diff -r e27684eed3b6 Lib/email/generator.py --- a/Lib/email/generator.py Tue Nov 26 19:24:01 2013 -0600 +++ b/Lib/email/generator.py Wed Nov 27 16:35:03 2013 +0800 @@ -14,6 +14,7 @@ from io import StringIO, BytesIO from email._policybase import compat32 +from email import message_from_bytes from email.header import Header from email.utils import _has_surrogates import email.charset as _charset @@ -225,9 +226,16 @@ if _has_surrogates(msg._payload): charset = msg.get_param('charset') if charset is not None: - del msg['content-transfer-encoding'] - msg.set_payload(payload, charset) - payload = msg.get_payload() + out = BytesIO() + BytesGenerator(out).flatten(msg) + copy_msg = message_from_bytes(out.getvalue()) + try: + # Downcast 8bit data to 7bit data + del msg['content-transfer-encoding'] + msg.set_payload(payload, charset) + payload = msg.get_payload() + finally: + msg = copy_msg if self._mangle_from_: payload = fcre.sub('>From ', payload) self._write_lines(payload) diff -r e27684eed3b6 Lib/test/test_email/test_email.py --- a/Lib/test/test_email/test_email.py Tue Nov 26 19:24:01 2013 -0600 +++ b/Lib/test/test_email/test_email.py Wed Nov 27 16:35:03 2013 +0800 @@ -3743,6 +3743,16 @@ email.generator.Generator(out).flatten(msg) self.assertEqual(out.getvalue(), self.non_latin_bin_msg_as7bit_wrapped) + def string_generator_should_not_mutate_message_when_handling_8bit(self): + msg = email.message_from_bytes(self.non_latin_bin_msg) + out = BytesIO() + BytesGenerator(out).flatten(msg) + orig_value = out.getvalue() + Generator(StringIO()).flatten(msg) + out = BytesIO() + BytesGenerator(out).flatten(msg) + self.assertEqual(out.getvalue(), orig_value) + def test_bytes_generator_with_unix_from(self): # The unixfrom contains a current date, so we can't check it # literally. Just make sure the first word is 'From' and the