60 lines
2.4 KiB
Python
60 lines
2.4 KiB
Python
"""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")
|