mirror of
https://github.com/pacnpal/django-anymail.git
synced 2025-12-21 04:11:06 -05:00
2
.gitignore
vendored
2
.gitignore
vendored
@@ -2,4 +2,6 @@
|
|||||||
._*
|
._*
|
||||||
*.pyc
|
*.pyc
|
||||||
*.egg-info
|
*.egg-info
|
||||||
|
dist/
|
||||||
|
TODO.txt
|
||||||
local.py
|
local.py
|
||||||
|
|||||||
@@ -6,3 +6,5 @@ Chris Jones
|
|||||||
Mike Edmunds
|
Mike Edmunds
|
||||||
ArnaudF
|
ArnaudF
|
||||||
Théo Crevon
|
Théo Crevon
|
||||||
|
Rafael E. Belliard
|
||||||
|
Jared Morse
|
||||||
|
|||||||
70
README.rst
70
README.rst
@@ -1,16 +1,16 @@
|
|||||||
Djrill, for Mandrill
|
Djrill, for Mandrill
|
||||||
====================
|
====================
|
||||||
|
|
||||||
.. image:: https://secure.travis-ci.org/brack3t/Djrill.png
|
.. image:: https://secure.travis-ci.org/brack3t/Djrill.png?branch=master
|
||||||
:target: https://secure.travis-ci.org/brack3t/Djrill
|
: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
|
Djrill is an email backend for Django users who want to take advantage of the
|
||||||
email service from MailChimp_.
|
Mandrill_ transactional email service from MailChimp_.
|
||||||
|
|
||||||
An optional Django admin interface is included. The admin interface allows you to:
|
An optional Django admin interface is included. The admin interface allows you to:
|
||||||
|
|
||||||
* Check the status of your Mandrill API connection.
|
* 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.
|
Djrill is made available under the BSD license.
|
||||||
|
|
||||||
@@ -81,35 +81,38 @@ package, including ``send_mail``, ``send_mass_mail``, ``EmailMessage`` and
|
|||||||
``EmailMultiAlternatives``.
|
``EmailMultiAlternatives``.
|
||||||
|
|
||||||
You can also take advantage of Mandrill-specific features like tags, metadata,
|
You can also take advantage of Mandrill-specific features like tags, metadata,
|
||||||
and tracking by creating a ``django.mail.EmailMessage`` (or for HTML,
|
and tracking by creating a Django EmailMessage_ (or for HTML,
|
||||||
``django.mail.EmailMultiAlternatives``) object and setting Mandrill-specific
|
EmailMultiAlternatives_) object and setting Mandrill-specific
|
||||||
properties on it before calling its ``send`` method.
|
properties on it before calling its ``send`` method.
|
||||||
|
|
||||||
Example:
|
Example, sending HTML email with Mandrill tags and metadata:
|
||||||
|
|
||||||
.. code:: python
|
.. 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"
|
msg = EmailMultiAlternatives(
|
||||||
from_email = "Djrill Sender <djrill@example.com>" # this has to be in your Mandrill account's sending domains
|
subject="Djrill Message",
|
||||||
to = ["Djrill Receiver <djrill.receiver@example.com>", "djrill.two@example.com"]
|
body="This is the text version of your email",
|
||||||
reply_email = "Customer Service <support@example.com>" # optional
|
from_email="Djrill Sender <djrill@example.com>",
|
||||||
text_content = "This is the text version of your email"
|
to=["Djrill Receiver <djrill.receiver@example.com>", "another.person@example.com"],
|
||||||
html_content = "<p>This is the HTML version of your email</p>" # optional, use with ``attach_alternative`` below
|
headers={'Reply-To': "Service <support@example.com>"} # optional extra headers
|
||||||
|
)
|
||||||
|
msg.attach_alternative("<p>This is the HTML version of your email</p>", "text/html")
|
||||||
|
|
||||||
msg = EmailMultiAlternatives(subject, text_content, from_email, to, headers={'Reply-To': reply_email})
|
# Optional Mandrill-specific extensions (see full list below):
|
||||||
msg.tags = ["one tag", "two tag", "red tag", "blue tag"] # optional, Mandrill-specific message extension
|
msg.tags = ["one tag", "two tag", "red tag", "blue tag"]
|
||||||
msg.metadata = {'user_id': "8675309"} # optional, Mandrill-specific message extension
|
msg.metadata = {'user_id': "8675309"}
|
||||||
msg.attach_alternative(html_content, "text/html")
|
|
||||||
|
# Send it:
|
||||||
msg.send()
|
msg.send()
|
||||||
|
|
||||||
If the Mandrill API returns an error response for any reason, the send call will
|
If the Mandrill API returns an error response for any reason, the send call will
|
||||||
raise a ``djrill.mail.backends.djrill.DjrillBackendHTTPError`` exception
|
raise a ``djrill.mail.backends.djrill.DjrillBackendHTTPError`` exception
|
||||||
(unless called with fail_silently=True).
|
(unless called with fail_silently=True).
|
||||||
|
|
||||||
Djrill supports most of the functionality of Django's ``EmailMessage`` and
|
Djrill supports most of the functionality of Django's `EmailMessage`_ and
|
||||||
``EmailMultiAlternatives``. Some limitations:
|
`EmailMultiAlternatives`_ classes. Some limitations:
|
||||||
|
|
||||||
* Djrill accepts additional headers, but only ``Reply-To`` and ``X-*`` (since
|
* Djrill accepts additional headers, but only ``Reply-To`` and ``X-*`` (since
|
||||||
that is all that Mandrill accepts). Any other extra headers will raise a
|
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``
|
which Djrill doesn't use. *Caution:* depending on the ``preserve_recipients``
|
||||||
setting, this could result in exposing bcc addresses to all recipients. It's
|
setting, this could result in exposing bcc addresses to all recipients. It's
|
||||||
probably best to just avoid bcc.)
|
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 <email@example.com>").
|
||||||
|
* 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``
|
Many of the options from the Mandrill `messages/send.json API`_ ``message``
|
||||||
struct can be set directly on an ``EmailMessage`` (or subclass) object:
|
struct can be set directly on an ``EmailMessage`` (or subclass) object:
|
||||||
@@ -160,12 +167,13 @@ see ``DjrillMandrillFeatureTests`` in tests.py for examples.
|
|||||||
Testing
|
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
|
(It may also work with Django 1.2 and Python 2.5, if you use an older
|
||||||
version of requests compatible with that code.)
|
version of requests compatible with that code.)
|
||||||
|
|
||||||
.. image:: https://secure.travis-ci.org/brack3t/Djrill.png
|
.. image:: https://secure.travis-ci.org/brack3t/Djrill.png?branch=master
|
||||||
:target: https://secure.travis-ci.org/brack3t/Djrill
|
:target: https://travis-ci.org/brack3t/Djrill
|
||||||
|
|
||||||
The included tests verify that Djrill constructs the expected Mandrill API
|
The included tests verify that Djrill constructs the expected Mandrill API
|
||||||
calls, without actually calling Mandrill or sending any email. So the tests
|
calls, without actually calling Mandrill or sending any email. So the tests
|
||||||
@@ -179,6 +187,18 @@ or::
|
|||||||
python runtests.py
|
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
|
Thanks
|
||||||
------
|
------
|
||||||
|
|
||||||
@@ -193,5 +213,7 @@ the awesome ``requests`` library.
|
|||||||
.. _django-adminplus: https://github.com/jsocol/django-adminplus
|
.. _django-adminplus: https://github.com/jsocol/django-adminplus
|
||||||
.. _mock: http://www.voidspace.org.uk/python/mock/index.html
|
.. _mock: http://www.voidspace.org.uk/python/mock/index.html
|
||||||
.. _django.core.mail: https://docs.djangoproject.com/en/dev/topics/email/
|
.. _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
|
.. _messages/send.json API: https://mandrillapp.com/api/docs/messages.html#method=send
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
from django.contrib.admin.sites import AdminSite
|
from django.contrib.admin.sites import AdminSite
|
||||||
from django.utils.text import capfirst
|
from django.utils.text import capfirst
|
||||||
|
|
||||||
VERSION = (0, 1, 2)
|
VERSION = (0, 2, 0)
|
||||||
__version__ = '.'.join([str(x) for x in VERSION])
|
__version__ = '.'.join([str(x) for x in VERSION])
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,30 +1,37 @@
|
|||||||
from django.core.exceptions import ImproperlyConfigured
|
|
||||||
from django.core.mail import EmailMultiAlternatives
|
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):
|
class DjrillMessage(EmailMultiAlternatives):
|
||||||
alternative_subtype = "mandrill"
|
alternative_subtype = "mandrill"
|
||||||
|
|
||||||
def __init__(self, subject='', body='', from_email=None, to=None, bcc=None,
|
def __init__(self, subject='', body='', from_email=None, to=None, bcc=None,
|
||||||
connection=None, attachments=None, headers=None, alternatives=None,
|
connection=None, attachments=None, headers=None, alternatives=None,
|
||||||
cc=None, from_name=None, tags=None, track_opens=True,
|
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,
|
super(DjrillMessage, self).__init__(subject, body, from_email, to, bcc,
|
||||||
connection, attachments, headers, alternatives, cc)
|
connection, attachments, headers, alternatives, cc)
|
||||||
|
|
||||||
self.from_name = from_name
|
if from_name:
|
||||||
self.tags = self._set_mandrill_tags(tags)
|
self.from_name = from_name
|
||||||
self.track_opens = track_opens
|
if tags:
|
||||||
self.track_clicks = track_clicks
|
self.tags = self._set_mandrill_tags(tags)
|
||||||
self.preserve_recipients = preserve_recipients
|
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):
|
def _set_mandrill_tags(self, tags):
|
||||||
"""
|
"""
|
||||||
Check that all tags are below 50 chars and that they do not start
|
Check that all tags are below 50 chars and that they do not start
|
||||||
with an underscore.
|
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.
|
alert the user. Any tag over 50 chars is left out of the list.
|
||||||
"""
|
"""
|
||||||
tag_list = []
|
tag_list = []
|
||||||
@@ -33,8 +40,8 @@ class DjrillMessage(EmailMultiAlternatives):
|
|||||||
if len(tag) <= 50 and not tag.startswith("_"):
|
if len(tag) <= 50 and not tag.startswith("_"):
|
||||||
tag_list.append(tag)
|
tag_list.append(tag)
|
||||||
elif tag.startswith("_"):
|
elif tag.startswith("_"):
|
||||||
raise ImproperlyConfigured(
|
raise ValueError(
|
||||||
"Tags starting with an underscore are reserved for "
|
"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
|
return tag_list
|
||||||
|
|||||||
@@ -61,6 +61,7 @@
|
|||||||
<dt>{{ term|capfirst }}</dt>
|
<dt>{{ term|capfirst }}</dt>
|
||||||
<dd>{{ value }}</dd>
|
<dd>{{ value }}</dd>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
</dl>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
@@ -392,7 +392,7 @@ class DjrillMessageTests(TestCase):
|
|||||||
self.assertEqual(msg.alternatives[0][0], self.html_content)
|
self.assertEqual(msg.alternatives[0][0], self.html_content)
|
||||||
|
|
||||||
def test_djrill_message_tag_failure(self):
|
def test_djrill_message_tag_failure(self):
|
||||||
with self.assertRaises(ImproperlyConfigured):
|
with self.assertRaises(ValueError):
|
||||||
DjrillMessage(self.subject, self.text_content, self.from_email,
|
DjrillMessage(self.subject, self.text_content, self.from_email,
|
||||||
self.to, tags=["_fail"])
|
self.to, tags=["_fail"])
|
||||||
|
|
||||||
@@ -409,3 +409,15 @@ class DjrillMessageTests(TestCase):
|
|||||||
self.assertIn(tags[0], msg.tags)
|
self.assertIn(tags[0], msg.tags)
|
||||||
self.assertIn(tags[1], msg.tags)
|
self.assertIn(tags[1], msg.tags)
|
||||||
self.assertNotIn(tags[2], 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'))
|
||||||
|
|||||||
13
setup.py
13
setup.py
@@ -2,9 +2,8 @@ from setuptools import setup
|
|||||||
|
|
||||||
setup(
|
setup(
|
||||||
name="djrill",
|
name="djrill",
|
||||||
version="0.1.4.1",
|
version="0.2.0",
|
||||||
description='Django email backend for Mandrill.',
|
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",
|
keywords="django, mailchimp, mandrill, email, email backend",
|
||||||
author="Kenneth Love <kenneth@brack3t.com>, Chris Jones <chris@brack3t.com>",
|
author="Kenneth Love <kenneth@brack3t.com>, Chris Jones <chris@brack3t.com>",
|
||||||
author_email="kenneth@brack3t.com",
|
author_email="kenneth@brack3t.com",
|
||||||
@@ -23,4 +22,14 @@ setup(
|
|||||||
"Framework :: Django",
|
"Framework :: Django",
|
||||||
"Environment :: Web Environment",
|
"Environment :: Web Environment",
|
||||||
],
|
],
|
||||||
|
long_description="""\
|
||||||
|
Djrill is an email backend for Django users who want to take advantage of the
|
||||||
|
`Mandrill <http://mandrill.com>`_ 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 <https://github.com/brack3t/Djrill>`_.
|
||||||
|
""",
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user