From 91b846fea31f6d1531bc134a37afa6603d3bd7ad Mon Sep 17 00:00:00 2001 From: Chris Jones Date: Tue, 28 Feb 2012 13:03:26 -0800 Subject: [PATCH] DjrillMessage which wraps Django's EmailMultiAlternatives. Mail backend now works with standard email and multipart through the DjrillMessage object. --- djrill/mail/__init__.py | 37 +++++++++++++++++++++++ djrill/mail/backends/djrill.py | 54 +++++++++++++++++++++++++++------- 2 files changed, 81 insertions(+), 10 deletions(-) diff --git a/djrill/mail/__init__.py b/djrill/mail/__init__.py index e69de29..960e87a 100644 --- a/djrill/mail/__init__.py +++ b/djrill/mail/__init__.py @@ -0,0 +1,37 @@ +from django.core.exceptions import ImproperlyConfigured +from django.core.mail import EmailMultiAlternatives + + +class DjrillMessage(EmailMultiAlternatives): + alternative_subtype = "mandrill" + + def __init__(self, subject='', body='', from_email=None, to=None, bcc=None, + connection=None, attachments=None, headers=None, alternatives=None, + cc=None, tags=None, track_opens=True, track_clicks=True): + + super(DjrillMessage, self).__init__(subject, body, from_email, to, bcc, + connection, attachments, headers, alternatives, cc) + + self.tags = self._set_mandrill_tags(tags) + self.track_opens = track_opens + self.track_clicks = track_clicks + + def _set_mandrill_tags(self, tags): + """ + Check that all tags are below 50 chars and that they do not start + with an underscore. + + Raise ImproperlyConfigured if an underscore tag is passed in to + alert the user. Any tag over 50 chars is left out of the list. + """ + tag_list = [] + + for tag in tags: + if len(tag) <= 50 and not tag.startswith("_"): + tag_list.append(tag) + elif tag.startswith("_"): + raise ImproperlyConfigured( + "Tags starting with an underscore are reserved for " + "internal use and will cause errors with Mandill's API") + + return tag_list diff --git a/djrill/mail/backends/djrill.py b/djrill/mail/backends/djrill.py index dc73231..f9acbe5 100644 --- a/djrill/mail/backends/djrill.py +++ b/djrill/mail/backends/djrill.py @@ -69,23 +69,21 @@ class DjrillBackend(BaseEmailBackend): if not message.recipients(): return False - sender = sanitize_address(message.from_email, message.encoding) + self.sender = sanitize_address(message.from_email, message.encoding) recipients_list = [sanitize_address(addr, message.encoding) for addr in message.recipients()] from email.utils import parseaddr - recipients = [{"email": e, "name": n} for n,e in [ + self.recipients = [{"email": e, "name": n} for n,e in [ parseaddr(r) for r in recipients_list]] + self.msg_dict = self._build_standard_message_dict(message) + + if message.alternative_subtype == "mandrill" and message.alternatives: + self._add_alternatives(message) + djrill_it = requests.post(self.api_action, data=json.dumps({ "key": self.api_key, - "message": { - "html": message.body, - "text": message.body, - "subject": message.subject, - "from_email": sender, - "from_name": "Devs", - "to": recipients - } + "message": self.msg_dict })) if djrill_it.status_code != 200: @@ -93,3 +91,39 @@ class DjrillBackend(BaseEmailBackend): raise return False return True + + def _build_standard_message_dict(self, message): + """ + Build standard message dict. + + Builds the standard dict that Django's send_mail and send_mass_mail + use by default. Standard text email messages sent through Django will + still work through Mandrill. + """ + return { + "text": message.body, + "subject": message.subject, + "from_email": self.sender, + "from_name": "Devs - FIX ME", + "to": self.recipients + } + + def _add_alternatives(self, message): + """ + There can be only one! ... alternative attachment. + + 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.") + + self.msg_dict.update({ + "html": message.alternatives[0][0], + "tags": message.tags, + "track_opens": message.track_opens, + "track_clicks": message.track_clicks + })