Ticket #12791: emailmessage-body-header-encoding.diff

File emailmessage-body-header-encoding.diff, 7.5 KB (added by oyvind, 15 years ago)

A combination of the patches in #12791 and #6918 supporting different encodings both in body and headers.

  • django/core/mail/message.py

     
    5454    return msgid
    5555
    5656
    57 def forbid_multi_line_headers(name, val):
     57def forbid_multi_line_headers(name, val, encoding):
     58    encoding = encoding or settings.DEFAULT_CHARSET
    5859    """Forbids multi-line headers, to prevent header injection."""
    5960    val = force_unicode(val)
    6061    if '\n' in val or '\r' in val:
     
    6566        if name.lower() in ('to', 'from', 'cc'):
    6667            result = []
    6768            for nm, addr in getaddresses((val,)):
    68                 nm = str(Header(nm, settings.DEFAULT_CHARSET))
     69                nm = str(Header(nm.encode(encoding), encoding))
    6970                result.append(formataddr((nm, str(addr))))
    7071            val = ', '.join(result)
    7172        else:
    72             val = Header(val, settings.DEFAULT_CHARSET)
     73            val = Header(val.encode(encoding), encoding)
    7374    else:
    7475        if name.lower() == 'subject':
    7576            val = Header(val)
    7677    return name, val
    7778
    78 
    7979class SafeMIMEText(MIMEText):
    80     def __setitem__(self, name, val):
    81         name, val = forbid_multi_line_headers(name, val)
     80   
     81    def __init__(self, text, subtype, charset):
     82        self.encoding = charset
     83        MIMEText.__init__(self, text, subtype, charset)
     84   
     85    def __setitem__(self, name, val):   
     86        name, val = forbid_multi_line_headers(name, val, self.encoding)
    8287        MIMEText.__setitem__(self, name, val)
    8388
    84 
    8589class SafeMIMEMultipart(MIMEMultipart):
     90   
     91    def __init__(self, _subtype='mixed', boundary=None, _subparts=None, encoding=None, **_params):
     92        self.encoding = encoding
     93        MIMEMultipart.__init__(self, _subtype, boundary, _subparts, **_params)
     94       
    8695    def __setitem__(self, name, val):
    87         name, val = forbid_multi_line_headers(name, val)
     96        name, val = forbid_multi_line_headers(name, val, self.encoding)
    8897        MIMEMultipart.__setitem__(self, name, val)
    8998
    90 
    9199class EmailMessage(object):
    92100    """
    93101    A container for email information.
     
    131139
    132140    def message(self):
    133141        encoding = self.encoding or settings.DEFAULT_CHARSET
    134         msg = SafeMIMEText(smart_str(self.body, settings.DEFAULT_CHARSET),
     142        msg = SafeMIMEText(smart_str(self.body, encoding),
    135143                           self.content_subtype, encoding)
    136144        msg = self._create_message(msg)
    137145        msg['Subject'] = self.subject
     
    190198
    191199    def _create_attachments(self, msg):
    192200        if self.attachments:
     201            encoding = self.encoding or settings.DEFAULT_CHARSET
    193202            body_msg = msg
    194             msg = SafeMIMEMultipart(_subtype=self.mixed_subtype)
     203            msg = SafeMIMEMultipart(_subtype=self.mixed_subtype, encoding=encoding)
    195204            if self.body:
    196205                msg.attach(body_msg)
    197206            for attachment in self.attachments:
     
    207216        """
    208217        basetype, subtype = mimetype.split('/', 1)
    209218        if basetype == 'text':
    210             attachment = SafeMIMEText(smart_str(content,
    211                 settings.DEFAULT_CHARSET), subtype, settings.DEFAULT_CHARSET)
     219            encoding = self.encoding or settings.DEFAULT_CHARSET
     220            attachment = SafeMIMEText(smart_str(content, encoding), subtype, encoding)
    212221        else:
    213222            # Encode non-text attachments with base64.
    214223            attachment = MIMEBase(basetype, subtype)
     
    263272        return self._create_attachments(self._create_alternatives(msg))
    264273
    265274    def _create_alternatives(self, msg):
     275        encoding = self.encoding or settings.DEFAULT_CHARSET
    266276        if self.alternatives:
    267277            body_msg = msg
    268             msg = SafeMIMEMultipart(_subtype=self.alternative_subtype)
     278            msg = SafeMIMEMultipart(_subtype=self.alternative_subtype, encoding=encoding)
    269279            if self.body:
    270280                msg.attach(body_msg)
    271281            for alternative in self.alternatives:
  • tests/regressiontests/mail/tests.py

     
    112112>>> email.message()['To']
    113113'=?utf-8?q?S=C3=BCrname=2C_Firstname?= <to@example.com>, other@example.com'
    114114
     115# Regression for #6918 - When a header contains unicode,
     116# make sure headers can be set with a different encoding than utf-8
     117>>> email = EmailMessage('Message from Firstname Sürname', 'Content', 'from@example.com', ['"Sürname, Firstname" <to@example.com>','other@example.com'])
     118>>> email.encoding = 'iso-8859-1'
     119>>> email.message()['To']
     120'=?iso-8859-1?q?S=FCrname=2C_Firstname?= <to@example.com>, other@example.com'
     121>>> email.message()['Subject'].encode()
     122u'=?iso-8859-1?q?Message_from_Firstname_S=FCrname?='
     123
     124# Make sure headers can be set with a different encoding than utf-8 in SafeMIMEMultipart aswell
     125>>> headers = {"Date": "Fri, 09 Nov 2001 01:08:47 -0000", "Message-ID": "foo"}
     126>>> subject, from_email, to = 'hello', 'from@example.com', '"Sürname, Firstname" <to@example.com>'
     127>>> text_content = 'This is an important message.'
     128>>> html_content = '<p>This is an <strong>important</strong> message.</p>'
     129>>> msg = EmailMultiAlternatives('Message from Firstname Sürname', text_content, from_email, [to], headers=headers)
     130>>> msg.attach_alternative(html_content, "text/html")
     131>>> msg.encoding = 'iso-8859-1'
     132>>> msg.message()['To']
     133'=?iso-8859-1?q?S=FCrname=2C_Firstname?= <to@example.com>'
     134>>> msg.message()['Subject'].encode()
     135u'=?iso-8859-1?q?Message_from_Firstname_S=FCrname?='
     136
     137# Regression for #12791  - Encode body correctly with other encodings than utf-8
     138>>> email = EmailMessage('Subject', 'Firstname Sürname is a great guy.', 'from@example.com', ['other@example.com'])
     139>>> email.encoding = 'iso-8859-1'
     140>>> message = email.message()
     141>>> message.as_string()
     142'Content-Type: text/plain; charset="iso-8859-1"\nMIME-Version: 1.0\nContent-Transfer-Encoding: quoted-printable\nSubject: Subject\nFrom: from@example.com\nTo: other@example.com\nDate: ...\nMessage-ID: <...>\n\nFirstname S=FCrname is a great guy.'
     143
     144# Make sure MIME attachments also works correctly with other encodings than utf-8
     145>>> text_content = 'Firstname Sürname is a great guy.'
     146>>> html_content = '<p>Firstname Sürname is a <strong>great</strong> guy.</p>'
     147>>> msg = EmailMultiAlternatives('Subject', text_content, 'from@example.com', ['to@example.com'])
     148>>> msg.encoding = 'iso-8859-1'
     149>>> msg.attach_alternative(html_content, "text/html")
     150>>> msg.message().as_string()
     151'Content-Type: multipart/alternative; boundary="===============...=="\nMIME-Version: 1.0\nSubject: Subject\nFrom: from@example.com\nTo: to@example.com\nDate: ...\nMessage-ID: <...>\n\n--===============...==\nContent-Type: text/plain; charset="iso-8859-1"\nMIME-Version: 1.0\nContent-Transfer-Encoding: quoted-printable\n\nFirstname S=FCrname is a great guy.\n--===============...==\nContent-Type: text/html; charset="iso-8859-1"\nMIME-Version: 1.0\nContent-Transfer-Encoding: quoted-printable\n\n<p>Firstname S=FCrname is a <strong>great</strong> guy.</p>\n--===============...==--'
     152
    115153# Handle attachments within an multipart/alternative mail correctly (#9367)
    116154# (test is not as precise/clear as it could be w.r.t. email tree structure,
    117155#  but it's good enough.)
    118 
    119156>>> headers = {"Date": "Fri, 09 Nov 2001 01:08:47 -0000", "Message-ID": "foo"}
    120157>>> subject, from_email, to = 'hello', 'from@example.com', 'to@example.com'
    121158>>> text_content = 'This is an important message.'
Back to Top