From ed167e53a52af22a8dce229696184b0d87a88a78 Mon Sep 17 00:00:00 2001 From: Florian Apolloner Date: Sat, 28 Dec 2013 15:24:25 +0100 Subject: [PATCH] [1.6.x] Worked around a bug in python 3.3.3. Refs #21093 Backport of 280c1a65ccacd679bf298bf2b169ff01e7266b8e from master. --- django/core/mail/message.py | 22 ++++++++++++++++++++-- tests/mail/tests.py | 4 ++-- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/django/core/mail/message.py b/django/core/mail/message.py index 41de859ee1..3450ecf6e0 100644 --- a/django/core/mail/message.py +++ b/django/core/mail/message.py @@ -21,7 +21,9 @@ from django.utils import six # Don't BASE64-encode UTF-8 messages so that we avoid unwanted attention from # some spam filters. -Charset.add_charset('utf-8', Charset.SHORTEST, None, 'utf-8') +utf8_charset = Charset.Charset('utf-8') +utf8_charset.body_encoding = None # Python defaults to BASE64 + # Default MIME type to use on attachments (if it is not explicitly given # and cannot be guessed). @@ -150,7 +152,23 @@ class SafeMIMEText(MIMEMixin, MIMEText): def __init__(self, text, subtype, charset): self.encoding = charset - MIMEText.__init__(self, text, subtype, charset) + if charset == 'utf-8': + # Unfortunately, Python doesn't support setting a Charset instance + # as MIMEText init parameter (http://bugs.python.org/issue16324). + # We do it manually and trigger re-encoding of the payload. + MIMEText.__init__(self, text, subtype, None) + del self['Content-Transfer-Encoding'] + # Work around a bug in python 3.3.3 [sic], see + # http://bugs.python.org/issue19063 for details. + if sys.version_info[:3] == (3, 3, 3): + payload = text.encode(utf8_charset.output_charset) + self._payload = payload.decode('ascii', 'surrogateescape') + self.set_charset(utf8_charset) + else: + self.set_payload(text, utf8_charset) + self.replace_header('Content-Type', 'text/%s; charset="%s"' % (subtype, charset)) + else: + MIMEText.__init__(self, text, subtype, charset) def __setitem__(self, name, val): name, val = forbid_multi_line_headers(name, val, self.encoding) diff --git a/tests/mail/tests.py b/tests/mail/tests.py index c90dc7e22a..01dbeb01e0 100644 --- a/tests/mail/tests.py +++ b/tests/mail/tests.py @@ -460,7 +460,7 @@ class BaseEmailBackendTests(object): email = EmailMessage('Subject', 'Content', 'from@example.com', ['to@example.com'], cc=['cc@example.com']) mail.get_connection().send_messages([email]) message = self.get_the_message() - self.assertStartsWith(message.as_string(), 'Content-Type: text/plain; charset="utf-8"\nMIME-Version: 1.0\nContent-Transfer-Encoding: 7bit\nSubject: Subject\nFrom: from@example.com\nTo: to@example.com\nCc: cc@example.com\nDate: ') + self.assertStartsWith(message.as_string(), 'MIME-Version: 1.0\nContent-Type: text/plain; charset="utf-8"\nContent-Transfer-Encoding: 7bit\nSubject: Subject\nFrom: from@example.com\nTo: to@example.com\nCc: cc@example.com\nDate: ') def test_idn_send(self): """ @@ -618,7 +618,7 @@ class ConsoleBackendTests(BaseEmailBackendTests, TestCase): s = StringIO() connection = mail.get_connection('django.core.mail.backends.console.EmailBackend', stream=s) send_mail('Subject', 'Content', 'from@example.com', ['to@example.com'], connection=connection) - self.assertTrue(s.getvalue().startswith('Content-Type: text/plain; charset="utf-8"\nMIME-Version: 1.0\nContent-Transfer-Encoding: 7bit\nSubject: Subject\nFrom: from@example.com\nTo: to@example.com\nDate: ')) + self.assertTrue(s.getvalue().startswith('MIME-Version: 1.0\nContent-Type: text/plain; charset="utf-8"\nContent-Transfer-Encoding: 7bit\nSubject: Subject\nFrom: from@example.com\nTo: to@example.com\nDate: ')) class FakeSMTPServer(smtpd.SMTPServer, threading.Thread):