Loading django/core/mail/backends/smtp.py +1 −1 Original line number Diff line number Diff line Loading @@ -120,7 +120,7 @@ class EmailBackend(BaseEmailBackend): for addr in email_message.recipients()] message = email_message.message() try: self.connection.sendmail(from_email, recipients, message.as_bytes()) self.connection.sendmail(from_email, recipients, message.as_bytes(linesep='\r\n')) except smtplib.SMTPException: if not self.fail_silently: raise Loading django/core/mail/message.py +7 −4 Original line number Diff line number Diff line Loading @@ -123,7 +123,7 @@ def sanitize_address(addr, encoding): class MIMEMixin(): def as_string(self, unixfrom=False): def as_string(self, unixfrom=False, linesep='\n'): """Return the entire formatted message as a string. Optional `unixfrom' when True, means include the Unix From_ envelope header. Loading @@ -133,13 +133,16 @@ class MIMEMixin(): """ fp = six.StringIO() g = generator.Generator(fp, mangle_from_=False) if six.PY2: g.flatten(self, unixfrom=unixfrom) else: g.flatten(self, unixfrom=unixfrom, linesep=linesep) return fp.getvalue() if six.PY2: as_bytes = as_string else: def as_bytes(self, unixfrom=False): def as_bytes(self, unixfrom=False, linesep='\n'): """Return the entire formatted message as bytes. Optional `unixfrom' when True, means include the Unix From_ envelope header. Loading @@ -149,7 +152,7 @@ class MIMEMixin(): """ fp = six.BytesIO() g = generator.BytesGenerator(fp, mangle_from_=False) g.flatten(self, unixfrom=unixfrom) g.flatten(self, unixfrom=unixfrom, linesep=linesep) return fp.getvalue() Loading docs/releases/1.7.1.txt +2 −0 Original line number Diff line number Diff line Loading @@ -115,3 +115,5 @@ Bugfixes (:ticket:`23609`). * Fixed generic relations in ``ModelAdmin.list_filter`` (:ticket:`23616`). * Restored RFC compliance for the SMTP backend on Python 3 (:ticket:`23063`). tests/mail/tests.py +35 −1 Original line number Diff line number Diff line Loading @@ -9,7 +9,7 @@ import smtpd import sys import tempfile import threading from smtplib import SMTPException from smtplib import SMTPException, SMTP from ssl import SSLError from django.core import mail Loading Loading @@ -1038,3 +1038,37 @@ class SMTPBackendTests(BaseEmailBackendTests, SimpleTestCase): def test_email_timeout_override_settings(self): backend = smtp.EmailBackend() self.assertEqual(backend.timeout, 10) def test_email_msg_uses_crlf(self): """#23063 -- Test that RFC-compliant messages are sent over SMTP.""" send = SMTP.send try: smtp_messages = [] def mock_send(self, s): smtp_messages.append(s) return send(self, s) SMTP.send = mock_send email = EmailMessage('Subject', 'Content', 'from@example.com', ['to@example.com']) mail.get_connection().send_messages([email]) # Find the actual message msg = None for i, m in enumerate(smtp_messages): if m[:4] == 'data': msg = smtp_messages[i+1] break self.assertTrue(msg) if PY3: msg = msg.decode('utf-8') # Ensure that the message only contains CRLF and not combinations of CRLF, LF, and CR. msg = msg.replace('\r\n', '') self.assertNotIn('\r', msg) self.assertNotIn('\n', msg) finally: SMTP.send = send Loading
django/core/mail/backends/smtp.py +1 −1 Original line number Diff line number Diff line Loading @@ -120,7 +120,7 @@ class EmailBackend(BaseEmailBackend): for addr in email_message.recipients()] message = email_message.message() try: self.connection.sendmail(from_email, recipients, message.as_bytes()) self.connection.sendmail(from_email, recipients, message.as_bytes(linesep='\r\n')) except smtplib.SMTPException: if not self.fail_silently: raise Loading
django/core/mail/message.py +7 −4 Original line number Diff line number Diff line Loading @@ -123,7 +123,7 @@ def sanitize_address(addr, encoding): class MIMEMixin(): def as_string(self, unixfrom=False): def as_string(self, unixfrom=False, linesep='\n'): """Return the entire formatted message as a string. Optional `unixfrom' when True, means include the Unix From_ envelope header. Loading @@ -133,13 +133,16 @@ class MIMEMixin(): """ fp = six.StringIO() g = generator.Generator(fp, mangle_from_=False) if six.PY2: g.flatten(self, unixfrom=unixfrom) else: g.flatten(self, unixfrom=unixfrom, linesep=linesep) return fp.getvalue() if six.PY2: as_bytes = as_string else: def as_bytes(self, unixfrom=False): def as_bytes(self, unixfrom=False, linesep='\n'): """Return the entire formatted message as bytes. Optional `unixfrom' when True, means include the Unix From_ envelope header. Loading @@ -149,7 +152,7 @@ class MIMEMixin(): """ fp = six.BytesIO() g = generator.BytesGenerator(fp, mangle_from_=False) g.flatten(self, unixfrom=unixfrom) g.flatten(self, unixfrom=unixfrom, linesep=linesep) return fp.getvalue() Loading
docs/releases/1.7.1.txt +2 −0 Original line number Diff line number Diff line Loading @@ -115,3 +115,5 @@ Bugfixes (:ticket:`23609`). * Fixed generic relations in ``ModelAdmin.list_filter`` (:ticket:`23616`). * Restored RFC compliance for the SMTP backend on Python 3 (:ticket:`23063`).
tests/mail/tests.py +35 −1 Original line number Diff line number Diff line Loading @@ -9,7 +9,7 @@ import smtpd import sys import tempfile import threading from smtplib import SMTPException from smtplib import SMTPException, SMTP from ssl import SSLError from django.core import mail Loading Loading @@ -1038,3 +1038,37 @@ class SMTPBackendTests(BaseEmailBackendTests, SimpleTestCase): def test_email_timeout_override_settings(self): backend = smtp.EmailBackend() self.assertEqual(backend.timeout, 10) def test_email_msg_uses_crlf(self): """#23063 -- Test that RFC-compliant messages are sent over SMTP.""" send = SMTP.send try: smtp_messages = [] def mock_send(self, s): smtp_messages.append(s) return send(self, s) SMTP.send = mock_send email = EmailMessage('Subject', 'Content', 'from@example.com', ['to@example.com']) mail.get_connection().send_messages([email]) # Find the actual message msg = None for i, m in enumerate(smtp_messages): if m[:4] == 'data': msg = smtp_messages[i+1] break self.assertTrue(msg) if PY3: msg = msg.decode('utf-8') # Ensure that the message only contains CRLF and not combinations of CRLF, LF, and CR. msg = msg.replace('\r\n', '') self.assertNotIn('\r', msg) self.assertNotIn('\n', msg) finally: SMTP.send = send