handoff fixes
This commit is contained in:
parent
6c52cd19cb
commit
89ddebdb60
15 changed files with 991 additions and 271 deletions
|
|
@ -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(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue