mirror of
https://github.com/pacnpal/django-anymail.git
synced 2025-12-20 03:41:05 -05:00
Improve MandrillAPIError.__str__
* Include formatted response from Mandrill API (if any) * Clean up recipient address(es)
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
import json
|
||||
from requests import HTTPError
|
||||
import warnings
|
||||
|
||||
@@ -14,8 +15,15 @@ class MandrillAPIError(HTTPError):
|
||||
message = "Mandrill API response %d" % self.status_code
|
||||
if self.log_message:
|
||||
message += "\n" + self.log_message
|
||||
if self.response:
|
||||
message += "\nResponse: " + getattr(self.response, 'content', "")
|
||||
# Include the Mandrill response, nicely formatted, if possible
|
||||
try:
|
||||
json_response = self.response.json()
|
||||
message += "\nMandrill response:\n" + json.dumps(json_response, indent=2)
|
||||
except (AttributeError, KeyError, ValueError): # not JSON = ValueError
|
||||
try:
|
||||
message += "\nMandrill response: " + self.response.text
|
||||
except AttributeError:
|
||||
pass
|
||||
return message
|
||||
|
||||
|
||||
|
||||
@@ -137,15 +137,16 @@ class DjrillBackend(BaseEmailBackend):
|
||||
message.mandrill_response = None
|
||||
|
||||
if not self.fail_silently:
|
||||
from_email = msg_dict.get('from_email', None)
|
||||
from_message = ""
|
||||
if from_email:
|
||||
from_message = ", from %s" % from_email
|
||||
log_message = "Failed to send a message"
|
||||
if 'to' in msg_dict:
|
||||
log_message += " to " + ','.join(
|
||||
to['email'] for to in msg_dict.get('to', []) if 'email' in to)
|
||||
if 'from_email' in msg_dict:
|
||||
log_message += " from %s" % msg_dict['from_email']
|
||||
raise MandrillAPIError(
|
||||
status_code=response.status_code,
|
||||
response=response,
|
||||
log_message="Failed to send a message to %s%s" %
|
||||
(msg_dict['to'], from_message))
|
||||
log_message=log_message)
|
||||
return False
|
||||
|
||||
# add the response from mandrill to the EmailMessage so callers can inspect it
|
||||
|
||||
@@ -308,6 +308,31 @@ class DjrillBackendTests(DjrillBackendMockAPITestCase):
|
||||
['to@example.com'], fail_silently=True)
|
||||
self.assertEqual(sent, 0)
|
||||
|
||||
def test_api_error_includes_details(self):
|
||||
"""MandrillAPIError should include Mandrill's error message"""
|
||||
msg = mail.EmailMessage('Subject', 'Body', 'from@example.com', ['to@example.com'])
|
||||
|
||||
# JSON error response:
|
||||
error_response = b"""{
|
||||
"status": "error",
|
||||
"code": 12,
|
||||
"name": "Error_Name",
|
||||
"message": "Helpful explanation from Mandrill"
|
||||
}"""
|
||||
self.mock_post.return_value = self.MockResponse(status_code=400, raw=error_response)
|
||||
with self.assertRaisesMessage(MandrillAPIError, "Helpful explanation from Mandrill"):
|
||||
msg.send()
|
||||
|
||||
# Non-JSON error response:
|
||||
self.mock_post.return_value = self.MockResponse(status_code=500, raw=b"Invalid API key")
|
||||
with self.assertRaisesMessage(MandrillAPIError, "Invalid API key"):
|
||||
msg.send()
|
||||
|
||||
# No content in the error response:
|
||||
self.mock_post.return_value = self.MockResponse(status_code=502, raw=None)
|
||||
with self.assertRaises(MandrillAPIError):
|
||||
msg.send()
|
||||
|
||||
|
||||
class DjrillMandrillFeatureTests(DjrillBackendMockAPITestCase):
|
||||
"""Test Djrill backend support for Mandrill-specific features"""
|
||||
|
||||
@@ -76,6 +76,8 @@ Version 1.4 (development):
|
||||
(Specifying a :ref:`Reply-To header <message-headers>`
|
||||
still works, with any version of Django,
|
||||
and will override the reply_to param if you use both.)
|
||||
* Include Mandrill error response in str(MandrillAPIError),
|
||||
to make errors easier to understand.
|
||||
* More-helpful exception when using a non-JSON-serializable
|
||||
type in merge_vars and other Djrill message attributes
|
||||
* Deprecation warnings for upcoming 2.0 changes (see above)
|
||||
|
||||
Reference in New Issue
Block a user