Add the Mandrill send API response to EmailMessage as a property, mandrill_response, when a message is sent. For errors, set mandrill_response to None. Add tests & docs.

This commit is contained in:
Eric Hennings
2013-12-22 14:12:57 -08:00
parent 08141a3003
commit e1c78ec197
4 changed files with 62 additions and 3 deletions

View File

@@ -105,6 +105,10 @@ class DjrillBackend(BaseEmailBackend):
response = requests.post(api_url, data=json.dumps(api_params, cls=JSONDateUTCEncoder)) response = requests.post(api_url, data=json.dumps(api_params, cls=JSONDateUTCEncoder))
if response.status_code != 200: if response.status_code != 200:
# add a mandrill_response for the sake of being explicit
message.mandrill_response = None
if not self.fail_silently: if not self.fail_silently:
raise MandrillAPIError( raise MandrillAPIError(
status_code=response.status_code, status_code=response.status_code,
@@ -112,6 +116,10 @@ class DjrillBackend(BaseEmailBackend):
log_message="Failed to send a message to %s, from %s" % log_message="Failed to send a message to %s, from %s" %
(msg_dict['to'], msg_dict['from_email'])) (msg_dict['to'], msg_dict['from_email']))
return False return False
# add the response from mandrill to the EmailMessage so callers can inspect it
message.mandrill_response = response.json()
return True return True
def _build_standard_message_dict(self, message): def _build_standard_message_dict(self, message):
@@ -302,4 +310,3 @@ class DjrillBackend(BaseEmailBackend):
'content': content_b64.decode('ascii'), 'content': content_b64.decode('ascii'),
} }
return mandrill_attachment, is_embedded_image return mandrill_attachment, is_embedded_image

View File

@@ -10,9 +10,13 @@ class DjrillBackendMockAPITestCase(TestCase):
class MockResponse: class MockResponse:
"""requests.post return value mock sufficient for DjrillBackend""" """requests.post return value mock sufficient for DjrillBackend"""
def __init__(self, status_code=200, content="{}"): def __init__(self, status_code=200, content="{}", json=['']):
self.status_code = status_code self.status_code = status_code
self.content = content self.content = content
self._json = json
def json(self):
return self._json
def setUp(self): def setUp(self):
self.patch = patch('requests.post', autospec=True) self.patch = patch('requests.post', autospec=True)

View File

@@ -10,9 +10,9 @@ from django.core.exceptions import ImproperlyConfigured
from django.core.mail import make_msgid from django.core.mail import make_msgid
from djrill import MandrillAPIError, NotSupportedByMandrillError from djrill import MandrillAPIError, NotSupportedByMandrillError
from djrill.mail.backends.djrill import DjrillBackend
from djrill.tests.mock_backend import DjrillBackendMockAPITestCase from djrill.tests.mock_backend import DjrillBackendMockAPITestCase
def decode_att(att): def decode_att(att):
"""Returns the original data from base64-encoded attachment content""" """Returns the original data from base64-encoded attachment content"""
return b64decode(att.encode('ascii')) return b64decode(att.encode('ascii'))
@@ -459,4 +459,20 @@ class DjrillMandrillFeatureTests(DjrillBackendMockAPITestCase):
self.assertFalse('async' in data) self.assertFalse('async' in data)
self.assertFalse('ip_pool' in data) self.assertFalse('ip_pool' in data)
def test_send_attaches_mandrill_response(self):
""" The mandrill_response should be attached to the message when it is sent """
response = [{u'status': u'sent', u'_id': u'd2dc8a04fedb463398d2c124fd0f1774',
u'email': u'someone@example.com', u'reject_reason': None}]
self.mock_post.return_value = self.MockResponse(json=response)
msg = mail.EmailMessage('Subject', 'Message', 'from@example.com', ['to1@example.com'],)
sent = msg.send()
self.assertEqual(sent, 1)
self.assertEqual(msg.mandrill_response, response)
def test_send_failed_mandrill_response(self):
""" If the send fails, mandrill_response should be set to None """
self.mock_post.return_value = self.MockResponse(status_code=500)
msg = mail.EmailMessage('Subject', 'Message', 'from@example.com', ['to1@example.com'],)
sent = msg.send(fail_silently=True)
self.assertEqual(sent, 0)
self.assertIsNone(msg.mandrill_response)

View File

@@ -272,6 +272,38 @@ If you have questions about the python syntax for any of these properties,
see :class:`DjrillMandrillFeatureTests` in :file:`tests/test_mandrill_send.py` for examples. see :class:`DjrillMandrillFeatureTests` in :file:`tests/test_mandrill_send.py` for examples.
.. _mandrill-response:
Mandrill Response
---------------------------------
A ``mandrill_response`` property is added to each :class:`~django.core.mail.EmailMessage` that you
send. This allows you to retrieve message ids, initial status information and more.
For an EmailMessage that is successfully sent to one or more email addresses, ``mandrill_response`` will
be set to a ``list`` of ``dict``, where each entry has info for one email address. See the Mandrill docs for the
/messages/send api for full details.
For example, to get the Mandrill message id for a sent email you might do this::
msg = EmailMultiAlternatives(subject="subject", body="body",
from_email="sender@example.com",to=["someone@example.com"])
msg.send()
response = msg.mandrill_response[0]
mandrill_id = response['_id']
For this example, msg.mandrill_response might look like this::
msg.mandrill_response = [
{
"email": "someone@example.com",
"status": "sent",
"_id": "abc123abc123abc123abc123abc123"
}
]
If an error is returned by Mandrill while sending the message then ``mandrill_response`` will be set to None.
.. _djrill-exceptions: .. _djrill-exceptions:
Exceptions Exceptions