Align the project baseline with the latest admin interface styling and layout structure while documenting setup and usage updates in README.
62 lines
1.7 KiB
Python
62 lines
1.7 KiB
Python
from __future__ import annotations
|
|
|
|
import smtplib
|
|
from dataclasses import dataclass
|
|
from email.message import EmailMessage
|
|
|
|
from app.core.config import settings
|
|
|
|
|
|
@dataclass
|
|
class SentEmail:
|
|
to: str
|
|
subject: str
|
|
body: str
|
|
template: str
|
|
|
|
|
|
class MemoryMailer:
|
|
def __init__(self) -> None:
|
|
self.sent: list[SentEmail] = []
|
|
|
|
def send(self, to: str, subject: str, body: str, template: str) -> None:
|
|
self.sent.append(SentEmail(to=to, subject=subject, body=body, template=template))
|
|
|
|
def clear(self) -> None:
|
|
self.sent.clear()
|
|
|
|
def latest_token(self, recipient: str, template: str) -> str | None:
|
|
for message in reversed(self.sent):
|
|
if message.to == recipient and message.template == template:
|
|
for line in message.body.splitlines():
|
|
if line.startswith("TOKEN:"):
|
|
return line.split(":", 1)[1].strip()
|
|
return None
|
|
|
|
|
|
class SmtpMailer:
|
|
def send(self, to: str, subject: str, body: str, template: str) -> None:
|
|
_ = template
|
|
message = EmailMessage()
|
|
message["From"] = settings.smtp_from
|
|
message["To"] = to
|
|
message["Subject"] = subject
|
|
message.set_content(body)
|
|
with smtplib.SMTP(settings.smtp_host, settings.smtp_port, timeout=10) as smtp:
|
|
if settings.smtp_user:
|
|
smtp.login(settings.smtp_user, settings.smtp_password)
|
|
smtp.send_message(message)
|
|
|
|
|
|
memory_mailer = MemoryMailer()
|
|
|
|
|
|
def get_mailer():
|
|
if settings.email_delivery_mode == "memory":
|
|
return memory_mailer
|
|
return SmtpMailer()
|
|
|
|
|
|
def send_template_email(to: str, template: str, subject: str, body: str) -> None:
|
|
get_mailer().send(to=to, subject=subject, body=body, template=template)
|