Allow html from any EmailMultiAlternatives (not just DjrillMessage)

Includes type-checking on alternative message part, and switches
to ValueError (rather than ImproperlyConfigured) for unacceptable
alternatives.

[Also fixes bug where fail_silently=True wasn't respected.]

Cherry-picked from: medmunds/Djrill@faf53a1a0
(and parts of medmunds/Djrill@62d48c5f)
This commit is contained in:
medmunds
2012-11-15 16:17:16 -08:00
parent 1901fd444e
commit c23696a590
2 changed files with 56 additions and 9 deletions

View File

@@ -26,7 +26,7 @@ class DjrillBackend(BaseEmailBackend):
Mandrill API Email Backend
"""
def __init__(self, fail_silently=False, **kwargs):
def __init__(self, **kwargs):
"""
Set the API key, API url and set the action url.
"""
@@ -71,8 +71,13 @@ class DjrillBackend(BaseEmailBackend):
if getattr(message, "alternative_subtype", None):
if message.alternative_subtype == "mandrill":
self._build_advanced_message_dict(message)
if message.alternatives:
self._add_alternatives(message)
try:
if getattr(message, 'alternatives', None):
self._add_alternatives(message)
except ValueError:
if not self.fail_silently:
raise
return False
djrill_it = requests.post(self.api_action, data=json.dumps({
"key": self.api_key,
@@ -121,23 +126,29 @@ class DjrillBackend(BaseEmailBackend):
"from_name": message.from_name,
"tags": message.tags,
"track_opens": message.track_opens,
"track_clicks": message.track_clicks
})
def _add_alternatives(self, message):
"""
There can be only one! ... alternative attachment.
There can be only one! ... alternative attachment, and it must be text/html.
Since mandrill does not accept image attachments or anything other
than HTML, the assumption is the only thing you are attaching is
the HTML output for your email.
"""
if len(message.alternatives) > 1:
raise ImproperlyConfigured(
"Mandrill only accepts plain text and html emails. Please "
"check the alternatives you have attached to your message.")
raise ValueError(
"Too many alternatives attached to the message. "
"Mandrill only accepts plain text and html emails.")
(content, mimetype) = message.alternatives[0]
if mimetype != 'text/html':
raise ValueError("Invalid alternative mimetype '%s'. "
"Mandrill only accepts plain text and html emails."
% mimetype)
self.msg_dict.update({
"html": message.alternatives[0][0],
"track_clicks": message.track_clicks
"html": message.alternatives[0][0]
})

View File

@@ -92,6 +92,42 @@ class DjrillBackendTests(DjrillBackendMockAPITestCase):
self.assertEqual(data['message']['to'][4]['email'], "bcc1@example.com")
self.assertEqual(data['message']['to'][5]['email'], "bcc2@example.com")
def test_html_message(self):
text_content = 'This is an important message.'
html_content = '<p>This is an <strong>important</strong> message.</p>'
email = mail.EmailMultiAlternatives('Subject', text_content,
'from@example.com', ['to@example.com'])
email.attach_alternative(html_content, "text/html")
email.send()
data = self.get_api_call_data()
self.assertEqual(data['message']['text'], text_content)
self.assertEqual(data['message']['html'], html_content)
def test_alternative_errors(self):
# Multiple alternatives not allowed
email = mail.EmailMultiAlternatives('Subject', 'Body',
'from@example.com', ['to@example.com'])
email.attach_alternative("<p>First html is OK</p>", "text/html")
email.attach_alternative("<p>But not second html</p>", "text/html")
with self.assertRaises(ValueError):
email.send()
# Only html alternatives allowed
email = mail.EmailMultiAlternatives('Subject', 'Body',
'from@example.com', ['to@example.com'])
email.attach_alternative("{'not': 'allowed'}", "application/json")
with self.assertRaises(ValueError):
email.send()
# Make sure fail_silently is respected
email = mail.EmailMultiAlternatives('Subject', 'Body',
'from@example.com', ['to@example.com'])
email.attach_alternative("{'not': 'allowed'}", "application/json")
sent = email.send(fail_silently=True)
self.assertFalse(self.mock_post.called,
msg="Mandrill API should not be called when send fails silently")
self.assertEqual(sent, 0)
class DjrillMessageTests(TestCase):
def setUp(self):