Ticket #12791: emailmessage-body-header-encoding.diff
File emailmessage-body-header-encoding.diff, 7.5 KB (added by , 15 years ago) |
---|
-
django/core/mail/message.py
54 54 return msgid 55 55 56 56 57 def forbid_multi_line_headers(name, val): 57 def forbid_multi_line_headers(name, val, encoding): 58 encoding = encoding or settings.DEFAULT_CHARSET 58 59 """Forbids multi-line headers, to prevent header injection.""" 59 60 val = force_unicode(val) 60 61 if '\n' in val or '\r' in val: … … 65 66 if name.lower() in ('to', 'from', 'cc'): 66 67 result = [] 67 68 for nm, addr in getaddresses((val,)): 68 nm = str(Header(nm , settings.DEFAULT_CHARSET))69 nm = str(Header(nm.encode(encoding), encoding)) 69 70 result.append(formataddr((nm, str(addr)))) 70 71 val = ', '.join(result) 71 72 else: 72 val = Header(val , settings.DEFAULT_CHARSET)73 val = Header(val.encode(encoding), encoding) 73 74 else: 74 75 if name.lower() == 'subject': 75 76 val = Header(val) 76 77 return name, val 77 78 78 79 79 class 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) 82 87 MIMEText.__setitem__(self, name, val) 83 88 84 85 89 class 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 86 95 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) 88 97 MIMEMultipart.__setitem__(self, name, val) 89 98 90 91 99 class EmailMessage(object): 92 100 """ 93 101 A container for email information. … … 131 139 132 140 def message(self): 133 141 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), 135 143 self.content_subtype, encoding) 136 144 msg = self._create_message(msg) 137 145 msg['Subject'] = self.subject … … 190 198 191 199 def _create_attachments(self, msg): 192 200 if self.attachments: 201 encoding = self.encoding or settings.DEFAULT_CHARSET 193 202 body_msg = msg 194 msg = SafeMIMEMultipart(_subtype=self.mixed_subtype )203 msg = SafeMIMEMultipart(_subtype=self.mixed_subtype, encoding=encoding) 195 204 if self.body: 196 205 msg.attach(body_msg) 197 206 for attachment in self.attachments: … … 207 216 """ 208 217 basetype, subtype = mimetype.split('/', 1) 209 218 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) 212 221 else: 213 222 # Encode non-text attachments with base64. 214 223 attachment = MIMEBase(basetype, subtype) … … 263 272 return self._create_attachments(self._create_alternatives(msg)) 264 273 265 274 def _create_alternatives(self, msg): 275 encoding = self.encoding or settings.DEFAULT_CHARSET 266 276 if self.alternatives: 267 277 body_msg = msg 268 msg = SafeMIMEMultipart(_subtype=self.alternative_subtype )278 msg = SafeMIMEMultipart(_subtype=self.alternative_subtype, encoding=encoding) 269 279 if self.body: 270 280 msg.attach(body_msg) 271 281 for alternative in self.alternatives: -
tests/regressiontests/mail/tests.py
112 112 >>> email.message()['To'] 113 113 '=?utf-8?q?S=C3=BCrname=2C_Firstname?= <to@example.com>, other@example.com' 114 114 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() 122 u'=?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() 135 u'=?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 115 153 # Handle attachments within an multipart/alternative mail correctly (#9367) 116 154 # (test is not as precise/clear as it could be w.r.t. email tree structure, 117 155 # but it's good enough.) 118 119 156 >>> headers = {"Date": "Fri, 09 Nov 2001 01:08:47 -0000", "Message-ID": "foo"} 120 157 >>> subject, from_email, to = 'hello', 'from@example.com', 'to@example.com' 121 158 >>> text_content = 'This is an important message.'