diff --git a/django_mailbox/models.py b/django_mailbox/models.py index fec57d6..3c6ed41 100644 --- a/django_mailbox/models.py +++ b/django_mailbox/models.py @@ -298,7 +298,10 @@ class Mailbox(models.Model): settings = utils.get_settings() new = EmailMessage() - if msg.is_multipart(): + if ( + msg.is_multipart() + and not 'attachment' in msg.get('Content-Disposition', '') + ): for header, value in msg.items(): new[header] = value for part in msg.get_payload(): @@ -339,11 +342,21 @@ class Mailbox(models.Model): attachment = MessageAttachment() + if msg.get_content_type() == 'message/rfc822': + attachment_payloads = msg.get_payload() + if len(attachment_payloads) != 1: + raise AssertionError( + "Attachment of type 'message/rfc822' " + 'must have exactly 1 payload.' + ) + attachment_payload = attachment_payloads[0].as_bytes() + else: + attachment_payload = msg.get_payload(decode=True) attachment.document.save( uuid.uuid4().hex + extension, ContentFile( BytesIO( - msg.get_payload(decode=True) + attachment_payload ).getvalue() ) ) @@ -832,6 +845,11 @@ class MessageAttachment(models.Model): return email.message_from_string(headers) def _set_dehydrated_headers(self, email_object): + if email_object._payload is None: + # otherwise it breaks in + # lib/python3.x/email/generator.py:_handle_message, + # line: "self._fp.write(payload)" + email_object._payload = "" self.headers = email_object.as_string() def __delitem__(self, name): diff --git a/django_mailbox/tests/messages/message_with_rfc822_attachment.eml b/django_mailbox/tests/messages/message_with_rfc822_attachment.eml new file mode 100644 index 0000000..0e1e050 --- /dev/null +++ b/django_mailbox/tests/messages/message_with_rfc822_attachment.eml @@ -0,0 +1,62 @@ +From: Adam Coddington +To: Adam Coddington +Subject: Email with RFC 822 attachment +Date: Fri, 15 May 2020 11:15:00 +0000 +Message-ID: +Content-Type: multipart/mixed; + boundary="_004_ce1f843c1a2d4de7a0c7c78c84a50f8dadamcoddington.net_" +Return-Path: test@adamcoddington.net +MIME-Version: 1.0 + +--_004_ce1f843c1a2d4de7a0c7c78c84a50f8dadamcoddington.net_ +Content-Type: multipart/alternative; + boundary="_000_ce1f843c1a2d4de7a0c7c78c84a50f8dadamcoddington.net_" + +--_000_ce1f843c1a2d4de7a0c7c78c84a50f8dadamcoddington.net_ +Content-Type: text/plain; charset="iso-8859-1" +Content-Transfer-Encoding: quoted-printable + +Dear Sir or Madam, + +I am sending you an email message as an attachment. + + +--_000_ce1f843c1a2d4de7a0c7c78c84a50f8dadamcoddington.net_ +Content-Type: text/html; charset="iso-8859-1" +Content-Transfer-Encoding: quoted-printable + + + + + + +
+

Dear Sir or Madam,

+

I am sending you an email message as an attachment.

+
+ + + +--_000_ce1f843c1a2d4de7a0c7c78c84a50f8dadamcoddington.net_-- + +--_004_ce1f843c1a2d4de7a0c7c78c84a50f8dadamcoddington.net_ +Content-Type: message/rfc822 +Content-Disposition: attachment; + creation-date="Fri, 15 May 2020 11:10:00 GMT"; + modification-date="Fri, 15 May 2020 11:10:00 GMT" + +From: Adam Coddington +To: Adam Coddington +Subject: Attached email +Date: Fri, 15 May 2020 09:00:00 +0000 +Message-ID: +Content-Type: text/plain; charset="iso-8859-1" +Content-Transfer-Encoding: quoted-printable +MIME-Version: 1.0 + +Hello! + +This is the attached email. + +--_004_ce1f843c1a2d4de7a0c7c78c84a50f8dadamcoddington.net_-- diff --git a/django_mailbox/tests/test_process_email.py b/django_mailbox/tests/test_process_email.py index c1179bf..d3316e8 100644 --- a/django_mailbox/tests/test_process_email.py +++ b/django_mailbox/tests/test_process_email.py @@ -87,6 +87,23 @@ class TestProcessEmail(EmailMessageTestCase): 'heart.png', ) + def test_message_with_rfc822_attachment(self): + message = self._get_email_object('message_with_rfc822_attachment.eml') + + mailbox = Mailbox.objects.create() + msg = mailbox.process_incoming_message(message) + + expected_count = 1 + actual_count = msg.attachments.count() + + self.assertEqual( + expected_count, + actual_count, + ) + + attachment = msg.attachments.all()[0] + self.assertIsNone(attachment.get_filename()) + def test_message_with_utf8_attachment_header(self): """ Ensure that we properly handle UTF-8 encoded attachment