diff options
| author | Florian Apolloner <florian@apolloner.eu> | 2013-12-28 12:40:10 +0100 |
|---|---|---|
| committer | Florian Apolloner <florian@apolloner.eu> | 2013-12-28 12:48:54 +0100 |
| commit | 35a447a263115b22a7040a9f4a16ff4bd2078466 (patch) | |
| tree | cb1653ad254bbf364c1d4fe6b08cd9ac23d4017c | |
| parent | 2d08390d70007236e083183d78a4435d249c5aa8 (diff) | |
[1.6.x] Fixed #21093 -- Ensured that mails are not base64 encoded on python 3.3.3+.
Thanks to Arfrever for the report and Aymeric for the review.
Backport of f28ea0230846c81e9b6725454bb3a10df24678aa from master.
| -rw-r--r-- | django/core/mail/message.py | 62 |
1 files changed, 30 insertions, 32 deletions
diff --git a/django/core/mail/message.py b/django/core/mail/message.py index a3b36df832..41de859ee1 100644 --- a/django/core/mail/message.py +++ b/django/core/mail/message.py @@ -5,8 +5,8 @@ import os import random import sys import time +from email import generator from email import charset as Charset, encoders as Encoders -from email.generator import Generator from email.mime.text import MIMEText from email.mime.multipart import MIMEMultipart from email.mime.base import MIMEBase @@ -119,16 +119,7 @@ def sanitize_address(addr, encoding): return formataddr((nm, addr)) -class SafeMIMEText(MIMEText): - - def __init__(self, text, subtype, charset): - self.encoding = charset - MIMEText.__init__(self, text, subtype, charset) - - def __setitem__(self, name, val): - name, val = forbid_multi_line_headers(name, val, self.encoding) - MIMEText.__setitem__(self, name, val) - +class MIMEMixin(): def as_string(self, unixfrom=False): """Return the entire formatted message as a string. Optional `unixfrom' when True, means include the Unix From_ envelope @@ -137,16 +128,36 @@ class SafeMIMEText(MIMEText): This overrides the default as_string() implementation to not mangle lines that begin with 'From '. See bug #13433 for details. """ - fp = six.StringIO() - g = Generator(fp, mangle_from_ = False) - if sys.version_info < (2, 6, 6) and isinstance(self._payload, six.text_type): - # Workaround for http://bugs.python.org/issue1368247 - self._payload = self._payload.encode(self._charset.output_charset) - g.flatten(self, unixfrom=unixfrom) - return fp.getvalue() + # Using a normal Generator on python 3 will yield a string, which will + # get base64 encoded in some cases to ensure that it's always convertable + # to ascii. We don't want base64 encoded emails, so we use a BytesGenertor + # which will do the right thing and then decode according to our known + # encoding. See #21093 and #3472 for details. + if six.PY3 and sys.version_info >= (3, 3, 3): + fp = six.BytesIO() + g = generator.BytesGenerator(fp, mangle_from_=False) + g.flatten(self, unixfrom=unixfrom) + encoding = self.get_charset().get_output_charset() if self.get_charset() else 'utf-8' + return fp.getvalue().decode(encoding) + else: + fp = six.StringIO() + g = generator.Generator(fp, mangle_from_=False) + g.flatten(self, unixfrom=unixfrom) + return fp.getvalue() -class SafeMIMEMultipart(MIMEMultipart): +class SafeMIMEText(MIMEMixin, MIMEText): + + def __init__(self, text, subtype, charset): + self.encoding = charset + MIMEText.__init__(self, text, subtype, charset) + + def __setitem__(self, name, val): + name, val = forbid_multi_line_headers(name, val, self.encoding) + MIMEText.__setitem__(self, name, val) + + +class SafeMIMEMultipart(MIMEMixin, MIMEMultipart): def __init__(self, _subtype='mixed', boundary=None, _subparts=None, encoding=None, **_params): self.encoding = encoding @@ -156,19 +167,6 @@ class SafeMIMEMultipart(MIMEMultipart): name, val = forbid_multi_line_headers(name, val, self.encoding) MIMEMultipart.__setitem__(self, name, val) - def as_string(self, unixfrom=False): - """Return the entire formatted message as a string. - Optional `unixfrom' when True, means include the Unix From_ envelope - header. - - This overrides the default as_string() implementation to not mangle - lines that begin with 'From '. See bug #13433 for details. - """ - fp = six.StringIO() - g = Generator(fp, mangle_from_ = False) - g.flatten(self, unixfrom=unixfrom) - return fp.getvalue() - class EmailMessage(object): """ |
