Skip to content

Commit b407e9f

Browse files
committed
Preserve filename of inline attachments
For ESPs that support both content-id and filename, don't drop the filename.
1 parent 6214fbb commit b407e9f

File tree

3 files changed

+21
-9
lines changed

3 files changed

+21
-9
lines changed

anymail/backends/mailgun.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,9 +111,14 @@ def set_html_body(self, body):
111111

112112
def add_attachment(self, attachment):
113113
# http://docs.python-requests.org/en/v2.4.3/user/advanced/#post-multiple-multipart-encoded-files
114-
field = "inline" if attachment.inline else "attachment"
114+
if attachment.inline:
115+
field = "inline"
116+
name = attachment.cid
117+
else:
118+
field = "attachment"
119+
name = attachment.name
115120
self.files.append(
116-
(field, (attachment.name, attachment.content, attachment.mimetype))
121+
(field, (name, attachment.content, attachment.mimetype))
117122
)
118123

119124
def set_metadata(self, metadata):

anymail/backends/mandrill.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -118,10 +118,15 @@ def set_html_body(self, body):
118118
self.data["message"]["html"] = body
119119

120120
def add_attachment(self, attachment):
121-
key = "images" if attachment.inline else "attachments"
122-
self.data["message"].setdefault(key, []).append({
121+
if attachment.inline:
122+
field = "images"
123+
name = attachment.cid
124+
else:
125+
field = "attachments"
126+
name = attachment.name or ""
127+
self.data["message"].setdefault(field, []).append({
123128
"type": attachment.mimetype,
124-
"name": attachment.name or "",
129+
"name": name,
125130
"content": attachment.b64content
126131
})
127132

anymail/utils.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -100,11 +100,12 @@ class Attachment(object):
100100
"""A normalized EmailMessage.attachments item with additional functionality
101101
102102
Normalized to have these properties:
103-
name: attachment filename; may be empty string; will be Content-ID (without <>) for inline attachments
104-
content
103+
name: attachment filename; may be empty string
104+
content: bytestream
105105
mimetype: the content type; guessed if not explicit
106106
inline: bool, True if attachment has a Content-ID header
107-
content_id: for inline, the Content-ID (with <>)
107+
content_id: for inline, the Content-ID (*with* <>)
108+
cid: for inline, the Content-ID *without* <>
108109
"""
109110

110111
def __init__(self, attachment, encoding):
@@ -114,6 +115,7 @@ def __init__(self, attachment, encoding):
114115
self.encoding = encoding # should we be checking attachment["Content-Encoding"] ???
115116
self.inline = False
116117
self.content_id = None
118+
self.cid = ""
117119

118120
if isinstance(attachment, MIMEBase):
119121
self.name = attachment.get_filename()
@@ -123,7 +125,7 @@ def __init__(self, attachment, encoding):
123125
if attachment.get_content_maintype() == "image" and attachment["Content-ID"] is not None:
124126
self.inline = True
125127
self.content_id = attachment["Content-ID"] # including the <...>
126-
self.name = self.content_id[1:-1] # without the <, >
128+
self.cid = self.content_id[1:-1] # without the <, >
127129
else:
128130
(self.name, self.content, self.mimetype) = attachment
129131

0 commit comments

Comments
 (0)