mirror of
https://github.com/pacnpal/django-anymail.git
synced 2025-12-19 19:31:06 -05:00
Mandrill has changed status code for invalid from_email from 500 to 400. (We don't actually care about the specific code, just that the error is caught and reported.)
176 lines
7.4 KiB
Python
176 lines
7.4 KiB
Python
import os
|
|
import unittest
|
|
from email.utils import formataddr
|
|
|
|
from django.core import mail
|
|
from django.test import SimpleTestCase, override_settings, tag
|
|
|
|
from anymail.exceptions import AnymailAPIError, AnymailRecipientsRefused
|
|
from anymail.message import AnymailMessage
|
|
|
|
from .utils import AnymailTestMixin, sample_image_path
|
|
|
|
ANYMAIL_TEST_MANDRILL_API_KEY = os.getenv("ANYMAIL_TEST_MANDRILL_API_KEY")
|
|
ANYMAIL_TEST_MANDRILL_DOMAIN = os.getenv("ANYMAIL_TEST_MANDRILL_DOMAIN")
|
|
|
|
|
|
@tag("mandrill", "live")
|
|
@unittest.skipUnless(
|
|
ANYMAIL_TEST_MANDRILL_API_KEY and ANYMAIL_TEST_MANDRILL_DOMAIN,
|
|
"Set ANYMAIL_TEST_MANDRILL_API_KEY and ANYMAIL_TEST_MANDRILL_DOMAIN "
|
|
"environment variables to run integration tests",
|
|
)
|
|
@override_settings(
|
|
MANDRILL_API_KEY=ANYMAIL_TEST_MANDRILL_API_KEY,
|
|
EMAIL_BACKEND="anymail.backends.mandrill.EmailBackend",
|
|
)
|
|
class MandrillBackendIntegrationTests(AnymailTestMixin, SimpleTestCase):
|
|
"""Mandrill API integration tests
|
|
|
|
These tests run against the **live** Mandrill API, using the
|
|
environment variable `ANYMAIL_TEST_MANDRILL_API_KEY` as the API key.
|
|
If that variable is not set, these tests won't run.
|
|
|
|
See https://mailchimp.com/developer/transactional/docs/fundamentals/#test-mode
|
|
for info on Mandrill test keys.
|
|
"""
|
|
|
|
def setUp(self):
|
|
super().setUp()
|
|
self.from_email = self.addr("from")
|
|
self.message = mail.EmailMultiAlternatives(
|
|
"Anymail Mandrill integration test",
|
|
"Text content",
|
|
self.from_email,
|
|
[self.addr("test+to1")],
|
|
)
|
|
self.message.attach_alternative("<p>HTML content</p>", "text/html")
|
|
|
|
def addr(self, username, display_name=None):
|
|
"""Construct test email address within our test domain"""
|
|
# Because integration tests run within a Mandrill trial account,
|
|
# both sender and recipient addresses must be within the test domain.
|
|
# (Other recipient addresses will be rejected with 'recipient-domain-mismatch'.)
|
|
email = "{username}@{domain}".format(
|
|
username=username, domain=ANYMAIL_TEST_MANDRILL_DOMAIN
|
|
)
|
|
if display_name is not None:
|
|
return formataddr((display_name, email))
|
|
else:
|
|
return email
|
|
|
|
def test_simple_send(self):
|
|
# Example of getting the Mandrill send status and _id from the message
|
|
sent_count = self.message.send()
|
|
self.assertEqual(sent_count, 1)
|
|
|
|
# noinspection PyUnresolvedReferences
|
|
anymail_status = self.message.anymail_status
|
|
to_email = self.message.to[0] # test+to1@{ANYMAIL_TEST_MANDRILL_DOMAIN}
|
|
sent_status = anymail_status.recipients[to_email].status
|
|
message_id = anymail_status.recipients[to_email].message_id
|
|
|
|
# successful send (could still bounce later):
|
|
self.assertIn(sent_status, ["sent", "queued"])
|
|
# don't know what it'll be, but it should exist:
|
|
self.assertGreater(len(message_id), 0)
|
|
|
|
# set of all recipient statuses:
|
|
self.assertEqual(anymail_status.status, {sent_status})
|
|
# because only a single recipient (else would be a set):
|
|
self.assertEqual(anymail_status.message_id, message_id)
|
|
|
|
def test_all_options(self):
|
|
message = AnymailMessage(
|
|
subject="Anymail Mandrill all-options integration test",
|
|
body="This is the text body",
|
|
from_email=self.addr("from", "Test From, with comma"),
|
|
to=[self.addr("test+to1"), self.addr("test+to2", "Recipient 2")],
|
|
cc=[self.addr("test+cc1"), self.addr("test+cc2", "Copy 2")],
|
|
bcc=[self.addr("test+bcc1"), self.addr("test+bcc2", "Blind Copy 2")],
|
|
reply_to=["reply1@example.com", "Reply 2 <reply2@example.com>"],
|
|
headers={"X-Anymail-Test": "value"},
|
|
# no metadata, send_at, track_clicks support
|
|
tags=["tag 1"], # max one tag
|
|
track_opens=True,
|
|
)
|
|
message.attach("attachment1.txt", "Here is some\ntext for you", "text/plain")
|
|
message.attach("attachment2.csv", "ID,Name\n1,Amy Lina", "text/csv")
|
|
cid = message.attach_inline_image_file(sample_image_path())
|
|
message.attach_alternative(
|
|
"<p><b>HTML:</b> with <a href='http://example.com'>link</a>"
|
|
"and image: <img src='cid:%s'></div>" % cid,
|
|
"text/html",
|
|
)
|
|
|
|
message.send()
|
|
self.assertTrue(message.anymail_status.status.issubset({"queued", "sent"}))
|
|
|
|
def test_invalid_from(self):
|
|
# Example of trying to send from an invalid address
|
|
self.message.from_email = (
|
|
"webmaster@localhost" # Django default DEFAULT_FROM_EMAIL
|
|
)
|
|
with self.assertRaisesMessage(AnymailAPIError, "email address is invalid"):
|
|
self.message.send()
|
|
|
|
def test_invalid_to(self):
|
|
# Example of detecting when a recipient is not a valid email address
|
|
self.message.to = ["invalid@localhost"]
|
|
try:
|
|
self.message.send()
|
|
except AnymailRecipientsRefused:
|
|
# Mandrill refused to deliver the mail -- message.anymail_status
|
|
# will tell you why:
|
|
# noinspection PyUnresolvedReferences
|
|
anymail_status = self.message.anymail_status
|
|
self.assertEqual(
|
|
anymail_status.recipients["invalid@localhost"].status, "invalid"
|
|
)
|
|
self.assertEqual(anymail_status.status, {"invalid"})
|
|
else:
|
|
# Sometimes Mandrill queues these test sends
|
|
# noinspection PyUnresolvedReferences
|
|
if self.message.anymail_status.status == {"queued"}:
|
|
self.skipTest("Mandrill queued the send -- can't complete this test")
|
|
else:
|
|
self.fail(
|
|
"Anymail did not raise AnymailRecipientsRefused"
|
|
" for invalid recipient"
|
|
)
|
|
|
|
def test_rejected_to(self):
|
|
# Example of detecting when a recipient is on Mandrill's rejection blacklist
|
|
self.message.to = ["reject@test.mandrillapp.com"]
|
|
try:
|
|
self.message.send()
|
|
except AnymailRecipientsRefused:
|
|
# Mandrill refused to deliver the mail -- message.anymail_status will
|
|
# tell you why:
|
|
# noinspection PyUnresolvedReferences
|
|
anymail_status = self.message.anymail_status
|
|
self.assertEqual(
|
|
anymail_status.recipients["reject@test.mandrillapp.com"].status,
|
|
"rejected",
|
|
)
|
|
self.assertEqual(anymail_status.status, {"rejected"})
|
|
else:
|
|
# Sometimes Mandrill queues these test sends
|
|
# noinspection PyUnresolvedReferences
|
|
if self.message.anymail_status.status == {"queued"}:
|
|
self.skipTest("Mandrill queued the send -- can't complete this test")
|
|
else:
|
|
self.fail(
|
|
"Anymail did not raise AnymailRecipientsRefused"
|
|
" for blacklist recipient"
|
|
)
|
|
|
|
@override_settings(MANDRILL_API_KEY="Hey, that's not an API key!")
|
|
def test_invalid_api_key(self):
|
|
# Example of trying to send with an invalid MANDRILL_API_KEY.
|
|
# Mandrill responds either 401 or 500 status for this case (it varies),
|
|
# but always seems to include the message "Invalid API key".
|
|
# Either response should result in an AnymailAPIError.
|
|
with self.assertRaisesMessage(AnymailAPIError, "Invalid API key"):
|
|
self.message.send()
|