handoff fixes

This commit is contained in:
debu-2 2026-10-06 02:44:54 +05:30
parent 6c52cd19cb
commit 89ddebdb60
15 changed files with 991 additions and 271 deletions

View file

@ -1,16 +1,33 @@
import email.policy
import email.utils
from email.message import EmailMessage
from email.message import EmailMessage, Message
from email.mime.base import MIMEBase
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
import aiosmtplib
import dkim
from app.config import get_settings
from app.models import MailDomain
from app.services.mime_body_extractor import ExtractedMimePart
SMTP_POLICY = email.policy.SMTP.clone(max_line_length=998)
def _mime_attachment(part: ExtractedMimePart) -> MIMEBase:
maintype, _, subtype = part.content_type.partition("/")
if not subtype:
maintype, subtype = "application", "octet-stream"
mime = MIMEBase(maintype, subtype, policy=SMTP_POLICY)
mime.set_payload(part.payload)
email.utils.encode_base64(mime)
mime.add_header("Content-Disposition", part.disposition, filename=part.filename)
if part.content_id:
mime.add_header("Content-ID", f"<{part.content_id}>")
return mime
def build_message(
*,
sender: str,
@ -23,7 +40,47 @@ def build_message(
in_reply_to: str | None = None,
references: list[str] | None = None,
message_id: str | None = None,
) -> EmailMessage:
inline_parts: list[ExtractedMimePart] | None = None,
file_attachments: list[ExtractedMimePart] | None = None,
) -> Message:
inline_parts = inline_parts or []
file_attachments = file_attachments or []
if inline_parts or file_attachments:
root = MIMEMultipart("mixed", policy=SMTP_POLICY)
root["From"] = sender
root["To"] = ", ".join(recipients)
if cc:
root["Cc"] = ", ".join(cc)
if reply_to:
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])
root["Message-ID"] = generated_id
if in_reply_to:
root["In-Reply-To"] = in_reply_to
if references:
root["References"] = " ".join(references)
alternative = MIMEMultipart("alternative", policy=SMTP_POLICY)
alternative.attach(MIMEText(body_text, "plain", "utf-8", policy=SMTP_POLICY))
if body_html:
if inline_parts:
related = MIMEMultipart("related", policy=SMTP_POLICY)
related.attach(MIMEText(body_html, "html", "utf-8", policy=SMTP_POLICY))
for part in inline_parts:
related.attach(_mime_attachment(part))
alternative.attach(related)
else:
alternative.attach(MIMEText(body_html, "html", "utf-8", policy=SMTP_POLICY))
root.attach(alternative)
for attachment in file_attachments:
root.attach(_mime_attachment(attachment))
return root
message = EmailMessage(policy=SMTP_POLICY)
message["From"] = sender
message["To"] = ", ".join(recipients)
@ -45,7 +102,7 @@ def build_message(
return message
def sign_message(message: EmailMessage, domain: MailDomain) -> bytes:
def sign_message(message: Message, domain: MailDomain) -> bytes:
raw_message = message.as_bytes(policy=SMTP_POLICY)
signed_headers = [
b"from",
@ -106,6 +163,8 @@ async def deliver_email(
in_reply_to: str | None = None,
references: list[str] | None = None,
message_id: str | None = None,
inline_parts: list[ExtractedMimePart] | None = None,
file_attachments: list[ExtractedMimePart] | None = None,
) -> str:
message = build_message(
sender=sender,
@ -118,6 +177,8 @@ async def deliver_email(
in_reply_to=in_reply_to,
references=references,
message_id=message_id,
inline_parts=inline_parts,
file_attachments=file_attachments,
)
signed = sign_message(message, domain)
await send_via_smtp(