Ticket #6918: emailmessage-header-encoding.diff

File emailmessage-header-encoding.diff, 5.4 KB (added by oyvind, 14 years ago)

New patch for r12398

  • 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):
    5858    """Forbids multi-line headers, to prevent header injection."""
    5959    val = force_unicode(val)
    6060    if '\n' in val or '\r' in val:
     
    6565        if name.lower() in ('to', 'from', 'cc'):
    6666            result = []
    6767            for nm, addr in getaddresses((val,)):
    68                 nm = str(Header(nm, settings.DEFAULT_CHARSET))
     68                nm = str(Header(nm.encode(encoding), encoding))
    6969                result.append(formataddr((nm, str(addr))))
    7070            val = ', '.join(result)
    7171        else:
    72             val = Header(val, settings.DEFAULT_CHARSET)
     72            val = Header(val.encode(encoding), encoding)
    7373    else:
    7474        if name.lower() == 'subject':
    7575            val = Header(val)
    7676    return name, val
    7777
    78 
    7978class SafeMIMEText(MIMEText):
    80     def __setitem__(self, name, val):
    81         name, val = forbid_multi_line_headers(name, val)
     79   
     80    def __init__(self, text, subtype, charset):
     81        self.encoding = charset
     82        MIMEText.__init__(self, text, subtype, charset)
     83   
     84    def __setitem__(self, name, val):   
     85        name, val = forbid_multi_line_headers(name, val, self.encoding)
    8286        MIMEText.__setitem__(self, name, val)
    8387
    84 
    8588class SafeMIMEMultipart(MIMEMultipart):
     89   
     90    def __init__(self, _subtype='mixed', boundary=None, _subparts=None, encoding=None, **_params):
     91        self.encoding = encoding
     92        MIMEMultipart.__init__(self, _subtype, boundary, _subparts, **_params)
     93       
    8694    def __setitem__(self, name, val):
    87         name, val = forbid_multi_line_headers(name, val)
     95        name, val = forbid_multi_line_headers(name, val, self.encoding)
    8896        MIMEMultipart.__setitem__(self, name, val)
    8997
    90 
    9198class EmailMessage(object):
    9299    """
    93100    A container for email information.
     
    190197
    191198    def _create_attachments(self, msg):
    192199        if self.attachments:
     200            encoding = self.encoding or settings.DEFAULT_CHARSET
    193201            body_msg = msg
    194             msg = SafeMIMEMultipart(_subtype=self.mixed_subtype)
     202            msg = SafeMIMEMultipart(_subtype=self.mixed_subtype, encoding=encoding)
    195203            if self.body:
    196204                msg.attach(body_msg)
    197205            for attachment in self.attachments:
     
    206214        Converts the content, mimetype pair into a MIME attachment object.
    207215        """
    208216        basetype, subtype = mimetype.split('/', 1)
     217        encoding = self.encoding or settings.DEFAULT_CHARSET
     218
    209219        if basetype == 'text':
    210220            attachment = SafeMIMEText(smart_str(content,
    211                 settings.DEFAULT_CHARSET), subtype, settings.DEFAULT_CHARSET)
     221                encoding), subtype, encoding)
    212222        else:
    213223            # Encode non-text attachments with base64.
    214224            attachment = MIMEBase(basetype, subtype)
     
    263273        return self._create_attachments(self._create_alternatives(msg))
    264274
    265275    def _create_alternatives(self, msg):
     276        encoding = self.encoding or settings.DEFAULT_CHARSET
    266277        if self.alternatives:
    267278            body_msg = msg
    268             msg = SafeMIMEMultipart(_subtype=self.alternative_subtype)
     279            msg = SafeMIMEMultipart(_subtype=self.alternative_subtype, encoding=encoding)
    269280            if self.body:
    270281                msg.attach(body_msg)
    271282            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 to/from/cc 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>>> email.message()['To']
     132'=?iso-8859-1?q?S=FCrname=2C_Firstname?= <to@example.com>, other@example.com'
     133>>> email.message()['Subject'].encode()
     134u'=?iso-8859-1?q?Message_from_Firstname_S=FCrname?='
     135
    115136# Handle attachments within an multipart/alternative mail correctly (#9367)
    116137# (test is not as precise/clear as it could be w.r.t. email tree structure,
    117138#  but it's good enough.)
Back to Top