From 09584bd33578b0f1ea7f173d06dbe2532336a7b1 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Mon, 30 May 2022 02:42:10 +0200 Subject: [PATCH] emsmdb, zcore: perform dot-stuffing ahead of SMTP DATA Certain lines in a mail have special meaning to certain components in the chain, such as lines beginning with "From " in the Unix mbox format, or lines beginning with a "." in a SMTP DATA command. When regular mail is prepared for export, MIME::write_content always applies a transform, and that is base64 or, (since recently) alternatively, quoted-printable. The base64 transform naturally "defuses" lines since neither "From " nor "." are possible with the base64 output alphabet. The QP encoder specifically looks for the special pattern and force-encodes them. By doing all that, no SMTP dot-stuffing would be needed. However, S/MIME is not classified as regular mail and would be copied verbatim to the SMTP channel, which is incorrect. Change the send routines to explicitly do SMTP-style dot-stuffing. References: GXF-30, GXL-84 --- exch/emsmdb/common_util.cpp | 6 ++++++ exch/zcore/common_util.cpp | 6 ++++++ lib/email/mail.cpp | 6 +++--- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/exch/emsmdb/common_util.cpp b/exch/emsmdb/common_util.cpp index 5609e5711..3666fd7d3 100644 --- a/exch/emsmdb/common_util.cpp +++ b/exch/emsmdb/common_util.cpp @@ -1676,6 +1676,12 @@ BOOL common_util_send_mail(MAIL *pmail, char last_command[1024]; char last_response[1024]; + MAIL dot_encoded(pmail->pmime_pool); + if (pmail->check_dot()) { + if (!pmail->transfer_dot(&dot_encoded, true)) + return false; + pmail = &dot_encoded; + } int sockd = gx_inet_connect(g_smtp_ip, g_smtp_port, 0); if (sockd < 0) { log_err("Cannot connect to SMTP server [%s]:%hu: %s", diff --git a/exch/zcore/common_util.cpp b/exch/zcore/common_util.cpp index 58956127a..64449cea7 100644 --- a/exch/zcore/common_util.cpp +++ b/exch/zcore/common_util.cpp @@ -1360,6 +1360,12 @@ static BOOL common_util_send_mail(MAIL *pmail, char last_command[1024]; char last_response[1024]; + MAIL dot_encoded(pmail->pmime_pool); + if (pmail->check_dot()) { + if (!pmail->transfer_dot(&dot_encoded, true)) + return false; + pmail = &dot_encoded; + } int sockd = gx_inet_connect(g_smtp_ip, g_smtp_port, 0); if (sockd < 0) { log_err("Cannot connect to SMTP server [%s]:%hu: %s", diff --git a/lib/email/mail.cpp b/lib/email/mail.cpp index e3382a7ce..7167adcb0 100644 --- a/lib/email/mail.cpp +++ b/lib/email/mail.cpp @@ -827,12 +827,12 @@ bool MAIL::dup(MAIL *pmail_dst) } /* - * apply or reverse-apply dot-stuffing mail object into a clean object + * add or remove dot-stuffing; copies into a clean object * @param * pmail_src [in] mail source object * pmail_dst [in, out] mail destination object */ -bool MAIL::transfer_dot(MAIL *pmail_dst, bool fwd) +bool MAIL::transfer_dot(MAIL *pmail_dst, bool add_dot) { auto pmail_src = this; unsigned int size; @@ -866,7 +866,7 @@ bool MAIL::transfer_dot(MAIL *pmail_dst, bool fwd) size ++; pbuff[offset + size] = '\n'; size ++; - if (fwd) { + if (add_dot) { if (pbuff[offset] == '.') { memmove(&pbuff[offset+1], &pbuff[offset], size); ++size;