Mailgun: improve API error messages

This commit is contained in:
medmunds
2021-01-26 16:29:14 -08:00
committed by Mike Edmunds
parent 2196ab8330
commit d33c9ea4ed
6 changed files with 95 additions and 2 deletions

View File

@@ -21,12 +21,22 @@ class RequestsBackendMockAPITestCase(AnymailTestMixin, SimpleTestCase):
class MockResponse(requests.Response):
"""requests.request return value mock sufficient for testing"""
def __init__(self, status_code=200, raw=b"RESPONSE", encoding='utf-8', reason=None):
def __init__(self, status_code=200, raw=b"RESPONSE", encoding='utf-8', reason=None, test_case=None):
super().__init__()
self.status_code = status_code
self.encoding = encoding
self.reason = reason or ("OK" if 200 <= status_code < 300 else "ERROR")
self.raw = BytesIO(raw)
self.test_case = test_case
@property
def url(self):
return self.test_case.get_api_call_arg('url', required=False)
@url.setter
def url(self, url):
if url is not None:
raise ValueError("MockResponse can't handle url assignment")
def setUp(self):
super().setUp()
@@ -38,7 +48,7 @@ class RequestsBackendMockAPITestCase(AnymailTestMixin, SimpleTestCase):
def set_mock_response(self, status_code=DEFAULT_STATUS_CODE, raw=UNSET, encoding='utf-8', reason=None):
if raw is UNSET:
raw = self.DEFAULT_RAW_RESPONSE
mock_response = self.MockResponse(status_code, raw=raw, encoding=encoding, reason=reason)
mock_response = self.MockResponse(status_code, raw=raw, encoding=encoding, reason=reason, test_case=self)
self.mock_request.return_value = mock_response
return mock_response

View File

@@ -667,6 +667,31 @@ class MailgunBackendAnymailFeatureTests(MailgunBackendMockAPITestCase):
self.message.send()
self.assert_esp_called('/example.com%20%23%20oops/messages')
def test_unknown_sender_domain(self):
self.set_mock_response(raw=b"""{
"message": "Domain not found: example.com"
}""", status_code=404)
with self.assertRaisesMessage(
AnymailAPIError,
"Unknown sender domain 'example.com'.\n"
"Check the domain is verified with Mailgun, and that the ANYMAIL MAILGUN_API_URL"
" setting 'https://api.mailgun.net/v3/' is the correct region."
):
self.message.send()
@override_settings(
# This is *not* a valid MAILGUN_API_URL setting (it should end at "...v3/"):
ANYMAIL_MAILGUN_API_URL='https://api.mailgun.net/v3/example.com/messages')
def test_magnificent_api(self):
# (Wouldn't a truly "magnificent API" just provide a helpful error message?)
self.set_mock_response(raw=b"Mailgun Magnificent API", status_code=200)
with self.assertRaisesMessage(
AnymailAPIError,
"Invalid Mailgun API endpoint 'https://api.mailgun.net/v3/example.com/messages/example.com/messages'.\n"
"Check your ANYMAIL MAILGUN_SENDER_DOMAIN and MAILGUN_API_URL settings."
):
self.message.send()
def test_default_omits_options(self):
"""Make sure by default we don't send any ESP-specific options.

View File

@@ -196,6 +196,29 @@ class MailgunInboundTestCase(WebhookTestCase):
self.client.post('/anymail/mailgun/inbound/',
data=json.dumps(raw_event), content_type='application/json')
def test_misconfigured_store_action(self):
# store() notification includes "attachments" json; forward() includes "attachment-count"
raw_event = mailgun_sign_legacy_payload({
'token': '06c96bafc3f42a66b9edd546347a2fe18dc23461fe80dc52f0',
'timestamp': '1461261330',
'recipient': 'test@inbound.example.com',
'sender': 'envelope-from@example.org',
'body-plain': 'Test body plain',
'body-html': '<div>Test body html</div>',
'attachments': json.dumps([{
"url": "https://storage.mailgun.net/v3/domains/example.com/messages/MESSAGE_KEY/attachments/0",
"content-type": "application/pdf",
"name": "attachment.pdf",
"size": 20202
}]),
})
with self.assertRaisesMessage(
AnymailConfigurationError,
"You seem to have configured Mailgun's receiving route using the store() action."
" Anymail's inbound webhook requires the forward() action."
):
self.client.post('/anymail/mailgun/inbound/', data=raw_event)
def test_misconfigured_tracking_legacy(self):
raw_event = mailgun_sign_legacy_payload({
'domain': 'example.com',