mirror of
https://github.com/pacnpal/django-anymail.git
synced 2025-12-20 03:41:05 -05:00
Inbound: improve inline content handling
* refactor: derive `AnymailInboundMessage` from `email.message.EmailMessage` rather than legacy Python 2.7 `email.message.Message` * feat(inbound): replace confusing `inline_attachments` with `content_id_map` and `inlines`; rename `is_inline_attachment` to `is_inline`; deprecate old names Closes #328 --------- Co-authored-by: Mike Edmunds <medmunds@gmail.com>
This commit is contained in:
@@ -267,7 +267,7 @@ class AmazonSESBackendStandardEmailTests(AmazonSESBackendMockAPITestCase):
|
||||
|
||||
self.assertEqual(sent_message.html, html_content)
|
||||
|
||||
inlines = sent_message.inline_attachments
|
||||
inlines = sent_message.content_id_map
|
||||
self.assertEqual(len(inlines), 1)
|
||||
self.assertEqual(inlines[cid].get_content_type(), "image/png")
|
||||
self.assertEqual(inlines[cid].get_filename(), image_filename)
|
||||
|
||||
@@ -274,7 +274,7 @@ class AmazonSESBackendStandardEmailTests(AmazonSESBackendMockAPITestCase):
|
||||
|
||||
self.assertEqual(sent_message.html, html_content)
|
||||
|
||||
inlines = sent_message.inline_attachments
|
||||
inlines = sent_message.content_id_map
|
||||
self.assertEqual(len(inlines), 1)
|
||||
self.assertEqual(inlines[cid].get_content_type(), "image/png")
|
||||
self.assertEqual(inlines[cid].get_filename(), image_filename)
|
||||
|
||||
@@ -6,6 +6,7 @@ from textwrap import dedent
|
||||
from django.core.mail import SafeMIMEText
|
||||
from django.test import SimpleTestCase
|
||||
|
||||
from anymail.exceptions import AnymailDeprecationWarning
|
||||
from anymail.inbound import AnymailInboundMessage
|
||||
|
||||
from .utils import SAMPLE_IMAGE_FILENAME, sample_email_path, sample_image_content
|
||||
@@ -200,7 +201,7 @@ class AnymailInboundMessageConstructionTests(SimpleTestCase):
|
||||
content_id="inline-id",
|
||||
)
|
||||
self.assertEqual(att.get_filename(), "Simulácia.txt")
|
||||
self.assertTrue(att.is_inline_attachment())
|
||||
self.assertTrue(att.is_inline())
|
||||
self.assertEqual(att.get_content_text(), "Unicode ✓")
|
||||
|
||||
def test_parse_raw_mime(self):
|
||||
@@ -446,7 +447,7 @@ class AnymailInboundMessageConveniencePropTests(SimpleTestCase):
|
||||
# Default empty list
|
||||
self.assertEqual(AnymailInboundMessage().attachments, [])
|
||||
|
||||
def test_inline_attachments_prop(self):
|
||||
def test_content_id_map_prop(self):
|
||||
att = AnymailInboundMessage.construct_attachment(
|
||||
"image/png",
|
||||
SAMPLE_IMAGE_CONTENT,
|
||||
@@ -455,10 +456,64 @@ class AnymailInboundMessageConveniencePropTests(SimpleTestCase):
|
||||
)
|
||||
|
||||
msg = AnymailInboundMessage.construct(attachments=[att])
|
||||
self.assertEqual(msg.inline_attachments, {"abc123": att})
|
||||
self.assertEqual(msg.content_id_map, {"abc123": att})
|
||||
|
||||
with self.assertWarnsMessage(
|
||||
AnymailDeprecationWarning,
|
||||
"inline_attachments has been renamed to content_id_map and will be removed "
|
||||
"in the near future.",
|
||||
):
|
||||
self.assertEqual(msg.inline_attachments, {"abc123": att})
|
||||
|
||||
# Default empty dict
|
||||
self.assertEqual(AnymailInboundMessage().inline_attachments, {})
|
||||
self.assertEqual(AnymailInboundMessage().content_id_map, {})
|
||||
|
||||
def test_inlines_prop(self):
|
||||
raw = dedent(
|
||||
"""\
|
||||
MIME-Version: 1.0
|
||||
Subject: Message with inline parts
|
||||
Content-Type: multipart/mixed; boundary="boundary-orig"
|
||||
|
||||
--boundary-orig
|
||||
Content-Type: text/html; charset="UTF-8"
|
||||
|
||||
<img src="cid:abc123"> Here is a message!
|
||||
|
||||
--boundary-orig
|
||||
Content-Type: image/png; name="sample_image.png"
|
||||
Content-Disposition: inline
|
||||
Content-ID: <abc123>
|
||||
Content-Transfer-Encoding: base64
|
||||
|
||||
{image_content_base64}
|
||||
|
||||
--boundary-orig
|
||||
Content-Type: image/png; name="sample_image_without_cid.png"
|
||||
Content-Disposition: inline
|
||||
Content-Transfer-Encoding: base64
|
||||
|
||||
{image_content_base64}
|
||||
|
||||
--boundary-orig--
|
||||
"""
|
||||
).format(image_content_base64=b64encode(SAMPLE_IMAGE_CONTENT).decode("ascii"))
|
||||
|
||||
msg = AnymailInboundMessage.parse_raw_mime(raw)
|
||||
inlines = msg.inlines
|
||||
|
||||
self.assertEqual(len(inlines), 2)
|
||||
|
||||
self.assertEqual(inlines[0].get_content_type(), "image/png")
|
||||
self.assertEqual(inlines[0].as_uploaded_file().name, "sample_image.png")
|
||||
|
||||
self.assertEqual(inlines[1].get_content_type(), "image/png")
|
||||
self.assertEqual(
|
||||
inlines[1].as_uploaded_file().name, "sample_image_without_cid.png"
|
||||
)
|
||||
|
||||
self.assertEqual(len(msg.content_id_map.items()), 1)
|
||||
self.assertIn("abc123", msg.content_id_map)
|
||||
|
||||
def test_attachment_as_uploaded_file(self):
|
||||
raw = dedent(
|
||||
@@ -609,9 +664,16 @@ class AnymailInboundMessageAttachedMessageTests(SimpleTestCase):
|
||||
|
||||
orig_inline_att = orig_msg.get_payload(1)
|
||||
self.assertEqual(orig_inline_att.get_content_type(), "image/png")
|
||||
self.assertTrue(orig_inline_att.is_inline_attachment())
|
||||
self.assertTrue(orig_inline_att.is_inline())
|
||||
self.assertEqual(orig_inline_att.get_payload(decode=True), SAMPLE_IMAGE_CONTENT)
|
||||
|
||||
with self.assertWarnsMessage(
|
||||
AnymailDeprecationWarning,
|
||||
"is_inline_attachment has been renamed to is_inline and will be removed in "
|
||||
"the near future.",
|
||||
):
|
||||
self.assertTrue(orig_inline_att.is_inline_attachment())
|
||||
|
||||
def test_construct_rfc822_attachment_from_data(self):
|
||||
# constructed message/rfc822 attachment should end up as parsed message
|
||||
# (same as if attachment was parsed from raw mime, as in previous test)
|
||||
|
||||
@@ -323,7 +323,7 @@ class MailerSendInboundTestCase(MailerSendWebhookTestCase):
|
||||
],
|
||||
)
|
||||
|
||||
inlines = message.inline_attachments
|
||||
inlines = message.content_id_map
|
||||
self.assertEqual(len(inlines), 1)
|
||||
inline = inlines["ii_letc8ro50"]
|
||||
self.assertEqual(inline.get_filename(), "sample_image.png")
|
||||
|
||||
@@ -182,7 +182,7 @@ class MailgunInboundTestCase(WebhookTestCase):
|
||||
attachments[1].get_content_bytes(), email_content
|
||||
)
|
||||
|
||||
inlines = message.inline_attachments
|
||||
inlines = message.content_id_map
|
||||
self.assertEqual(len(inlines), 1)
|
||||
inline = inlines["abc123"]
|
||||
self.assertEqual(inline.get_filename(), "image.png")
|
||||
@@ -266,7 +266,7 @@ class MailgunInboundTestCase(WebhookTestCase):
|
||||
event = kwargs["event"]
|
||||
message = event.message
|
||||
self.assertEqual(len(message.attachments), 0) # all inlines
|
||||
inlines = [part for part in message.walk() if part.is_inline_attachment()]
|
||||
inlines = [part for part in message.walk() if part.is_inline()]
|
||||
self.assertEqual(len(inlines), 4)
|
||||
self.assertEqual(inlines[0]["Content-ID"], "")
|
||||
self.assertEqual(inlines[1]["Content-ID"], "")
|
||||
|
||||
@@ -205,7 +205,7 @@ class MailjetInboundTestCase(WebhookTestCase):
|
||||
attachments[1].get_content_bytes(), email_content
|
||||
)
|
||||
|
||||
inlines = message.inline_attachments
|
||||
inlines = message.content_id_map
|
||||
self.assertEqual(len(inlines), 1)
|
||||
inline = inlines["abc123"]
|
||||
self.assertEqual(inline.get_filename(), "image.png")
|
||||
|
||||
@@ -204,7 +204,7 @@ class PostalInboundTestCase(WebhookTestCase):
|
||||
attachments[1].get_content_bytes(), email_content
|
||||
)
|
||||
|
||||
inlines = message.inline_attachments
|
||||
inlines = message.content_id_map
|
||||
self.assertEqual(len(inlines), 1)
|
||||
inline = inlines["abc123"]
|
||||
self.assertEqual(inline.get_filename(), "image.png")
|
||||
|
||||
@@ -191,7 +191,7 @@ class PostmarkInboundTestCase(WebhookTestCase):
|
||||
attachments[1].get_content_bytes(), email_content
|
||||
)
|
||||
|
||||
inlines = message.inline_attachments
|
||||
inlines = message.content_id_map
|
||||
self.assertEqual(len(inlines), 1)
|
||||
inline = inlines["abc123"]
|
||||
self.assertEqual(inline.get_filename(), "image.png")
|
||||
|
||||
@@ -170,7 +170,7 @@ class SendgridInboundTestCase(WebhookTestCase):
|
||||
attachments[1].get_content_bytes(), email_content
|
||||
)
|
||||
|
||||
inlines = message.inline_attachments
|
||||
inlines = message.content_id_map
|
||||
self.assertEqual(len(inlines), 1)
|
||||
inline = inlines["abc123"]
|
||||
self.assertEqual(inline.get_filename(), "image.png")
|
||||
|
||||
@@ -205,7 +205,7 @@ class SparkpostInboundTestCase(WebhookTestCase):
|
||||
self.assertEqual(att_message["Subject"], "Test email")
|
||||
self.assertEqual(att_message.text, "Hi Bob, This is a message. Thanks!\n")
|
||||
|
||||
inlines = message.inline_attachments
|
||||
inlines = message.content_id_map
|
||||
self.assertEqual(len(inlines), 1)
|
||||
inline = inlines["abc123"]
|
||||
self.assertEqual(inline.get_filename(), "image.png")
|
||||
|
||||
Reference in New Issue
Block a user