[1.2.X] Fixed #13433 -- Changed default behavior of Django email message wrappers to not mangle lines starting with 'From '. Thanks Leo for the report and patch.

Backport of [15669] from trunk.

git-svn-id: http://code.djangoproject.com/svn/django/branches/releases/1.2.X@15670 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Ramiro Morales 2011-02-28 02:56:02 +00:00
parent 076ce17f0e
commit f5c0328fd3
2 changed files with 41 additions and 4 deletions

View File

@ -3,16 +3,21 @@ import os
import random import random
import time import time
from email import Charset, Encoders from email import Charset, Encoders
from email.generator import Generator
from email.MIMEText import MIMEText from email.MIMEText import MIMEText
from email.MIMEMultipart import MIMEMultipart from email.MIMEMultipart import MIMEMultipart
from email.MIMEBase import MIMEBase from email.MIMEBase import MIMEBase
from email.Header import Header from email.Header import Header
from email.Utils import formatdate, getaddresses, formataddr from email.Utils import formatdate, getaddresses, formataddr, parseaddr
from django.conf import settings from django.conf import settings
from django.core.mail.utils import DNS_NAME from django.core.mail.utils import DNS_NAME
from django.utils.encoding import smart_str, force_unicode from django.utils.encoding import smart_str, force_unicode
from email.Utils import parseaddr
try:
from cStringIO import StringIO
except ImportError:
from StringIO import StringIO
# Don't BASE64-encode UTF-8 messages so that we avoid unwanted attention from # Don't BASE64-encode UTF-8 messages so that we avoid unwanted attention from
# some spam filters. # some spam filters.
@ -119,6 +124,19 @@ class SafeMIMEText(MIMEText):
name, val = forbid_multi_line_headers(name, val, self.encoding) name, val = forbid_multi_line_headers(name, val, self.encoding)
MIMEText.__setitem__(self, name, val) MIMEText.__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 = StringIO()
g = Generator(fp, mangle_from_ = False)
g.flatten(self, unixfrom=unixfrom)
return fp.getvalue()
class SafeMIMEMultipart(MIMEMultipart): class SafeMIMEMultipart(MIMEMultipart):
@ -130,6 +148,19 @@ class SafeMIMEMultipart(MIMEMultipart):
name, val = forbid_multi_line_headers(name, val, self.encoding) name, val = forbid_multi_line_headers(name, val, self.encoding)
MIMEMultipart.__setitem__(self, name, val) 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 = StringIO()
g = Generator(fp, mangle_from_ = False)
g.flatten(self, unixfrom=unixfrom)
return fp.getvalue()
class EmailMessage(object): class EmailMessage(object):
""" """

View File

@ -11,8 +11,8 @@ import threading
from django.conf import settings from django.conf import settings
from django.core import mail from django.core import mail
from django.core.mail import EmailMessage, mail_admins, mail_managers, EmailMultiAlternatives from django.core.mail import (EmailMessage, mail_admins, mail_managers,
from django.core.mail import send_mail, send_mass_mail EmailMultiAlternatives, send_mail, send_mass_mail)
from django.core.mail.backends import console, dummy, locmem, filebased, smtp from django.core.mail.backends import console, dummy, locmem, filebased, smtp
from django.core.mail.message import BadHeaderError from django.core.mail.message import BadHeaderError
from django.test import TestCase from django.test import TestCase
@ -263,6 +263,12 @@ class MailTests(TestCase):
self.assertEqual(len(connection.test_outbox), 1) self.assertEqual(len(connection.test_outbox), 1)
self.assertEqual(connection.test_outbox[0].subject, '[Django] Manager message') self.assertEqual(connection.test_outbox[0].subject, '[Django] Manager message')
def test_dont_mangle_from_in_body(self):
# Regression for #13433 - Make sure that EmailMessage doesn't mangle
# 'From ' in message body.
email = EmailMessage('Subject', 'From the future', 'bounce@example.com', ['to@example.com'], headers={'From': 'from@example.com'})
self.assertFalse('>From the future' in email.message().as_string())
class BaseEmailBackendTests(object): class BaseEmailBackendTests(object):
email_backend = None email_backend = None