diff --git a/Lib/email/charset.py b/Lib/email/charset.py --- a/Lib/email/charset.py +++ b/Lib/email/charset.py @@ -390,7 +390,9 @@ if self.body_encoding is BASE64: if isinstance(string, str): string = string.encode(self.output_charset) - return email.base64mime.body_encode(string) + cteinput = b'\r\n'.join(string.splitlines()) + ( + b'\r\n' if string[-1] in b'\r\n' else b'') + return email.base64mime.body_encode(cteinput) elif self.body_encoding is QP: return email.quoprimime.body_encode(string) else: diff --git a/Lib/email/test/test_email.py b/Lib/email/test/test_email.py --- a/Lib/email/test/test_email.py +++ b/Lib/email/test/test_email.py @@ -3304,7 +3304,7 @@ Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 - 0JTQsCwg0L7QvdC4INC70LXRgtGP0YIuCg== + 0JTQsCwg0L7QvdC4INC70LXRgtGP0YIuDQo= """) def test_generator_handles_8bit(self): @@ -3920,6 +3920,40 @@ c = Charset('fake') eq('hello world', c.body_encode('hello world')) + def test_base64_body_encode_normalizes_newlines(self): + # issue #975330. + c = Charset('utf-8') + self.assertEqual( + email.base64mime.decode(c.body_encode('hello\n world')), + b'hello\r\n world') + self.assertEqual( + email.base64mime.decode(c.body_encode('hello\n world\n')), + b'hello\r\n world\r\n') + + def test_base64_body_encode_normalizes_os9_linesep(self): + # issue #975330. + c = Charset('utf-8') + self.assertEqual( + email.base64mime.decode(c.body_encode('hello\r world')), + b'hello\r\n world') + self.assertEqual( + email.base64mime.decode(c.body_encode('hello\r world\r')), + b'hello\r\n world\r\n') + + def test_base64_body_encode_normalizes_mixed_linesep(self): + # issue #975330. + c = Charset('utf-8') + self.assertEqual( + email.base64mime.decode(c.body_encode('hello\rmy\r\nworld\n')), + b'hello\r\nmy\r\nworld\r\n') + + def test_base64_body_encode_lack_of_final_linsep_preserved(self): + # issue #975330. + c = Charset('utf-8') + self.assertEqual( + email.base64mime.decode(c.body_encode('hello\rmy\r\nworld')), + b'hello\r\nmy\r\nworld') + def test_unicode_charset_name(self): charset = Charset('us-ascii') self.assertEqual(str(charset), 'us-ascii') diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -67,6 +67,10 @@ Library ------- +- Issue #975330: when email uses base64mime to encode the text of a message + because of its charset, it now normalizes any line endings to the RFC + standard `\r\n` endings before doing the encoding. + - Issue #14443: Tell rpmbuild to use the correct version of Python in bdist_rpm. Initial patch by Ross Lagerwall.