From d164b6f5673106459aec8456acb5771922d99605 Mon Sep 17 00:00:00 2001 From: YuehuCao Date: Sat, 9 Aug 2025 11:25:47 +0800 Subject: [PATCH] feat(email_sending): introduce multi-tenant delivery system --- .../backend/infra/email_handler.py | 85 +++++++++++++++++++ 1 file changed, 85 insertions(+) diff --git a/apps/notification/backend/infra/email_handler.py b/apps/notification/backend/infra/email_handler.py index 03908b3..2c70ce5 100644 --- a/apps/notification/backend/infra/email_handler.py +++ b/apps/notification/backend/infra/email_handler.py @@ -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