From 9a6eb78db5cd929e739a0f06b6fcaa7da94826fe Mon Sep 17 00:00:00 2001 From: medmunds Date: Tue, 11 Dec 2012 10:28:12 -0800 Subject: [PATCH 1/5] One more try on correct Travis-CI links --- README.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.rst b/README.rst index 364d2dc..1834032 100644 --- a/README.rst +++ b/README.rst @@ -1,8 +1,8 @@ Djrill, for Mandrill ==================== -.. image:: https://secure.travis-ci.org/brack3t/Djrill.png - :target: https://secure.travis-ci.org/brack3t/Djrill +.. image:: https://secure.travis-ci.org/brack3t/Djrill.png?branch=master + :target: https://travis-ci.org/brack3t/Djrill Djrill is an email backend and new message class for Django users that want to take advantage of the Mandrill_ transactional email service from MailChimp_. @@ -164,8 +164,8 @@ Djrill is tested against Django 1.3 and 1.4 on Python 2.6 and 2.7. (It may also work with Django 1.2 and Python 2.5, if you use an older version of requests compatible with that code.) -.. image:: https://secure.travis-ci.org/brack3t/Djrill.png - :target: https://secure.travis-ci.org/brack3t/Djrill +.. image:: https://secure.travis-ci.org/brack3t/Djrill.png?branch=master + :target: https://travis-ci.org/brack3t/Djrill The included tests verify that Djrill constructs the expected Mandrill API calls, without actually calling Mandrill or sending any email. So the tests From b0da1cf9538c0da875bb538d53e6da851a01e776 Mon Sep 17 00:00:00 2001 From: medmunds Date: Tue, 11 Dec 2012 10:49:43 -0800 Subject: [PATCH 2/5] DjrillMessage class fixes * Don't crash if no tags * Allow `None` to omit options entirely from Mandrill send call * Default `preserve_recipients` to None (= use setting from Mandrill account) * ImproperlyConfigured --> ValueError for bad tags --- djrill/mail/__init__.py | 24 ++++++++++++++---------- djrill/tests.py | 14 +++++++++++++- 2 files changed, 27 insertions(+), 11 deletions(-) diff --git a/djrill/mail/__init__.py b/djrill/mail/__init__.py index d406e90..d38bed9 100644 --- a/djrill/mail/__init__.py +++ b/djrill/mail/__init__.py @@ -1,4 +1,3 @@ -from django.core.exceptions import ImproperlyConfigured from django.core.mail import EmailMultiAlternatives @@ -8,23 +7,28 @@ class DjrillMessage(EmailMultiAlternatives): def __init__(self, subject='', body='', from_email=None, to=None, bcc=None, connection=None, attachments=None, headers=None, alternatives=None, cc=None, from_name=None, tags=None, track_opens=True, - track_clicks=True, preserve_recipients=False): + track_clicks=True, preserve_recipients=None): super(DjrillMessage, self).__init__(subject, body, from_email, to, bcc, connection, attachments, headers, alternatives, cc) - self.from_name = from_name - self.tags = self._set_mandrill_tags(tags) - self.track_opens = track_opens - self.track_clicks = track_clicks - self.preserve_recipients = preserve_recipients + if from_name: + self.from_name = from_name + if tags: + self.tags = self._set_mandrill_tags(tags) + if track_opens is not None: + self.track_opens = track_opens + if track_clicks is not None: + self.track_clicks = track_clicks + if preserve_recipients is not None: + self.preserve_recipients = preserve_recipients 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 + Raise ValueError if an underscore tag is passed in to alert the user. Any tag over 50 chars is left out of the list. """ tag_list = [] @@ -33,8 +37,8 @@ class DjrillMessage(EmailMultiAlternatives): if len(tag) <= 50 and not tag.startswith("_"): tag_list.append(tag) elif tag.startswith("_"): - raise ImproperlyConfigured( + raise ValueError( "Tags starting with an underscore are reserved for " - "internal use and will cause errors with Mandill's API") + "internal use and will cause errors with Mandrill's API") return tag_list diff --git a/djrill/tests.py b/djrill/tests.py index 7c9e175..3ecef10 100644 --- a/djrill/tests.py +++ b/djrill/tests.py @@ -392,7 +392,7 @@ class DjrillMessageTests(TestCase): self.assertEqual(msg.alternatives[0][0], self.html_content) def test_djrill_message_tag_failure(self): - with self.assertRaises(ImproperlyConfigured): + with self.assertRaises(ValueError): DjrillMessage(self.subject, self.text_content, self.from_email, self.to, tags=["_fail"]) @@ -409,3 +409,15 @@ class DjrillMessageTests(TestCase): self.assertIn(tags[0], msg.tags) self.assertIn(tags[1], msg.tags) self.assertNotIn(tags[2], msg.tags) + + def test_djrill_message_no_options(self): + """DjrillMessage with only basic EmailMessage options should work""" + msg = DjrillMessage(self.subject, self.text_content, + self.from_email, self.to) # no Mandrill-specific options + + self.assertIsInstance(msg, DjrillMessage) + self.assertEqual(msg.body, self.text_content) + self.assertEqual(msg.recipients(), self.to) + self.assertFalse(hasattr(msg, 'tags')) + self.assertFalse(hasattr(msg, 'from_name')) + self.assertFalse(hasattr(msg, 'preserve_recipients')) From 2a2ca6c137ee12d555e87ce9db217bbf19efbe94 Mon Sep 17 00:00:00 2001 From: medmunds Date: Tue, 11 Dec 2012 10:55:01 -0800 Subject: [PATCH 3/5] Unclosed
in admin status.html --- djrill/templates/djrill/status.html | 1 + 1 file changed, 1 insertion(+) diff --git a/djrill/templates/djrill/status.html b/djrill/templates/djrill/status.html index 63f7731..33dac6f 100644 --- a/djrill/templates/djrill/status.html +++ b/djrill/templates/djrill/status.html @@ -61,6 +61,7 @@
{{ term|capfirst }}
{{ value }}
{% endfor %} +
{% endblock %} From bc9e6212a6ecf7b913ac332598316ecfb16638e1 Mon Sep 17 00:00:00 2001 From: medmunds Date: Tue, 11 Dec 2012 13:19:21 -0800 Subject: [PATCH 4/5] Version 0.2.0 * Release notes in readme * Update example in readme * Note deprecation of DjrillMessage class * Longer long_description for PyPI * Update authors * Bump version number (setup.py and __init__.py) --- AUTHORS.txt | 2 ++ README.rst | 62 ++++++++++++++++++++++++++++------------- djrill/__init__.py | 2 +- djrill/mail/__init__.py | 3 ++ setup.py | 13 +++++++-- 5 files changed, 59 insertions(+), 23 deletions(-) diff --git a/AUTHORS.txt b/AUTHORS.txt index 4d56db7..adf7072 100644 --- a/AUTHORS.txt +++ b/AUTHORS.txt @@ -6,3 +6,5 @@ Chris Jones Mike Edmunds ArnaudF Théo Crevon +Rafael E. Belliard +Jared Morse diff --git a/README.rst b/README.rst index 1834032..1a2553c 100644 --- a/README.rst +++ b/README.rst @@ -4,13 +4,13 @@ Djrill, for Mandrill .. image:: https://secure.travis-ci.org/brack3t/Djrill.png?branch=master :target: https://travis-ci.org/brack3t/Djrill -Djrill is an email backend and new message class for Django users that want to take advantage of the Mandrill_ transactional -email service from MailChimp_. +Djrill is an email backend for Django users who want to take advantage of the +Mandrill_ transactional email service from MailChimp_. An optional Django admin interface is included. The admin interface allows you to: * Check the status of your Mandrill API connection. -* See stats on email tags and urls. +* See stats on email senders, tags and urls. Djrill is made available under the BSD license. @@ -81,35 +81,38 @@ package, including ``send_mail``, ``send_mass_mail``, ``EmailMessage`` and ``EmailMultiAlternatives``. You can also take advantage of Mandrill-specific features like tags, metadata, -and tracking by creating a ``django.mail.EmailMessage`` (or for HTML, -``django.mail.EmailMultiAlternatives``) object and setting Mandrill-specific +and tracking by creating a Django EmailMessage_ (or for HTML, +EmailMultiAlternatives_) object and setting Mandrill-specific properties on it before calling its ``send`` method. -Example: +Example, sending HTML email with Mandrill tags and metadata: .. code:: python - from django.core.mail import EmailMultiAlternatives # or just EmailMessage if you don't need HTML + from django.core.mail import EmailMultiAlternatives - subject = "Djrill Message" - from_email = "Djrill Sender " # this has to be in your Mandrill account's sending domains - to = ["Djrill Receiver ", "djrill.two@example.com"] - reply_email = "Customer Service " # optional - text_content = "This is the text version of your email" - html_content = "

This is the HTML version of your email

" # optional, use with ``attach_alternative`` below + msg = EmailMultiAlternatives( + subject="Djrill Message", + body="This is the text version of your email", + from_email="Djrill Sender ", + to=["Djrill Receiver ", "another.person@example.com"], + headers={'Reply-To': "Service "} # optional extra headers + ) + msg.attach_alternative("

This is the HTML version of your email

", "text/html") - msg = EmailMultiAlternatives(subject, text_content, from_email, to, headers={'Reply-To': reply_email}) - msg.tags = ["one tag", "two tag", "red tag", "blue tag"] # optional, Mandrill-specific message extension - msg.metadata = {'user_id': "8675309"} # optional, Mandrill-specific message extension - msg.attach_alternative(html_content, "text/html") + # Optional Mandrill-specific extensions (see full list below): + msg.tags = ["one tag", "two tag", "red tag", "blue tag"] + msg.metadata = {'user_id': "8675309"} + + # Send it: msg.send() If the Mandrill API returns an error response for any reason, the send call will raise a ``djrill.mail.backends.djrill.DjrillBackendHTTPError`` exception (unless called with fail_silently=True). -Djrill supports most of the functionality of Django's ``EmailMessage`` and -``EmailMultiAlternatives``. Some limitations: +Djrill supports most of the functionality of Django's `EmailMessage`_ and +`EmailMultiAlternatives`_ classes. Some limitations: * Djrill accepts additional headers, but only ``Reply-To`` and ``X-*`` (since that is all that Mandrill accepts). Any other extra headers will raise a @@ -125,6 +128,10 @@ Djrill supports most of the functionality of Django's ``EmailMessage`` and which Djrill doesn't use. *Caution:* depending on the ``preserve_recipients`` setting, this could result in exposing bcc addresses to all recipients. It's probably best to just avoid bcc.) +* All email addresses (from, to, cc) can be simple ("email@example.com") or + can include a display name ("Real Name "). +* The ``from_email`` must be in one of the approved sending domains in your + Mandrill account. Many of the options from the Mandrill `messages/send.json API`_ ``message`` struct can be set directly on an ``EmailMessage`` (or subclass) object: @@ -160,7 +167,8 @@ see ``DjrillMandrillFeatureTests`` in tests.py for examples. Testing ------- -Djrill is tested against Django 1.3 and 1.4 on Python 2.6 and 2.7. +Djrill is tested against Django 1.3 and 1.4 on Python 2.6 and 2.7, and +Django 1.5beta on Python 2.7. (It may also work with Django 1.2 and Python 2.5, if you use an older version of requests compatible with that code.) @@ -179,6 +187,18 @@ or:: python runtests.py +Release Notes +------------- + +Version 0.2.0: + +* ``MANDRILL_API_URL`` is no longer required in settings.py +* Earlier versions of Djrill required use of a ``DjrillMessage`` class to + specify Mandrill-specific options. This is no longer needed -- Mandrill + options can now be set directly on a Django EmailMessage_ object or any + subclass. (Existing code can continue to use ``DjrillMessage``.) + + Thanks ------ @@ -193,5 +213,7 @@ the awesome ``requests`` library. .. _django-adminplus: https://github.com/jsocol/django-adminplus .. _mock: http://www.voidspace.org.uk/python/mock/index.html .. _django.core.mail: https://docs.djangoproject.com/en/dev/topics/email/ +.. _EmailMessage: https://docs.djangoproject.com/en/dev/topics/email/#django.core.mail.EmailMessage +.. _EmailMultiAlternatives: https://docs.djangoproject.com/en/dev/topics/email/#sending-alternative-content-types .. _messages/send.json API: https://mandrillapp.com/api/docs/messages.html#method=send diff --git a/djrill/__init__.py b/djrill/__init__.py index 97158cb..1e21173 100644 --- a/djrill/__init__.py +++ b/djrill/__init__.py @@ -1,7 +1,7 @@ from django.contrib.admin.sites import AdminSite from django.utils.text import capfirst -VERSION = (0, 1, 2) +VERSION = (0, 2, 0) __version__ = '.'.join([str(x) for x in VERSION]) diff --git a/djrill/mail/__init__.py b/djrill/mail/__init__.py index d38bed9..021b149 100644 --- a/djrill/mail/__init__.py +++ b/djrill/mail/__init__.py @@ -1,6 +1,9 @@ from django.core.mail import EmailMultiAlternatives +# DjrillMessage class is deprecated as of 0.2.0, but retained for +# compatibility with existing code. (New code can just set Mandrill-specific +# options directly on an EmailMessage or EmailMultiAlternatives object.) class DjrillMessage(EmailMultiAlternatives): alternative_subtype = "mandrill" diff --git a/setup.py b/setup.py index 22ea8ab..da91696 100644 --- a/setup.py +++ b/setup.py @@ -2,9 +2,8 @@ from setuptools import setup setup( name="djrill", - version="0.1.4.1", + version="0.2.0", description='Django email backend for Mandrill.', - long_description='Email backend and new message class to send emails through the Mandrill email service.', keywords="django, mailchimp, mandrill, email, email backend", author="Kenneth Love , Chris Jones ", author_email="kenneth@brack3t.com", @@ -23,4 +22,14 @@ setup( "Framework :: Django", "Environment :: Web Environment", ], + long_description="""\ +Djrill is an email backend for Django users who want to take advantage of the +`Mandrill `_ transactional email service from MailChimp. + +In general, Djrill "just works" with Django's built-in ``django.core.mail`` +package. You can also take advantage of Mandrill-specific features like tags, +metadata, and tracking. An optional Django admin interface is included. + +Full details are on the `project page `_. +""", ) From c7f13ed5e5a2e15e797511da6e80dd74683c5979 Mon Sep 17 00:00:00 2001 From: medmunds Date: Tue, 11 Dec 2012 13:37:30 -0800 Subject: [PATCH 5/5] Ignore sdist output [ci skip] --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 77e536a..25a740f 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,6 @@ ._* *.pyc *.egg-info +dist/ +TODO.txt local.py