]> git.ipfire.org Git - thirdparty/rspamd.git/commitdiff
[Fix] Split MIME address lists on semicolons as well as commas
authorVsevolod Stakhov <vsevolod@rspamd.com>
Thu, 16 Jul 2026 11:28:23 +0000 (12:28 +0100)
committerVsevolod Stakhov <vsevolod@rspamd.com>
Thu, 16 Jul 2026 11:28:23 +0000 (12:28 +0100)
A semicolon is not an RFC 5322 address-list separator (it only
terminates a group construct), but Outlook-style ;-separated recipient
lists are pervasive in real mail and most MTAs (e.g. Postfix) split
them. Previously such a list was parsed as a single malformed address
whose local part swallowed the semicolon and the next address, breaking
recipient counts and producing false invalid-address signals.

Treat ';' exactly like ',' in the list parser. This mirrors the
existing comma behaviour in every edge case: semicolons inside quoted
strings are preserved, an unquoted semicolon in a display name drops
the preceding phrase just like a comma does, an empty group
(undisclosed-recipients:;) now yields no addresses like the comma
variant, and the trailing ';' of a group construct no longer leaks
into the last member's domain.

Issue: #6139

src/libmime/email_addr.c

index c3af21f9f2b8b65ff2a3e240793fc50c535a406f..fccf56d4839d40098183b43062030d7fc3ef181b 100644 (file)
@@ -376,7 +376,14 @@ rspamd_email_address_from_mime(rspamd_mempool_t *pool, const char *hdr,
                                c = p;
                                state = parse_addr;
                        }
-                       else if (*p == ',') {
+                       else if (*p == ',' || *p == ';') {
+                               /*
+                                * Semicolon is not an RFC 5322 list separator (it merely
+                                * terminates a group construct), but Outlook-style
+                                * `;'-separated address lists are pervasive in real mail and
+                                * are split by most MTAs, so treat it exactly like a comma;
+                                * a `;' inside a quoted string is handled by parse_quoted
+                                */
                                if (p > c && seen_at) {
                                        /*
                                         * Last token must be the address: