New submission from Douglas Thor <doug.t...@gmail.com>:
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 iVBORw0KGgoAAAANSUhEUgAABE0AAALFCAYAAAA2rB2uAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjw== 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 iVBORw0KGgoAAAANSUhEUgAABE0AAALFCAYAAAA2rB2uAAAAAXNSR0IArs4c6QAAAARnQU1BAACx jwv8YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAA/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 <rep...@bugs.python.org> <https://bugs.python.org/issue34025> _______________________________________ _______________________________________________ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com