diff options
| author | Florian Apolloner <florian@apolloner.eu> | 2013-12-30 14:58:49 -0800 |
|---|---|---|
| committer | Florian Apolloner <florian@apolloner.eu> | 2013-12-30 14:58:49 -0800 |
| commit | df075c74896b63ff39c250bb52a1f168265dfeee (patch) | |
| tree | 2885cce2922d8d6d23cacdde9f514b89d7413763 /django | |
| parent | 270f7e21676f043464e9a3e252fec0a63e3c0b2a (diff) | |
| parent | bfe9052831c6d7ad7501b71c884525b3b471eebc (diff) | |
Merge pull request #2126 from apollo13/email_bytes
Many thanks to @bitdancer and @aaugustin for answering my stupid questions about (mail)encodings and pointing me in the right direction.
Diffstat (limited to 'django')
| -rw-r--r-- | django/core/mail/backends/console.py | 15 | ||||
| -rw-r--r-- | django/core/mail/backends/filebased.py | 7 | ||||
| -rw-r--r-- | django/core/mail/backends/smtp.py | 5 | ||||
| -rw-r--r-- | django/core/mail/message.py | 33 |
4 files changed, 37 insertions, 23 deletions
diff --git a/django/core/mail/backends/console.py b/django/core/mail/backends/console.py index d0ecac74ea..0ce88534ea 100644 --- a/django/core/mail/backends/console.py +++ b/django/core/mail/backends/console.py @@ -5,6 +5,7 @@ import sys import threading from django.core.mail.backends.base import BaseEmailBackend +from django.utils import six class EmailBackend(BaseEmailBackend): @@ -13,6 +14,16 @@ class EmailBackend(BaseEmailBackend): self._lock = threading.RLock() super(EmailBackend, self).__init__(*args, **kwargs) + def write_message(self, message): + msg = message.message() + msg_data = msg.as_bytes() + if six.PY3: + charset = msg.get_charset().get_output_charset() if msg.get_charset() else 'utf-8' + msg_data = msg_data.decode(charset) + self.stream.write('%s\n' % msg_data) + self.stream.write('-' * 79) + self.stream.write('\n') + def send_messages(self, email_messages): """Write all messages to the stream in a thread-safe way.""" if not email_messages: @@ -22,9 +33,7 @@ class EmailBackend(BaseEmailBackend): try: stream_created = self.open() for message in email_messages: - self.stream.write('%s\n' % message.message().as_string()) - self.stream.write('-' * 79) - self.stream.write('\n') + self.write_message(message) self.stream.flush() # flush after each message msg_count += 1 if stream_created: diff --git a/django/core/mail/backends/filebased.py b/django/core/mail/backends/filebased.py index 3f26551dab..5caedd5802 100644 --- a/django/core/mail/backends/filebased.py +++ b/django/core/mail/backends/filebased.py @@ -38,6 +38,11 @@ class EmailBackend(ConsoleEmailBackend): kwargs['stream'] = None super(EmailBackend, self).__init__(*args, **kwargs) + def write_message(self, message): + self.stream.write(message.message().as_bytes() + b'\n') + self.stream.write(b'-' * 79) + self.stream.write(b'\n') + def _get_filename(self): """Return a unique file name.""" if self._fname is None: @@ -48,7 +53,7 @@ class EmailBackend(ConsoleEmailBackend): def open(self): if self.stream is None: - self.stream = open(self._get_filename(), 'a') + self.stream = open(self._get_filename(), 'ab') return True return False diff --git a/django/core/mail/backends/smtp.py b/django/core/mail/backends/smtp.py index c9e0a18728..e72e372ca9 100644 --- a/django/core/mail/backends/smtp.py +++ b/django/core/mail/backends/smtp.py @@ -7,7 +7,6 @@ from django.conf import settings from django.core.mail.backends.base import BaseEmailBackend from django.core.mail.utils import DNS_NAME from django.core.mail.message import sanitize_address -from django.utils.encoding import force_bytes class EmailBackend(BaseEmailBackend): @@ -111,10 +110,8 @@ class EmailBackend(BaseEmailBackend): recipients = [sanitize_address(addr, email_message.encoding) for addr in email_message.recipients()] message = email_message.message() - charset = message.get_charset().get_output_charset() if message.get_charset() else 'utf-8' try: - self.connection.sendmail(from_email, recipients, - force_bytes(message.as_string(), charset)) + self.connection.sendmail(from_email, recipients, message.as_bytes()) except smtplib.SMTPException: if not self.fail_silently: raise diff --git a/django/core/mail/message.py b/django/core/mail/message.py index cde37ea6d2..cdd265521b 100644 --- a/django/core/mail/message.py +++ b/django/core/mail/message.py @@ -131,21 +131,25 @@ class MIMEMixin(): This overrides the default as_string() implementation to not mangle lines that begin with 'From '. See bug #13433 for details. """ - # 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.StringIO() + g = generator.Generator(fp, mangle_from_=False) + g.flatten(self, unixfrom=unixfrom) + return fp.getvalue() + + if six.PY2: + as_bytes = as_string + else: + def as_bytes(self, unixfrom=False): + """Return the entire formatted message as bytes. + Optional `unixfrom' when True, means include the Unix From_ envelope + header. + + This overrides the default as_bytes() implementation to not mangle + lines that begin with 'From '. See bug #13433 for details. + """ 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() @@ -167,9 +171,8 @@ class SafeMIMEText(MIMEMixin, MIMEText): # 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): + # Workaround for versions without http://bugs.python.org/issue19063 + if (3, 2) < sys.version_info < (3, 3, 4): payload = text.encode(utf8_charset.output_charset) self._payload = payload.decode('ascii', 'surrogateescape') self.set_charset(utf8_charset) |
