New submission from Douglas Thor :
It appears that the SMTP EmailPolicy object does not correctly set
max_line_length.
RFC 2045 (https://www.ietf.org/rfc/rfc2045.txt) requires a max_line_length of
76 characters, while email._policybase.Policy sets it to 78 (which typically is
correct).
This causes email attachments to be truncated/corrupted.
While the workaround is quite trivial, debugging the root cause was not as
easy. Thus I think this should be fixed in at the std lib level, or at the very
least mentioned in the docs.
This was tested on Python 3.5.2. I did not test on 3.7, but I did check the
source code and it appears that the bug still exists.
To reproduce:
import smtplib
from email.message import EmailMessage
from email.policy import SMTP
msg = EmailMessage()
msg['Subject'] = "Test message"
msg['To'] = "to@valid_address.com"
msg['From'] = "from@valid_address.com"
content = "hello world, I should have an attachment"
msg.set_content(content)
maintype = 'image'
subtype = 'png'
test_file = './aaa.png'
with open(test_file, 'rb') as fp:
data = fp.read()
msg.add_attachment(data,
maintype=maintype,
subtype=subtype,
filename='aaa.png')
with smtplib.SMTP_SSL('smtp.address.com', port=465) as s:
s.ehlo()
user = 'smtp_user@valid_address.com'
pw = 'smtp_password'
s.login(user, pw)
s.send_message(msg)
Check the raw email message received. You'll see that lines have a length of 78
and are padded with "==" which makes the total length 80 chars:
...
MIME-Version: 1.0
Content-Type: multipart/mixed;
boundary="===1585876390557366757=="
--===1585876390557366757==
Content-Type: text/plain; charset="utf-8"
Content-Transfer-Encoding: 7bit
hello world, I should have an attachment
--===1585876390557366757==
Content-Type: image/png
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="aaa.png"
MIME-Version: 1.0
iVBORw0KGgoNSUhEUgAABE0AAALFCAY2rB2uAXNSR0IArs4c6QRnQU1BAACxjw==
C/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAD/jklEQVR4Xg==
7P1rsHVJWecBvl4RFFAuIpcCEYQuLkUDBcgBoQsULLnJXaoaEApe5FLSTVFUC4JACQ1NiQdsQoFBAQ==
iW4aQSWEt4cQwwB6xqC+CPYHqX5jQno+jHyYCCMmZsKJmYjZs3/rnOe8uXNnrpW5LrlzrfVfVSfOeQ==
986Vl/+T678y//nkk9+3OXdu+78uISAEhIAQEAJCQAgIASEgBISAEBACQkAICIEdBBBN9CMM1AfUBw==
...
Next, modify the code with:
from email.policy import SMTP
smtp_pol = SMTP.clone(max_line_length=76)
msg = EmailMessage(policy=smtp_pol)
msg['Subject'] = ...
And check the raw email again. This time, lines are 76 chars long and have no
padding. Data is the same, just wrapped differently as expected.
...
MIME-Version: 1.0
Content-Type: multipart/mixed;
boundary="===4874323426669347622=="
--===4874323426669347622==
Content-Type: text/plain; charset="utf-8"
Content-Transfer-Encoding: 7bit
hello world, I should have an attachment
--===4874323426669347622==
Content-Type: image/png
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="aaa.png"
MIME-Version: 1.0
iVBORw0KGgoNSUhEUgAABE0AAALFCAY2rB2uAXNSR0IArs4c6QRnQU1BAACx
jwv8YQUgY0hSTQAAeiYAAICEAAD6gOgAAHUwAADqYAAAOpgAABdwnLpRPAAA/45JREFU
eF7s/WuwdUlZ5wG+XhEUUC4ilwIRhC4uRQMFyAGhCxQsucldqhoQCl7kUtJNUVQLgkAJDU2JB2xC
gUEBiW4aQSWEt4cQwwB6xqC+CPYHqX5jQno+jHyYCCMmZsKJmYjZs3/rnOe8uXNnrpW5LrlzrfVf
...
This fix *should* be extremely easy:
diff --git "a/policy.py" "b/policy.py"
index 6ac64a5..046b788 100644
--- "a/policy.py"
+++ "b/policy.py"
@@ -209,6 +209,6 @@ default = EmailPolicy()
# Make the default policy use the class default header_factory
del default.header_factory
strict = default.clone(raise_on_defect=True)
-SMTP = default.clone(linesep='\r\n')
+SMTP = default.clone(linesep='\r\n', max_line_length=76)
HTTP = default.clone(linesep='\r\n', max_line_length=None)
SMTPUTF8 = SMTP.clone(utf8=True)
--
components: email
messages: 320898
nosy: Douglas Thor, barry, r.david.murray
priority: normal
severity: normal
status: open
title: SMTP EmailPolicy not setting max_line_length as expected. RCF 2045
states 76 char, Default policy uses 78
type: behavior
versions: Python 3.5
___
Python tracker
<https://bugs.python.org/issue34025>
___
___
Python-bugs-list mailing list
Unsubscribe:
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com