File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -41,6 +41,14 @@ Features
4141
4242* **Resend: ** Add support for inbound email. (Thanks to `@btimby `_.)
4343
44+ Fixes
45+ ~~~~~
46+
47+ * **Inbound: ** Convert carriage return and line feed characters in attachment
48+ filenames to spaces for ESPs that parse them from invalid headers (e.g.,
49+ Postmark). (Thanks to `@BHSPitMonkey `_ for reporting the issue and providing
50+ an example.)
51+
4452
4553v14.0
4654-----
@@ -1959,6 +1967,7 @@ Features
19591967.. _@b0d0nne11 : https://github.com/b0d0nne11
19601968.. _@blag : https://github.com/blag
19611969.. _@btimby : https://github.com/btimby
1970+ .. _@BHSPitMonkey : https://github.com/BHSPitMonkey
19621971.. _@cahna : https://github.com/cahna
19631972.. _@calvin : https://github.com/calvin
19641973.. _@carrerasrodrigo : https://github.com/carrerasrodrigo
Original file line number Diff line number Diff line change 1+ import re
12import warnings
23from base64 import b64decode
34from email .message import EmailMessage
@@ -393,6 +394,8 @@ def construct_attachment(
393394 )
394395
395396 if filename is not None :
397+ # Replace CR/NL sequences with a space. See issue #465.
398+ filename = re .sub (r"[\r\n]+" , " " , filename )
396399 part .set_param ("name" , filename , header = "Content-Type" )
397400 part .set_param ("filename" , filename , header = "Content-Disposition" )
398401
Original file line number Diff line number Diff line change @@ -203,6 +203,20 @@ def test_construct_attachment_unicode_filename(self):
203203 self .assertTrue (att .is_inline ())
204204 self .assertEqual (att .get_content_text (), "Unicode ✓" )
205205
206+ def test_construct_attachment_crnl_in_filename (self ):
207+ # Issue #465: Postmark (at least) decodes newlines out of this header:
208+ # Content-Disposition: inline;
209+ # filename="=?iso-8859-1?Q?Outlook-Icon=0A=0ADesc.png?="
210+ # leading to the ValueError "Header values may not contain linefeed or
211+ # carriage return characters" when Anymail tries to use that filename
212+ # in Python's EmailMessage.
213+ att = AnymailInboundMessage .construct_attachment (
214+ content_type = "text/plain" ,
215+ content = "content" ,
216+ filename = "Outlook-Icon\n \n Dec.png" ,
217+ )
218+ self .assertEqual (att .get_filename (), "Outlook-Icon Dec.png" )
219+
206220 def test_parse_raw_mime (self ):
207221 # (we're not trying to exhaustively test email.parser MIME handling here;
208222 # just that AnymailInboundMessage.parse_raw_mime calls it correctly)
You can’t perform that action at this time.
0 commit comments