From f19265742cc682d964f27ac75ab85d43f7ad9070 Mon Sep 17 00:00:00 2001 From: Afonso Coutinho Date: Wed, 3 Jun 2026 06:23:58 +0100 Subject: [PATCH] fix: SMTP envelope recipients split on commas inside display names (#1464) --- routes/email_routes.py | 29 +++++++++++++++---------- tests/test_email_envelope_recipients.py | 26 ++++++++++++++++++++++ 2 files changed, 44 insertions(+), 11 deletions(-) create mode 100644 tests/test_email_envelope_recipients.py diff --git a/routes/email_routes.py b/routes/email_routes.py index 129be0a..e611a29 100644 --- a/routes/email_routes.py +++ b/routes/email_routes.py @@ -322,6 +322,20 @@ def _apply_odysseus_headers(msg, kind: str | None = None, ref_id: str | None = N msg["X-Odysseus-Ref"] = re.sub(r"[^A-Za-z0-9_.:-]", "-", ref_id)[:128] +def _envelope_recipients(*fields: str) -> list: + """Extract bare SMTP envelope addresses from one or more To/Cc/Bcc header + strings. A naive `field.split(",")` corrupts display names that contain a + comma (e.g. `"Smith, John" `, the canonical Outlook form): + it splits into `"Smith` and `John" `, breaking delivery. + email.utils.getaddresses parses the address grammar correctly.""" + out = [] + for _name, addr in email.utils.getaddresses([f for f in fields if f]): + addr = (addr or "").strip() + if addr: + out.append(addr) + return out + + def _md_to_email_html(text: str) -> str: """Render the compose markdown body to a SAFE HTML fragment for the email's text/html part. Everything is HTML-escaped FIRST (so a pasted