"""Transactional email via AWS SES, with a console mock fallback.""" from typing import Optional from app.core.config import settings from app.models import EmailLog async def _log(to_email: str, subject: str, template: str, status: str = "sent", error: Optional[str] = None): try: await EmailLog(to_email=to_email, subject=subject, template=template, status=status, error=error).insert() except Exception: pass async def send_email(to_email: str, subject: str, body: str, template: str = "generic"): if settings.mock_email or not settings.ses_configured: print(f"\n[MOCK EMAIL] to={to_email} subject={subject}\n{body}\n") await _log(to_email, subject, template, status="mocked") return True try: import boto3 client = boto3.client( "ses", region_name=settings.aws_region, aws_access_key_id=settings.aws_access_key_id, aws_secret_access_key=settings.aws_secret_access_key, ) client.send_email( Source=settings.ses_from_email, Destination={"ToAddresses": [to_email]}, Message={"Subject": {"Data": subject}, "Body": {"Html": {"Data": body}}}, ) await _log(to_email, subject, template) return True except Exception as e: # noqa await _log(to_email, subject, template, status="failed", error=str(e)) return False async def send_verification_email(to_email: str, name: str, token: str, code: str = ""): link = f"{settings.frontend_url}/verify-email?token={token}" body = (f"Hi {name},\n\n" f"Your VerifyPack verification code is: {code}\n\n" f"Or click this link to verify: {link}\n\n" f"This code expires in 30 minutes.") await send_email(to_email, "Verify your VerifyPack email", body, "verify_email") async def send_reset_email(to_email: str, name: str, token: str): link = f"{settings.frontend_url}/reset-password?token={token}" await send_email(to_email, "Reset your VerifyPack password", f"Hi {name}, reset your password: {link}", "reset_password") async def send_invite_email(to_email: str, org_name: str, token: str): link = f"{settings.frontend_url}/signup?invite={token}" await send_email(to_email, f"You're invited to {org_name} on VerifyPack", f"Join {org_name}: {link}", "invite")