"""SMTP mailer using the standard library, run off the event loop. Configured entirely from settings (host/port/credentials/from).""" import asyncio import smtplib from email.message import EmailMessage from app.core.config import Settings from app.integrations.mailer.base import Mailer class SMTPMailer(Mailer): def __init__(self, settings: Settings) -> None: self.settings = settings def _send(self, *, to: str, subject: str, body: str) -> None: msg = EmailMessage() msg["From"] = self.settings.smtp_from msg["To"] = to msg["Subject"] = subject msg.set_content(body) with smtplib.SMTP(self.settings.smtp_host, self.settings.smtp_port) as smtp: smtp.starttls() if self.settings.smtp_username and self.settings.smtp_password: smtp.login(self.settings.smtp_username, self.settings.smtp_password) smtp.send_message(msg) async def _send_async(self, *, to: str, subject: str, body: str) -> None: await asyncio.to_thread(self._send, to=to, subject=subject, body=body) async def send_email_verification(self, *, to: str, link: str) -> None: await self._send_async( to=to, subject="Verify your Provenance email", body=f"Confirm your email address:\n\n{link}\n", ) async def send_password_reset(self, *, to: str, link: str) -> None: await self._send_async( to=to, subject="Reset your Provenance password", body=f"Reset your password:\n\n{link}\n", )