Fixed #22561 -- Prevented too long lines in email messages
Thanks NotSqrt for the excellent report and Tim Graham for the review.
This commit is contained in:
parent
f43da05cc5
commit
836d475afe
|
@ -25,11 +25,15 @@ from django.utils.encoding import force_text
|
||||||
# some spam filters.
|
# some spam filters.
|
||||||
utf8_charset = Charset.Charset('utf-8')
|
utf8_charset = Charset.Charset('utf-8')
|
||||||
utf8_charset.body_encoding = None # Python defaults to BASE64
|
utf8_charset.body_encoding = None # Python defaults to BASE64
|
||||||
|
utf8_charset_qp = Charset.Charset('utf-8')
|
||||||
|
utf8_charset_qp.body_encoding = Charset.QP
|
||||||
|
|
||||||
# Default MIME type to use on attachments (if it is not explicitly given
|
# Default MIME type to use on attachments (if it is not explicitly given
|
||||||
# and cannot be guessed).
|
# and cannot be guessed).
|
||||||
DEFAULT_ATTACHMENT_MIME_TYPE = 'application/octet-stream'
|
DEFAULT_ATTACHMENT_MIME_TYPE = 'application/octet-stream'
|
||||||
|
|
||||||
|
RFC5322_EMAIL_LINE_LENGTH_LIMIT = 998
|
||||||
|
|
||||||
|
|
||||||
class BadHeaderError(ValueError):
|
class BadHeaderError(ValueError):
|
||||||
pass
|
pass
|
||||||
|
@ -169,7 +173,10 @@ class SafeMIMEText(MIMEMixin, MIMEText):
|
||||||
# We do it manually and trigger re-encoding of the payload.
|
# We do it manually and trigger re-encoding of the payload.
|
||||||
MIMEText.__init__(self, _text, _subtype, None)
|
MIMEText.__init__(self, _text, _subtype, None)
|
||||||
del self['Content-Transfer-Encoding']
|
del self['Content-Transfer-Encoding']
|
||||||
self.set_payload(_text, utf8_charset)
|
has_long_lines = any(len(l) > RFC5322_EMAIL_LINE_LENGTH_LIMIT for l in _text.splitlines())
|
||||||
|
# Quoted-Printable encoding has the side effect of shortening long
|
||||||
|
# lines, if any (#22561).
|
||||||
|
self.set_payload(_text, utf8_charset_qp if has_long_lines else utf8_charset)
|
||||||
self.replace_header('Content-Type', 'text/%s; charset="%s"' % (_subtype, _charset))
|
self.replace_header('Content-Type', 'text/%s; charset="%s"' % (_subtype, _charset))
|
||||||
elif _charset is None:
|
elif _charset is None:
|
||||||
# the default value of '_charset' is 'us-ascii' on Python 2
|
# the default value of '_charset' is 'us-ascii' on Python 2
|
||||||
|
|
|
@ -639,6 +639,22 @@ class BaseEmailBackendTests(HeadersCheckMixin, object):
|
||||||
self.assertEqual(message["subject"], '=?utf-8?q?Ch=C3=A8re_maman?=')
|
self.assertEqual(message["subject"], '=?utf-8?q?Ch=C3=A8re_maman?=')
|
||||||
self.assertEqual(force_text(message.get_payload(decode=True)), 'Je t\'aime très fort')
|
self.assertEqual(force_text(message.get_payload(decode=True)), 'Je t\'aime très fort')
|
||||||
|
|
||||||
|
def test_send_long_lines(self):
|
||||||
|
"""
|
||||||
|
Email line length is limited to 998 chars by the RFC:
|
||||||
|
https://tools.ietf.org/html/rfc5322#section-2.1.1
|
||||||
|
Message body containing longer lines are converted to Quoted-Printable
|
||||||
|
to avoid having to insert newlines, which could be hairy to do properly.
|
||||||
|
"""
|
||||||
|
email = EmailMessage('Subject', "Comment ça va? " * 100, 'from@example.com', ['to@example.com'])
|
||||||
|
email.send()
|
||||||
|
message = self.get_the_message()
|
||||||
|
self.assertMessageHasHeaders(message, {
|
||||||
|
('MIME-Version', '1.0'),
|
||||||
|
('Content-Type', 'text/plain; charset="utf-8"'),
|
||||||
|
('Content-Transfer-Encoding', 'quoted-printable'),
|
||||||
|
})
|
||||||
|
|
||||||
def test_send_many(self):
|
def test_send_many(self):
|
||||||
email1 = EmailMessage('Subject', 'Content1', 'from@example.com', ['to@example.com'])
|
email1 = EmailMessage('Subject', 'Content1', 'from@example.com', ['to@example.com'])
|
||||||
email2 = EmailMessage('Subject', 'Content2', 'from@example.com', ['to@example.com'])
|
email2 = EmailMessage('Subject', 'Content2', 'from@example.com', ['to@example.com'])
|
||||||
|
|
Loading…
Reference in New Issue