Raise error for invalid/rejected recipients

Raise new MandrillRecipientsRefused exception
when Mandrill returns 'reject' or 'invalid' status
for *all* recipients of a message.

(Similar to Django's SMTP email backend raising
SMTPRecipientsRefused.)

Add setting MANDRILL_IGNORE_RECIPIENT_STATUS
to override the new exception.

Trap JSON parsing errors in Mandrill API response,
and raise MandrillAPIError for them. (Helps with #93.)

Closes #80.
Closes #81.
This commit is contained in:
medmunds
2015-12-01 13:26:21 -08:00
parent 8433e6d660
commit d14b87c910
9 changed files with 204 additions and 37 deletions

View File

@@ -18,7 +18,7 @@ from django.core.mail import make_msgid
from django.test import TestCase
from django.test.utils import override_settings
from djrill import MandrillAPIError, NotSupportedByMandrillError
from djrill import MandrillAPIError, MandrillRecipientsRefused, NotSupportedByMandrillError
from .mock_backend import DjrillBackendMockAPITestCase
@@ -515,7 +515,7 @@ class DjrillMandrillFeatureTests(DjrillBackendMockAPITestCase):
def test_send_attaches_mandrill_response(self):
""" The mandrill_response should be attached to the message when it is sent """
response = [{'mandrill_response': 'would_be_here'}]
response = [{'email': 'to1@example.com', 'status': 'sent'}]
self.mock_post.return_value = self.MockResponse(raw=six.b(json.dumps(response)))
msg = mail.EmailMessage('Subject', 'Message', 'from@example.com', ['to1@example.com'],)
sent = msg.send()
@@ -530,6 +530,14 @@ class DjrillMandrillFeatureTests(DjrillBackendMockAPITestCase):
self.assertEqual(sent, 0)
self.assertIsNone(msg.mandrill_response)
def test_send_unparsable_mandrill_response(self):
"""If the send succeeds, but a non-JSON API response, should raise an API exception"""
self.mock_post.return_value = self.MockResponse(status_code=500, raw=b"this isn't json")
msg = mail.EmailMessage('Subject', 'Message', 'from@example.com', ['to1@example.com'],)
with self.assertRaises(MandrillAPIError):
msg.send()
self.assertIsNone(msg.mandrill_response)
def test_json_serialization_errors(self):
"""Try to provide more information about non-json-serializable data"""
self.message.global_merge_vars = {'PRICE': Decimal('19.99')}
@@ -547,6 +555,51 @@ class DjrillMandrillFeatureTests(DjrillBackendMockAPITestCase):
self.message.send()
class DjrillRecipientsRefusedTests(DjrillBackendMockAPITestCase):
"""Djrill raises MandrillRecipientsRefused when *all* recipients are rejected or invalid"""
def test_recipients_refused(self):
msg = mail.EmailMessage('Subject', 'Body', 'from@example.com',
['invalid@localhost', 'reject@test.mandrillapp.com'])
self.mock_post.return_value = self.MockResponse(status_code=200, raw=b"""
[{ "email": "invalid@localhost", "status": "invalid" },
{ "email": "reject@test.mandrillapp.com", "status": "rejected" }]""")
with self.assertRaises(MandrillRecipientsRefused):
msg.send()
def test_fail_silently(self):
self.mock_post.return_value = self.MockResponse(status_code=200, raw=b"""
[{ "email": "invalid@localhost", "status": "invalid" },
{ "email": "reject@test.mandrillapp.com", "status": "rejected" }]""")
sent = mail.send_mail('Subject', 'Body', 'from@example.com',
['invalid@localhost', 'reject@test.mandrillapp.com'],
fail_silently=True)
self.assertEqual(sent, 0)
def test_mixed_response(self):
"""If *any* recipients are valid or queued, no exception is raised"""
msg = mail.EmailMessage('Subject', 'Body', 'from@example.com',
['invalid@localhost', 'valid@example.com',
'reject@test.mandrillapp.com', 'also.valid@example.com'])
self.mock_post.return_value = self.MockResponse(status_code=200, raw=b"""
[{ "email": "invalid@localhost", "status": "invalid" },
{ "email": "valid@example.com", "status": "sent" },
{ "email": "reject@test.mandrillapp.com", "status": "rejected" },
{ "email": "also.valid@example.com", "status": "queued" }]""")
sent = msg.send()
self.assertEqual(sent, 1) # one message sent, successfully, to 2 of 4 recipients
@override_settings(MANDRILL_IGNORE_RECIPIENT_STATUS=True)
def test_settings_override(self):
"""Setting restores Djrill 1.x behavior"""
self.mock_post.return_value = self.MockResponse(status_code=200, raw=b"""
[{ "email": "invalid@localhost", "status": "invalid" },
{ "email": "reject@test.mandrillapp.com", "status": "rejected" }]""")
sent = mail.send_mail('Subject', 'Body', 'from@example.com',
['invalid@localhost', 'reject@test.mandrillapp.com'])
self.assertEqual(sent, 1) # refused message is included in sent count
@override_settings(MANDRILL_SETTINGS={
'from_name': 'Djrill Test',
'important': True,