mirror of
https://github.com/django/django.git
synced 2025-10-27 23:56:08 +00:00
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.
This commit is contained in:
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user