import logging from email.message import EmailMessage import aiosmtplib from app.config.settings import settings logger = logging.getLogger(__name__) class EmailDeliveryError(Exception): pass class EmailService: async def send_verification_email(self, email: str, token: str) -> None: verify_link = f"{settings.frontend_base_url}/verify-email?token={token}" subject = "Verify your BenyaMessenger account" text = ( "Welcome to BenyaMessenger.\n\n" f"Verify your email by opening this link:\n{verify_link}\n\n" "If you did not create this account, ignore this email." ) html = ( "

Welcome to BenyaMessenger.

" f"

Verify your email by opening this link:
{verify_link}

" "

If you did not create this account, ignore this email.

" ) await self._send_email(email, subject, text, html) async def send_password_reset_email(self, email: str, token: str) -> None: reset_link = f"{settings.frontend_base_url}/reset-password?token={token}" subject = "Reset your BenyaMessenger password" text = ( "Password reset request.\n\n" f"Open this link to reset your password:\n{reset_link}\n\n" "If you did not request this, ignore this email." ) html = ( "

Password reset request.

" f"

Open this link to reset your password:
{reset_link}

" "

If you did not request this, ignore this email.

" ) await self._send_email(email, subject, text, html) async def _send_email(self, recipient: str, subject: str, text: str, html: str) -> None: if settings.email_provider.lower() != "smtp": logger.info("EMAIL to=%s subject=%s body=%s", recipient, subject, text) return message = EmailMessage() message["From"] = settings.smtp_from_email message["To"] = recipient message["Subject"] = subject message.set_content(text) message.add_alternative(html, subtype="html") try: await aiosmtplib.send( message, hostname=settings.smtp_host, port=settings.smtp_port, username=settings.smtp_username or None, password=settings.smtp_password or None, start_tls=settings.smtp_use_tls, use_tls=settings.smtp_use_ssl, timeout=settings.smtp_timeout_seconds, ) except Exception as exc: logger.exception("SMTP delivery failed to=%s subject=%s", recipient, subject) raise EmailDeliveryError("Email delivery failed") from exc def get_email_service() -> EmailService: return EmailService()