human hand off
This commit is contained in:
parent
d0fee5c8f7
commit
7af776196a
34 changed files with 2941 additions and 195 deletions
|
|
@ -16,6 +16,36 @@ from app.services.mime_body_extractor import ExtractedMimePart
|
|||
|
||||
SMTP_POLICY = email.policy.SMTP.clone(max_line_length=998)
|
||||
logger = logging.getLogger(__name__)
|
||||
SYSTEM_SENDER_LOCALS = {
|
||||
"invite",
|
||||
"invites",
|
||||
"notification",
|
||||
"notifications",
|
||||
"no-reply",
|
||||
"noreply",
|
||||
"support",
|
||||
}
|
||||
|
||||
|
||||
def _sender_identity(sender: str, sender_name: str | None = None) -> tuple[str, str]:
|
||||
"""Return an RFC-compliant From header and the bare SMTP envelope address."""
|
||||
if "\r" in sender or "\n" in sender or (sender_name and ("\r" in sender_name or "\n" in sender_name)):
|
||||
raise ValueError("Sender identity cannot contain line breaks.")
|
||||
|
||||
existing_name, address = email.utils.parseaddr(sender)
|
||||
address = address.strip().lower()
|
||||
if not address or "@" not in address:
|
||||
raise ValueError("A valid sender email address is required.")
|
||||
|
||||
display_name = (sender_name or existing_name).strip()
|
||||
if not display_name:
|
||||
local_part = address.split("@", 1)[0]
|
||||
if local_part in SYSTEM_SENDER_LOCALS:
|
||||
display_name = "aGentic Email"
|
||||
else:
|
||||
display_name = local_part.replace(".", " ").replace("_", " ").replace("-", " ").title()
|
||||
|
||||
return email.utils.formataddr((display_name, address), charset="utf-8"), address
|
||||
|
||||
|
||||
def log_outbound_mime_headers(message: Message) -> None:
|
||||
|
|
@ -62,6 +92,7 @@ def _mime_attachment(part: ExtractedMimePart) -> MIMEBase:
|
|||
def build_message(
|
||||
*,
|
||||
sender: str,
|
||||
sender_name: str | None = None,
|
||||
recipients: list[str],
|
||||
cc: list[str],
|
||||
subject: str,
|
||||
|
|
@ -76,10 +107,11 @@ def build_message(
|
|||
) -> Message:
|
||||
inline_parts = inline_parts or []
|
||||
file_attachments = file_attachments or []
|
||||
sender_header, sender_address = _sender_identity(sender, sender_name)
|
||||
|
||||
if inline_parts or file_attachments:
|
||||
root = MIMEMultipart("mixed", policy=SMTP_POLICY)
|
||||
root["From"] = sender
|
||||
root["From"] = sender_header
|
||||
root["To"] = ", ".join(recipients)
|
||||
if cc:
|
||||
root["Cc"] = ", ".join(cc)
|
||||
|
|
@ -87,7 +119,7 @@ def build_message(
|
|||
root["Reply-To"] = reply_to
|
||||
root["Subject"] = subject
|
||||
root["Date"] = email.utils.formatdate(localtime=True)
|
||||
generated_id = message_id or email.utils.make_msgid(domain=sender.split("@")[-1])
|
||||
generated_id = message_id or email.utils.make_msgid(domain=sender_address.split("@")[-1])
|
||||
root["Message-ID"] = generated_id
|
||||
if in_reply_to:
|
||||
root["In-Reply-To"] = in_reply_to
|
||||
|
|
@ -115,7 +147,7 @@ def build_message(
|
|||
return root
|
||||
|
||||
message = EmailMessage(policy=SMTP_POLICY)
|
||||
message["From"] = sender
|
||||
message["From"] = sender_header
|
||||
message["To"] = ", ".join(recipients)
|
||||
if cc:
|
||||
message["Cc"] = ", ".join(cc)
|
||||
|
|
@ -123,7 +155,7 @@ def build_message(
|
|||
message["Reply-To"] = reply_to
|
||||
message["Subject"] = subject
|
||||
message["Date"] = email.utils.formatdate(localtime=True)
|
||||
generated_id = message_id or email.utils.make_msgid(domain=sender.split("@")[-1])
|
||||
generated_id = message_id or email.utils.make_msgid(domain=sender_address.split("@")[-1])
|
||||
message["Message-ID"] = generated_id
|
||||
if in_reply_to:
|
||||
message["In-Reply-To"] = in_reply_to
|
||||
|
|
@ -191,6 +223,7 @@ async def send_via_smtp(
|
|||
async def deliver_email(
|
||||
*,
|
||||
sender: str,
|
||||
sender_name: str | None = None,
|
||||
recipients: list[str],
|
||||
cc: list[str],
|
||||
bcc: list[str],
|
||||
|
|
@ -205,8 +238,10 @@ async def deliver_email(
|
|||
inline_parts: list[ExtractedMimePart] | None = None,
|
||||
file_attachments: list[ExtractedMimePart] | None = None,
|
||||
) -> str:
|
||||
_, sender_address = _sender_identity(sender, sender_name)
|
||||
message = build_message(
|
||||
sender=sender,
|
||||
sender_name=sender_name,
|
||||
recipients=recipients,
|
||||
cc=cc,
|
||||
subject=subject,
|
||||
|
|
@ -224,7 +259,7 @@ async def deliver_email(
|
|||
log_signed_mime_headers(signed)
|
||||
await send_via_smtp(
|
||||
signed,
|
||||
sender=sender,
|
||||
sender=sender_address,
|
||||
recipients=[*recipients, *cc, *bcc],
|
||||
)
|
||||
return str(message["Message-ID"])
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue