[PATCH] patchbomb: do not send bare LFs in emails

Antonio Muci a.mux at inwind.it
Wed Nov 13 21:38:08 UTC 2024


# HG changeset patch
# User Antonio Muci <a.mux at inwind.it>
# Date 1728298075 -7200
#      Mon Oct 07 12:47:55 2024 +0200
# Branch stable
# Node ID d1da72aa71c3dffc4a9002b413105dceed8d56ce
# Parent  124c944b71b293057649cb1983ee4a9e0d8eeb37
patchbomb: do not send bare LFs in emails

Before this change, on some systems, sending emails caused the following error:
    abort: (552, b'Message contains bare LF and is violating 822.bis section 2.3')

The reason is that Python's default email policy keeps compatibility with Python
3.2, and that version is not standards compliant.

The standard library contains a standard compliant email.policy.SMTP class. See
https://docs.python.org/3.13/library/email.policy.html#email.policy.SMTP
    > Suitable for serializing messages in conformance with the email RFCs. Like
    > default, but with linesep set to \r\n, which is RFC compliant.

The policy, however, needs to be explicitly opted in.

These changes should get rid of the above error when sending email and should be
future proof too.

Note that we also no longer need to explicitly pass mangle_from_=False, because
it is subsumed in the Policy object. See the documentation at
https://docs.python.org/3.13/library/email.generator.html#email.generator.Generator
    > *mangle_from_* defaults to the value of the mangle_from_ setting of the
    > policy (which is True for the compat32 policy and False for all others)

diff --git a/hgext/patchbomb.py b/hgext/patchbomb.py
--- a/hgext/patchbomb.py
+++ b/hgext/patchbomb.py
@@ -78,6 +78,7 @@ import email.encoders as emailencoders
 import email.mime.base as emimebase
 import email.mime.multipart as emimemultipart
 import email.utils as eutil
+import email.policy as epolicy
 import os
 import socket
 
@@ -985,7 +986,7 @@ def email(ui, repo, *revs, **opts):
         if opts.get(b'test'):
             ui.status(_(b'displaying '), subj, b' ...\n')
             ui.pager(b'email')
-            generator = mail.Generator(ui, mangle_from_=False)
+            generator = mail.Generator(ui, policy=epolicy.SMTP)
             try:
                 generator.flatten(m, False)
                 ui.write(b'\n')
@@ -1000,7 +1001,7 @@ def email(ui, repo, *revs, **opts):
                 # Exim does not remove the Bcc field
                 del m['Bcc']
             fp = stringio()
-            generator = mail.Generator(fp, mangle_from_=False)
+            generator = mail.Generator(fp, policy=epolicy.SMTP)
             generator.flatten(m, False)
             alldests = to + bcc + cc
             sendmail(sender_addr, alldests, fp.getvalue())


More information about the Mercurial-devel mailing list