diff --git a/README.rst b/README.rst index c9113b6..99c5c6a 100644 --- a/README.rst +++ b/README.rst @@ -134,10 +134,10 @@ Djrill supports most of the functionality of Django's `EmailMessage`_ and raise a ``djrill.NotSupportedByMandrillError`` exception when you attempt to send the message. (Mandrill doesn't support sending multiple html alternative parts, or any non-html alternatives.) -* Djrill attempts to include a message's attachments, but Mandrill will - (silently) ignore any attachment types it doesn't allow. According to - Mandrill's docs, attachments are only allowed with the mimetypes "text/\*", - "image/\*", or "application/pdf". +* Djrill includes a message's attachments, but only with the mimetypes "text/\*", + "image/\*", or "application/pdf" (since that is all Mandrill allows). Any + other attachment types will raise a ``djrill.NotSupportedByMandrillError`` + exception when you attempt to send the message. * Djrill treats all cc and bcc recipients as if they were additional "to" addresses. (Mandrill does not distinguish cc, and only allows a single bcc -- which Djrill doesn't use. *Caution:* depending on the ``preserve_recipients`` diff --git a/djrill/mail/backends/djrill.py b/djrill/mail/backends/djrill.py index 73b8a42..98466a3 100644 --- a/djrill/mail/backends/djrill.py +++ b/djrill/mail/backends/djrill.py @@ -226,6 +226,18 @@ class DjrillBackend(BaseEmailBackend): if mimetype is None: mimetype = DEFAULT_ATTACHMENT_MIME_TYPE + # Mandrill silently filters attachments with unsupported mimetypes. + # This can be confusing, so we raise an exception instead. + (main, sub) = mimetype.lower().split('/') + attachment_allowed = ( + main == 'text' or main == 'image' + or (main == 'application' and sub == 'pdf')) + if not attachment_allowed: + raise NotSupportedByMandrillError( + "Invalid attachment mimetype '%s'. Mandrill only supports " + "text/*, image/*, and application/pdf attachments." + % mimetype) + return { 'type': mimetype, 'name': filename or "", diff --git a/djrill/tests/test_mandrill_send.py b/djrill/tests/test_mandrill_send.py index 2565ac1..2a86147 100644 --- a/djrill/tests/test_mandrill_send.py +++ b/djrill/tests/test_mandrill_send.py @@ -160,6 +160,24 @@ class DjrillBackendTests(DjrillBackendMockAPITestCase): msg="Mandrill API should not be called when send fails silently") self.assertEqual(sent, 0) + def test_attachment_errors(self): + # Mandrill silently strips attachments that aren't text/*, image/*, + # or application/pdf. We want to alert the Djrill user: + with self.assertRaises(NotSupportedByMandrillError): + msg = mail.EmailMessage('Subject', 'Body', + 'from@example.com', ['to@example.com']) + # This is the default mimetype, but won't work with Mandrill: + msg.attach(content="test", mimetype="application/octet-stream") + msg.send() + + with self.assertRaises(NotSupportedByMandrillError): + msg = mail.EmailMessage('Subject', 'Body', + 'from@example.com', ['to@example.com']) + # Can't send Office docs, either: + msg.attach(filename="presentation.ppt", content="test", + mimetype="application/vnd.ms-powerpoint") + msg.send() + def test_mandrill_api_failure(self): self.mock_post.return_value = self.MockResponse(status_code=400) with self.assertRaises(MandrillAPIError):