"""Mail sender via SMTP (Mailhog in dev).""" from __future__ import annotations import asyncio from email.message import EmailMessage import aiosmtplib from fastapi import APIRouter from core.config import settings from core.di import register_service router = APIRouter() class MailService: async def send(self, to: str, subject: str, body_html: str, body_text: str = "") -> None: msg = EmailMessage() msg["From"] = settings.MAIL_FROM msg["To"] = to msg["Subject"] = subject if body_text: msg.set_content(body_text) msg.add_alternative(body_html, subtype="html") else: msg.set_content(body_html, subtype="html") try: await aiosmtplib.send( msg, hostname=settings.SMTP_HOST, port=settings.SMTP_PORT, start_tls=False, ) except Exception as e: # noqa: BLE001 print(f"[mail] send error: {e}") def send_sync(self, to: str, subject: str, body_html: str, body_text: str = "") -> None: """Blocking wrapper for event handlers.""" try: asyncio.run(self.send(to, subject, body_html, body_text)) except RuntimeError: # inside running loop (unlikely in sync event handlers, but just in case) loop = asyncio.new_event_loop() try: loop.run_until_complete(self.send(to, subject, body_html, body_text)) finally: loop.close() def on_load() -> None: register_service("MailService", MailService())