feat(email_sending): introduce multi-tenant delivery system

This commit is contained in:
YuehuCao 2025-08-09 11:25:47 +08:00
parent 2f10275493
commit d164b6f567

View File

@ -2,7 +2,12 @@ from common.config.app_settings import app_settings
from sendgrid import SendGridAPIClient
from sendgrid.helpers.mail import Mail
from common.log.module_logger import ModuleLogger
from typing import List, Dict
import uuid
from datetime import datetime
from backend.models.models import EmailSendStatusDoc
from common.constants.email import EmailSendStatus
class EmailHandler:
def __init__(self) -> None:
@ -38,3 +43,83 @@ class EmailHandler:
)
except Exception as e:
await module_logger.log_exception(e)
async def send_tenant_email(
self,
tenant_id: str,
template_id: str,
recipient_email: str,
sender_emails: List[str],
subject_properties: Dict = {},
body_properties: Dict = {}
):
"""Send tenant email using specified senders"""
module_logger = ModuleLogger(sender_id="EmailHandler")
try:
email_id = str(uuid.uuid4())
from_email = sender_emails[0] if sender_emails else app_settings.EMAIL_FROM
subject = subject_properties.get("subject", "No Subject")
html_content = body_properties.get("html_content", "")
text_content = body_properties.get("text_content", "")
email_status_doc = EmailSendStatusDoc(
email_id=email_id,
tenant_id=tenant_id,
email_senders=sender_emails,
recipient_email=recipient_email,
template_id=template_id,
subject=subject,
body=html_content,
status=EmailSendStatus.SENDING
)
await email_status_doc.save()
mail = Mail(
from_email=from_email,
to_emails=recipient_email,
subject=subject,
html_content=html_content,
)
sg = SendGridAPIClient(app_settings.SENDGRID_API_KEY)
response = sg.send(mail)
email_status_doc.status = EmailSendStatus.SENT
email_status_doc.sent_at = datetime.utcnow()
email_status_doc.message_id = str(response.headers.get('X-Message-Id', ''))
await email_status_doc.save()
await module_logger.log_info(
f"Tenant email sent successfully",
properties={
"tenant_id": tenant_id,
"template_id": template_id,
"email_id": email_id,
"recipient_email": recipient_email,
"sender_email": from_email,
"status_code": response.status_code
}
)
return email_id
except Exception as e:
if 'email_status_doc' in locals():
email_status_doc.status = EmailSendStatus.FAILED
email_status_doc.failed_at = datetime.utcnow()
email_status_doc.error_message = str(e)
await email_status_doc.save()
await module_logger.log_error(
f"Failed to send tenant email",
properties={
"tenant_id": tenant_id,
"template_id": template_id,
"recipient_email": recipient_email,
"error": str(e)
}
)
raise