mirror of
https://github.com/pacnpal/django-anymail.git
synced 2025-12-20 03:41:05 -05:00
Docs: break apart the lengthy readme into organized docs
Also sphinx-ify where appropriate, and lots of general cleanup/editing.
This commit is contained in:
342
README.rst
342
README.rst
@@ -1,327 +1,23 @@
|
||||
Djrill, for Mandrill
|
||||
====================
|
||||
Djrill: Mandrill for Django
|
||||
===========================
|
||||
|
||||
Djrill integrates the `Mandrill <http://mandrill.com>`_ transactional
|
||||
email service into Django.
|
||||
|
||||
In general, Djrill "just works" with Django's built-in
|
||||
`django.core.mail <https://docs.djangoproject.com/en/dev/topics/email/>`_
|
||||
functions. It supports:
|
||||
|
||||
* HTML email, attachments, extra headers, and other basic email functionality
|
||||
* Mandrill-specific extensions like tags, metadata, tracking, and MailChimp templates
|
||||
* An optional Django admin interface
|
||||
|
||||
.. image:: https://secure.travis-ci.org/brack3t/Djrill.png?branch=master
|
||||
:target: https://travis-ci.org/brack3t/Djrill
|
||||
:target: https://travis-ci.org/brack3t/Djrill
|
||||
|
||||
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. The admin interface allows you to:
|
||||
|
||||
* Check the status of your Mandrill API connection.
|
||||
* See stats on email senders, tags and urls.
|
||||
|
||||
Djrill is made available under the BSD license.
|
||||
|
||||
Installation
|
||||
------------
|
||||
|
||||
Install from PyPI::
|
||||
|
||||
pip install djrill
|
||||
|
||||
The only dependency other than Django is the requests_ library from Kenneth
|
||||
Reitz. (If you do not install Djrill using pip or setuptools, you will also
|
||||
need to ``pip install requests``.)
|
||||
|
||||
|
||||
Configuration
|
||||
-------------
|
||||
|
||||
In ``settings.py``:
|
||||
|
||||
1. Add ``djrill`` to your ``INSTALLED_APPS``:
|
||||
|
||||
.. code:: python
|
||||
|
||||
INSTALLED_APPS = (
|
||||
...
|
||||
"djrill"
|
||||
)
|
||||
|
||||
2. Add the following line, substituting your own ``MANDRILL_API_KEY``:
|
||||
|
||||
.. code:: python
|
||||
|
||||
MANDRILL_API_KEY = "brack3t-is-awesome"
|
||||
|
||||
3. Override your existing email backend with the following line:
|
||||
|
||||
.. code:: python
|
||||
|
||||
EMAIL_BACKEND = "djrill.mail.backends.djrill.DjrillBackend"
|
||||
|
||||
4. (optional) If you want to be able to add senders through Django's admin or
|
||||
view stats about your messages, do the following in your base ``urls.py``:
|
||||
|
||||
.. code:: python
|
||||
|
||||
...
|
||||
from django.contrib import admin
|
||||
|
||||
from djrill import DjrillAdminSite
|
||||
|
||||
admin.site = DjrillAdminSite()
|
||||
admin.autodiscover()
|
||||
...
|
||||
|
||||
urlpatterns = patterns('',
|
||||
...
|
||||
url(r'^admin/', include(admin.site.urls)),
|
||||
)
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
Since you are replacing the global ``EMAIL_BACKEND``, **all** emails are sent
|
||||
through Mandrill's service. (To selectively use Mandrill for some messages, see
|
||||
`Using Multiple Email Backends`_ below.)
|
||||
|
||||
In general, Djrill "just works" with Django's built-in `django.core.mail`_
|
||||
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 EmailMessage_ (or for HTML,
|
||||
EmailMultiAlternatives_) object and setting Mandrill-specific
|
||||
properties on it before calling its ``send`` method. (See
|
||||
`Mandrill Message Options`_ below.)
|
||||
|
||||
Example, sending HTML email with Mandrill tags and metadata:
|
||||
|
||||
.. code:: python
|
||||
|
||||
from django.core.mail import EmailMultiAlternatives
|
||||
|
||||
msg = EmailMultiAlternatives(
|
||||
subject="Djrill Message",
|
||||
body="This is the text version of your email",
|
||||
from_email="Djrill Sender <djrill@example.com>",
|
||||
to=["Djrill Receiver <djrill.receiver@example.com>", "another.person@example.com"],
|
||||
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")
|
||||
|
||||
# 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 email tries to use features that aren't supported by Mandrill, the send
|
||||
call will raise a ``djrill.NotSupportedByMandrillError`` exception (a subclass
|
||||
of ValueError).
|
||||
|
||||
If the Mandrill API fails or returns an error response, the send call will
|
||||
raise a ``djrill.MandrillAPIError`` exception (a subclass of
|
||||
requests.HTTPError).
|
||||
|
||||
|
||||
Django EmailMessage Support
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Djrill supports most of the functionality of Django's `EmailMessage`_ and
|
||||
`EmailMultiAlternatives`_ classes. Some notes and limitations:
|
||||
|
||||
* **Display Names:** All email addresses (from, to, cc) can be simple
|
||||
("email@example.com") or can include a display name
|
||||
("Real Name <email@example.com>").
|
||||
* **From Address:** The ``from_email`` must be in one of the approved sending
|
||||
domains in your Mandrill account.
|
||||
* **CC Recipients:** Djrill treats all "cc" recipients as if they were
|
||||
additional "to" addresses. (Mandrill does not distinguish "cc" from "to".)
|
||||
Note that you will also need to set ``preserve_recipients`` True if you want
|
||||
each recipient to see the other recipients listed in the email headers.
|
||||
* **BCC Recipients:** Mandrill does not permit more than one "bcc" address.
|
||||
Djrill raises ``djrill.NotSupportedByMandrillError`` if you attempt to send a
|
||||
message with multiple bcc's. (Mandrill's bcc option seems intended primarily
|
||||
for logging. To send a single message to multiple recipients without exposing
|
||||
their email addresses to each other, simply include them all in the "to" list
|
||||
and leave ``preserve_recipients`` set to False.)
|
||||
* **Attachments:** Djrill includes a message's attachments. Also, if an image
|
||||
attachment has a Content-ID header, Djrill will tell Mandrill to treat that
|
||||
as an embedded image rather than an ordinary attachment. (For an example,
|
||||
see ``test_embedded_images`` in tests/test_mandrill_send.py.)
|
||||
* **Headers:** Djrill accepts additional headers, but only ``Reply-To`` and
|
||||
``X-*`` (since that is all that Mandrill accepts). Any other extra headers
|
||||
will raise ``djrill.NotSupportedByMandrillError`` when you attempt to send the
|
||||
message.
|
||||
* **Alternative Parts:** Djrill requires that if you ``attach_alternative`` to a
|
||||
message, there must be only one alternative part, and it must be text/html.
|
||||
Otherwise, Djrill will raise ``djrill.NotSupportedByMandrillError`` when you
|
||||
attempt to send the message. (Mandrill doesn't support sending multiple html
|
||||
alternative parts, or any non-html alternatives.)
|
||||
|
||||
Mandrill Message Options
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Many of the options from the Mandrill `messages/send API`_ ``message``
|
||||
struct can be set directly on an ``EmailMessage`` (or subclass) object:
|
||||
|
||||
* ``track_opens`` - Boolean
|
||||
* ``track_clicks`` - Boolean (If you want to track clicks in HTML only, not
|
||||
plaintext mail, you must *not* set this property, and instead just set the
|
||||
default in your Mandrill account sending options.)
|
||||
* ``auto_text`` - Boolean
|
||||
* ``url_strip_qs`` - Boolean
|
||||
* ``preserve_recipients`` - Boolean
|
||||
* ``global_merge_vars`` - a dict -- e.g.,
|
||||
``{ 'company': "ACME", 'offer': "10% off" }``
|
||||
* ``recipient_merge_vars`` - a dict whose keys are the recipient email addresses
|
||||
and whose values are dicts of merge vars for each recipient -- e.g.,
|
||||
``{ 'wiley@example.com': { 'offer': "15% off anvils" } }``
|
||||
* ``tags`` - a list of strings
|
||||
* ``google_analytics_domains`` - a list of string domain names
|
||||
* ``google_analytics_campaign`` - a string or list of strings
|
||||
* ``metadata`` - a dict
|
||||
* ``recipient_metadata`` - a dict whose keys are the recipient email addresses,
|
||||
and whose values are dicts of metadata for each recipient (similar to
|
||||
``recipient_merge_vars``)
|
||||
|
||||
These Mandrill-specific properties work with *any* ``EmailMessage``-derived
|
||||
object, so you can use them with many other apps that add Django mail
|
||||
functionality (such as Django template-based messages).
|
||||
|
||||
If you have any questions about the python syntax for any of these properties,
|
||||
see ``DjrillMandrillFeatureTests`` in tests/test_mandrill_send.py for examples.
|
||||
|
||||
Mandrill Templates
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
To use a Mandrill (MailChimp) template, set a ``template_name`` and (optionally)
|
||||
``template_content`` on your ``EmailMessage`` object:
|
||||
|
||||
.. code:: python
|
||||
|
||||
msg = EmailMessage(subject="Shipped!", from_email="store@example.com",
|
||||
to=["customer@example.com", "accounting@example.com"])
|
||||
msg.template_name = "SHIPPING_NOTICE" # A Mandrill template name
|
||||
msg.template_content = { # Content blocks to fill in
|
||||
'TRACKING_BLOCK': "<a href='.../\*\|TRACKINGNO\|\*'>track it</a>" }
|
||||
msg.global_merge_vars = { # Merge tags in your template
|
||||
'ORDERNO': "12345", 'TRACKINGNO': "1Z987" }
|
||||
msg.merge_vars = { # Per-recipient merge tags
|
||||
'accounting@example.com': { 'NAME': "Pat" },
|
||||
'customer@example.com': { 'NAME': "Kim" } }
|
||||
msg.send()
|
||||
|
||||
If template_name is set, Djrill will use Mandrill's `messages/send-template API`_,
|
||||
rather than messages/send. All of the other options listed above can be used.
|
||||
|
||||
(This is for *MailChimp* templates stored in your Mandrill account. If you
|
||||
want to use a *Django* template, you can use Django's render_to_string_ template
|
||||
shortcut to build the body and html, and send using EmailMultiAlternatives as
|
||||
in the earlier examples.)
|
||||
|
||||
Using Multiple Email Backends
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
You can use Django mail's optional ``connection`` argument to send some mail
|
||||
through Mandrill and others through a different system. This can be useful to
|
||||
send customer emails with Mandrill, but admin emails directly through an SMTP
|
||||
server. Example:
|
||||
|
||||
.. code:: python
|
||||
|
||||
from django.core.mail import send_mail, get_connection
|
||||
|
||||
# send_mail connection defaults to the settings EMAIL_BACKEND, which
|
||||
# we've set to DjrillBackend. This will be sent using Mandrill:
|
||||
send_mail("Subject", "Body", "support@example.com", ["user@example.com"])
|
||||
|
||||
# Get a connection to an SMTP backend, and send using that instead:
|
||||
smtp_backend = get_connection('django.core.mail.backends.smtp.EmailBackend')
|
||||
send_mail("Subject", "Body", "admin@example.com", ["alert@example.com"],
|
||||
connection=smtp_backend)
|
||||
|
||||
You can supply a different connection to Django's `django.core.mail`_
|
||||
``send_mail`` and ``send_mass_mail`` helpers, and in the constructor for an
|
||||
EmailMessage_ or EmailMultiAlternatives_.
|
||||
|
||||
|
||||
Testing
|
||||
-------
|
||||
|
||||
Djrill is tested against Django 1.3 and 1.4 on Python 2.6 and 2.7, and
|
||||
Django 1.5RC on Python 2.7 and 3.2.
|
||||
(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?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
|
||||
don't require a Mandrill API key, but they *do* require mock_
|
||||
(``pip install mock``). To run the tests, either::
|
||||
|
||||
python -Wall setup.py test
|
||||
|
||||
or::
|
||||
|
||||
python -Wall runtests.py
|
||||
|
||||
|
||||
Contributing
|
||||
------------
|
||||
|
||||
Djrill is maintained by its users -- it's not managed by the folks at MailChimp.
|
||||
Pull requests are always welcome to improve support for Mandrill and Django
|
||||
features.
|
||||
|
||||
Please include test cases with pull requests. (And by submitting a pull request,
|
||||
you're agreeing to release your changes under under the same BSD license as the
|
||||
rest of this project.)
|
||||
|
||||
|
||||
Release Notes
|
||||
-------------
|
||||
|
||||
Version 0.3.0:
|
||||
|
||||
* Attachments are now supported
|
||||
* Mandrill templates are now supported
|
||||
* A bcc address is now passed to Mandrill as bcc, rather than being lumped in
|
||||
with the "to" recipients. Multiple bcc recipients will now raise an exception,
|
||||
as Mandrill only allows one.
|
||||
* Python 3 support (with Django 1.5)
|
||||
* Exceptions should be more useful: ``djrill.NotSupportedByMandrillError``
|
||||
replaces generic ValueError; ``djrill.MandrillAPIError`` replaces
|
||||
DjrillBackendHTTPError, and is now derived from requests.HTTPError. (New
|
||||
exceptions are backwards compatible with old ones for existing code.)
|
||||
|
||||
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 to the MailChimp team for asking us to build this nifty little app. Also thanks to James Socol on Github for his
|
||||
django-adminplus_ library that got us off on the right foot for the custom admin views. Oh, and, of course, Kenneth Reitz for
|
||||
the awesome ``requests`` library.
|
||||
|
||||
|
||||
.. _Mandrill: http://mandrill.com
|
||||
.. _MailChimp: http://mailchimp.com
|
||||
.. _requests: http://docs.python-requests.org
|
||||
.. _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
|
||||
.. _render_to_string: https://docs.djangoproject.com/en/dev/ref/templates/api/#the-render-to-string-shortcut
|
||||
.. _messages/send API: https://mandrillapp.com/api/docs/messages.html#method=send
|
||||
.. _messages/send-template API: https://mandrillapp.com/api/docs/messages.html#method=send-template
|
||||
Djrill is tested with Django 1.3 and later (including Python 3 support with Django 1.5).
|
||||
It is made available under the BSD license.
|
||||
|
||||
* Documentation: https://readthedocs.org/docs/djrill/en/latest/
|
||||
* Package on PyPI: https://pypi.python.org/pypi/djrill
|
||||
* Latest source: https://github.com/brack3t/Djrill
|
||||
|
||||
40
docs/conf.py
40
docs/conf.py
@@ -23,11 +23,11 @@ execfile('../djrill/_version.py')
|
||||
# -- General configuration -----------------------------------------------------
|
||||
|
||||
# If your documentation needs a minimal Sphinx version, state it here.
|
||||
#needs_sphinx = '1.0'
|
||||
needs_sphinx = '1.0'
|
||||
|
||||
# Add any Sphinx extension module names here, as strings. They can be extensions
|
||||
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
|
||||
extensions = []
|
||||
extensions = ['sphinx.ext.intersphinx']
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
templates_path = ['_templates']
|
||||
@@ -43,6 +43,7 @@ master_doc = 'index'
|
||||
|
||||
# General information about the project.
|
||||
project = u'Djrill'
|
||||
# noinspection PyShadowingBuiltins
|
||||
copyright = u'2013, Djrill contributors (see AUTHORS.txt)'
|
||||
|
||||
# The version info for the project you're documenting, acts as replacement for
|
||||
@@ -69,7 +70,7 @@ release = __version__
|
||||
exclude_patterns = ['_build']
|
||||
|
||||
# The reST default role (used for this markup: `text`) to use for all documents.
|
||||
#default_role = None
|
||||
default_role = "py:obj"
|
||||
|
||||
# If true, '()' will be appended to :func: etc. cross-reference text.
|
||||
#add_function_parentheses = True
|
||||
@@ -242,3 +243,36 @@ texinfo_documents = [
|
||||
|
||||
# How to display URL addresses: 'footnote', 'no', or 'inline'.
|
||||
#texinfo_show_urls = 'footnote'
|
||||
|
||||
|
||||
# -- Options for Intersphinx ------------------------------------------------
|
||||
|
||||
intersphinx_mapping = {
|
||||
'python': ('http://docs.python.org/2.7', None),
|
||||
'django': ('http://docs.djangoproject.com/en/dev/', 'http://docs.djangoproject.com/en/dev/_objects/'),
|
||||
'requests': ('http://docs.python-requests.org/en/latest/', None),
|
||||
}
|
||||
|
||||
|
||||
def setup(app):
|
||||
# Django-specific roles, from https://github.com/django/django/blob/master/docs/_ext/djangodocs.py:
|
||||
app.add_crossref_type(
|
||||
directivename = "setting",
|
||||
rolename = "setting",
|
||||
indextemplate = "pair: %s; setting",
|
||||
)
|
||||
app.add_crossref_type(
|
||||
directivename = "templatetag",
|
||||
rolename = "ttag",
|
||||
indextemplate = "pair: %s; template tag"
|
||||
)
|
||||
app.add_crossref_type(
|
||||
directivename = "templatefilter",
|
||||
rolename = "tfilter",
|
||||
indextemplate = "pair: %s; template filter"
|
||||
)
|
||||
app.add_crossref_type(
|
||||
directivename = "fieldlookup",
|
||||
rolename = "lookup",
|
||||
indextemplate = "pair: %s; field lookup type",
|
||||
)
|
||||
|
||||
54
docs/contributing.rst
Normal file
54
docs/contributing.rst
Normal file
@@ -0,0 +1,54 @@
|
||||
Contributing
|
||||
============
|
||||
|
||||
Djrill is maintained by its users. Your contributions are encouraged!
|
||||
|
||||
The `Djrill source code`_ is on github. See `AUTHORS.txt`_ for a list
|
||||
of some of the people who have helped improve Djrill.
|
||||
|
||||
.. _Djrill source code: https://github.com/brack3t/Djrill:
|
||||
.. _AUTHORS.txt: https://github.com/brack3t/Djrill/blob/master/AUTHORS.txt
|
||||
|
||||
|
||||
Bugs
|
||||
----
|
||||
|
||||
You can report problems or request features in
|
||||
`Djrill's github issue tracker <https://github.com/brack3t/Djrill/issues>`_.
|
||||
|
||||
|
||||
Pull Requests
|
||||
-------------
|
||||
|
||||
Pull requests are always welcome to fix bugs and improve support for Mandrill and Django features.
|
||||
|
||||
* Please include test cases.
|
||||
* We try to follow the `Django coding style`_ (basically, PEP 8 with longer lines OK).
|
||||
* By submitting a pull request, you're agreeing to release your changes under under
|
||||
the same BSD license as the rest of this project.
|
||||
|
||||
.. _Django coding style: https://docs.djangoproject.com/en/dev/internals/contributing/writing-code/coding-style/
|
||||
|
||||
|
||||
Testing
|
||||
-------
|
||||
|
||||
Djrill is `tested on Travis <https://travis-ci.org/brack3t/Djrill>`_ against:
|
||||
|
||||
* Django 1.3 on Python 2.6 and 2.7
|
||||
* Django 1.4 on Python 2.6 and 2.7
|
||||
* Django 1.5 on Python 2.7 and 3.2
|
||||
|
||||
The included tests verify that Djrill constructs the expected Mandrill API
|
||||
calls, without actually calling Mandrill or sending any email. So the tests
|
||||
don't require a Mandrill API key, but they *do* require
|
||||
`mock <http://www.voidspace.org.uk/python/mock/index.html>`_ (``pip install mock``).
|
||||
|
||||
To run the tests, either::
|
||||
|
||||
python -Wall setup.py test
|
||||
|
||||
or::
|
||||
|
||||
python -Wall runtests.py
|
||||
|
||||
25
docs/history.rst
Normal file
25
docs/history.rst
Normal file
@@ -0,0 +1,25 @@
|
||||
Release Notes
|
||||
=============
|
||||
|
||||
Version 0.3.0:
|
||||
|
||||
* :ref:`Attachments <sending-attachments>` are now supported
|
||||
* :ref:`Mandrill templates <mandrill-templates>` are now supported
|
||||
* A bcc address is now passed to Mandrill as bcc, rather than being lumped in
|
||||
with the "to" recipients. Multiple bcc recipients will now raise an exception,
|
||||
as Mandrill only allows one.
|
||||
* Python 3 support (with Django 1.5)
|
||||
* Exceptions should be more useful:
|
||||
:exc:`djrill.NotSupportedByMandrillError` replaces generic ValueError;
|
||||
:exc:`djrill.MandrillAPIError` replaces DjrillBackendHTTPError, and is now
|
||||
derived from requests.HTTPError.
|
||||
(New exceptions are backwards compatible with old ones for existing code.)
|
||||
|
||||
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``.)
|
||||
|
||||
101
docs/index.rst
101
docs/index.rst
@@ -3,20 +3,105 @@
|
||||
You can adapt this file completely to your liking, but it should at least
|
||||
contain the root `toctree` directive.
|
||||
|
||||
Welcome to Djrill's documentation!
|
||||
==================================
|
||||
Djrill: Mandrill for Django
|
||||
===========================
|
||||
|
||||
Contents:
|
||||
Release |release|
|
||||
|
||||
Djrill integrates the `Mandrill <http://mandrill.com>`_ transactional
|
||||
email service into Django.
|
||||
|
||||
In general, Djrill "just works" with Django's built-in
|
||||
`django.core.mail <https://docs.djangoproject.com/en/dev/topics/email/>`_
|
||||
functions. It supports:
|
||||
|
||||
* HTML email, attachments, extra headers, and other basic email functionality
|
||||
* Mandrill-specific extensions like tags, metadata, tracking, and MailChimp templates
|
||||
* An optional Django admin interface
|
||||
|
||||
Djrill is tested with Django 1.3 and later (including Python 3 support with Django 1.5).
|
||||
It is made available under the BSD license.
|
||||
|
||||
|
||||
.. _quickstart:
|
||||
|
||||
Quick Start
|
||||
-----------
|
||||
|
||||
1. Install from PyPI:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
$ pip install djrill
|
||||
|
||||
|
||||
2. Edit your project's :file:`settings.py`:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
INSTALLED_APPS = (
|
||||
...
|
||||
"djrill"
|
||||
)
|
||||
|
||||
MANDRILL_API_KEY = "<your Mandrill key>"
|
||||
EMAIL_BACKEND = "djrill.mail.backends.djrill.DjrillBackend"
|
||||
|
||||
|
||||
3. Now the regular `Django email functions <https://docs.djangoproject.com/en/dev/topics/email/>`_
|
||||
will send through Mandrill::
|
||||
|
||||
from django.core.mail import send_mail
|
||||
|
||||
send_mail("It works!", "This will get sent through Mandrill",
|
||||
"Djrill Sender <djrill@example.com>", ["to@example.com"])
|
||||
|
||||
|
||||
You could send an HTML message, complete with custom Mandrill tags and metadata::
|
||||
|
||||
from django.core.mail import EmailMultiAlternatives
|
||||
|
||||
msg = EmailMultiAlternatives(
|
||||
subject="Djrill Message",
|
||||
body="This is the text email body",
|
||||
from_email="Djrill Sender <djrill@example.com>",
|
||||
to=["Recipient One <someone@example.com>", "another.person@example.com"],
|
||||
headers={'Reply-To': "Service <support@example.com>"} # optional extra headers
|
||||
)
|
||||
msg.attach_alternative("<p>This is the HTML email body</p>", "text/html")
|
||||
|
||||
# Optional Mandrill-specific extensions:
|
||||
msg.tags = ["one tag", "two tag", "red tag", "blue tag"]
|
||||
msg.metadata = {'user_id': "8675309"}
|
||||
|
||||
# Send it:
|
||||
msg.send()
|
||||
|
||||
(Be sure to use a ``from_email`` that's in one of your Mandrill approved sending
|
||||
domains, or the message won't get sent.)
|
||||
|
||||
|
||||
Documentation
|
||||
-------------
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
installation
|
||||
usage/sending_mail
|
||||
usage/templates
|
||||
usage/multiple_backends
|
||||
contributing
|
||||
history
|
||||
|
||||
|
||||
Indices and tables
|
||||
==================
|
||||
Thanks
|
||||
------
|
||||
|
||||
* :ref:`genindex`
|
||||
* :ref:`modindex`
|
||||
* :ref:`search`
|
||||
Thanks to the MailChimp team for asking us to build this nifty little app, and to all of Djrill's
|
||||
:doc:`contributors <contributing>`. Also thanks to James Socol on Github for his django-adminplus_
|
||||
library that got us off on the right foot for the custom admin views.
|
||||
Oh, and, of course, Kenneth Reitz for the awesome requests_ library.
|
||||
|
||||
.. _requests: http://docs.python-requests.org
|
||||
.. _django-adminplus: https://github.com/jsocol/django-adminplus
|
||||
|
||||
61
docs/installation.rst
Normal file
61
docs/installation.rst
Normal file
@@ -0,0 +1,61 @@
|
||||
Installation
|
||||
============
|
||||
|
||||
It's easiest to install Djrill from `PyPI <https://pypi.python.org/pypi/djrill>`_:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
$ pip install djrill
|
||||
|
||||
If you decide to install Djrill some other way, you'll also need to install its
|
||||
one dependency (other than Django, of course): the `requests <http://docs.python-requests.org>`_
|
||||
library from Kenneth Reitz.
|
||||
|
||||
|
||||
Configuration
|
||||
-------------
|
||||
|
||||
In your project's :file:`settings.py`:
|
||||
|
||||
1. Add :mod:`djrill` to your :setting:`INSTALLED_APPS`::
|
||||
|
||||
INSTALLED_APPS = (
|
||||
...
|
||||
"djrill"
|
||||
)
|
||||
|
||||
2. Add the following line, substituting your own :setting:`MANDRILL_API_KEY`::
|
||||
|
||||
MANDRILL_API_KEY = "brack3t-is-awesome"
|
||||
|
||||
3. Override your existing :setting:`EMAIL_BACKEND` with the following line::
|
||||
|
||||
EMAIL_BACKEND = "djrill.mail.backends.djrill.DjrillBackend"
|
||||
|
||||
|
||||
Admin (Optional)
|
||||
----------------
|
||||
|
||||
Djrill includes an optional Django admin interface, which allows you to:
|
||||
|
||||
* Check the status of your Mandrill API connection
|
||||
* See stats on email senders, tags and urls
|
||||
|
||||
If you want to enable the Djrill admin interface, edit your base :file:`urls.py`:
|
||||
|
||||
.. code-block:: python
|
||||
:emphasize-lines: 4,6
|
||||
|
||||
...
|
||||
from django.contrib import admin
|
||||
|
||||
from djrill import DjrillAdminSite
|
||||
|
||||
admin.site = DjrillAdminSite()
|
||||
admin.autodiscover()
|
||||
...
|
||||
|
||||
urlpatterns = patterns('',
|
||||
...
|
||||
url(r'^admin/', include(admin.site.urls)),
|
||||
)
|
||||
32
docs/usage/multiple_backends.rst
Normal file
32
docs/usage/multiple_backends.rst
Normal file
@@ -0,0 +1,32 @@
|
||||
.. _multiple-backends:
|
||||
|
||||
Mixing Email Backends
|
||||
=====================
|
||||
|
||||
Since you are replacing Django's global :setting:`EMAIL_BACKEND`, by default
|
||||
Djrill will handle all outgoing mail, sending everything through Mandrill.
|
||||
|
||||
You can use Django mail's optional :func:`connection <django.core.mail.get_connection>`
|
||||
argument to send some mail through Mandrill and others through a different system.
|
||||
|
||||
This could be useful, for example, to deliver customer emails with Mandrill,
|
||||
but send admin emails directly through an SMTP server:
|
||||
|
||||
.. code-block:: python
|
||||
:emphasize-lines: 8,10
|
||||
|
||||
from django.core.mail import send_mail, get_connection
|
||||
|
||||
# send_mail connection defaults to the settings EMAIL_BACKEND, which
|
||||
# we've set to DjrillBackend. This will be sent using Mandrill:
|
||||
send_mail("Thanks", "We sent your order", "sales@example.com", ["customer@example.com"])
|
||||
|
||||
# Get a connection to an SMTP backend, and send using that instead:
|
||||
smtp_backend = get_connection('django.core.mail.backends.smtp.EmailBackend')
|
||||
send_mail("Uh-Oh", "Need your attention", "admin@example.com", ["alert@example.com"],
|
||||
connection=smtp_backend)
|
||||
|
||||
You can supply a different connection to Django's
|
||||
:func:`~django.core.mail.send_mail` and :func:`~django.core.mail.send_mass_mail` helpers,
|
||||
and in the constructor for an
|
||||
:class:`~django.core.mail.EmailMessage` or :class:`~django.core.mail.EmailMultiAlternatives`.
|
||||
225
docs/usage/sending_mail.rst
Normal file
225
docs/usage/sending_mail.rst
Normal file
@@ -0,0 +1,225 @@
|
||||
Sending Mail
|
||||
============
|
||||
|
||||
Djrill handles **all** outgoing email sent through Django's standard
|
||||
:mod:`django.core.mail` package, including :func:`~django.core.mail.send_mail`,
|
||||
:func:`~django.core.mail.send_mass_mail`, the :class:`~django.core.mail.EmailMessage` class,
|
||||
and even :func:`~django.core.mail.mail_admins`.
|
||||
|
||||
If you'd like to selectively send only some messages through Mandrill,
|
||||
there is a way to :ref:`use multiple email backends <multiple-backends>`.
|
||||
|
||||
|
||||
.. _django-send-support:
|
||||
|
||||
Django Email Support
|
||||
--------------------
|
||||
|
||||
Djrill supports most of the functionality of Django's :class:`~django.core.mail.EmailMessage`
|
||||
and :class:`~django.core.mail.EmailMultiAlternatives` classes.
|
||||
|
||||
Some notes and limitations:
|
||||
|
||||
**Display Names**
|
||||
All email addresses (from, to, cc) can be simple
|
||||
("email\@example.com") or can include a display name
|
||||
("Real Name <email\@example.com>").
|
||||
|
||||
**From Address**
|
||||
The ``from_email`` must be in one of the approved sending
|
||||
domains in your Mandrill account, or Mandrill will refuse to send the message.
|
||||
|
||||
**CC Recipients**
|
||||
Djrill treats all "cc" recipients as if they were
|
||||
additional "to" addresses. (Mandrill does not distinguish "cc" from "to".)
|
||||
|
||||
.. note::
|
||||
|
||||
By default, Mandrill hides all recipients from each other. If you want the
|
||||
headers to list everyone who was sent the message, you'll also need to set the
|
||||
Mandrill option :attr:`preserve_recipients` to `!True`
|
||||
|
||||
**BCC Recipients**
|
||||
Mandrill does not permit more than one "bcc" address.
|
||||
Djrill raises :exc:`~djrill.NotSupportedByMandrillError` if you attempt to send a
|
||||
message with multiple bcc's.
|
||||
|
||||
(Mandrill's bcc option seems intended primarily
|
||||
for logging. To send a single message to multiple recipients without exposing
|
||||
their email addresses to each other, simply include them all in the "to" list
|
||||
and leave Mandrill's :attr:`preserve_recipients` set to `!False`.)
|
||||
|
||||
.. versionadded:: 0.3
|
||||
Previously "bcc" was treated as "cc"
|
||||
|
||||
|
||||
.. _sending-html:
|
||||
|
||||
**HTML/Alternative Parts**
|
||||
To include an HTML version of a message, use
|
||||
:meth:`~django.core.mail.EmailMultiAlternatives.attach_alternative`:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from django.core.mail import EmailMultiAlternatives
|
||||
|
||||
msg = EmailMultiAlternatives("Subject", "text body",
|
||||
"from@example.com", ["to@example.com"])
|
||||
msg.attach_alternative("<html>html body</html>", "text/html")
|
||||
|
||||
Djrill allows a maximum of one
|
||||
:meth:`~django.core.mail.EmailMultiAlternatives.attach_alternative`
|
||||
on a message, and it must be ``mimetype="text/html"``.
|
||||
Otherwise, Djrill will raise :exc:`~djrill.NotSupportedByMandrillError` when you
|
||||
attempt to send the message. (Mandrill doesn't support sending multiple html
|
||||
alternative parts, or any non-html alternatives.)
|
||||
|
||||
|
||||
.. _sending-attachments:
|
||||
|
||||
**Attachments**
|
||||
Djrill will send a message's attachments. (Note that Mandrill may impose limits
|
||||
on size and type of attachments.)
|
||||
|
||||
Also, if an image attachment has a Content-ID header, Djrill will tell Mandrill
|
||||
to treat that as an embedded image rather than an ordinary attachment.
|
||||
(For an example, see :meth:`~DjrillBackendTests.test_embedded_images`
|
||||
in :file:`tests/test_mandrill_send.py`.)
|
||||
|
||||
.. versionadded:: 0.3
|
||||
Attachments
|
||||
|
||||
.. versionchanged:: 0.4
|
||||
Special handling for embedded images
|
||||
|
||||
**Headers**
|
||||
Djrill accepts additional headers, but only ``Reply-To`` and
|
||||
``X-*`` (since that is all that Mandrill accepts). Any other extra headers
|
||||
will raise :exc:`~djrill.NotSupportedByMandrillError` when you attempt to send the
|
||||
message.
|
||||
|
||||
|
||||
.. _mandrill-send-support:
|
||||
|
||||
Mandrill-Specific Options
|
||||
-------------------------
|
||||
|
||||
Most of the options from the Mandrill
|
||||
`messages/send API <https://mandrillapp.com/api/docs/messages.html#method=send>`_
|
||||
`message` struct can be set directly on an :class:`~django.core.mail.EmailMessage`
|
||||
(or subclass) object:
|
||||
|
||||
.. attribute:: track_opens
|
||||
|
||||
``Boolean``: whether Mandrill should enable open-tracking for this message.
|
||||
Default from your Mandrill account settings. ::
|
||||
|
||||
message.track_opens = True
|
||||
|
||||
.. attribute:: track_clicks
|
||||
|
||||
``Boolean``: whether Mandrill should enable click-tracking for this message.
|
||||
Default from your Mandrill account settings.
|
||||
|
||||
.. note::
|
||||
|
||||
Mandrill has an option to track clicks in HTML email but not plaintext, but
|
||||
it's *only* available in your Mandrill account settings. If you want to use that
|
||||
option, set it at Mandrill, and *don't* set the ``track_clicks`` attribute here.
|
||||
|
||||
.. attribute:: auto_text
|
||||
|
||||
``Boolean``: whether Mandrill should automatically generate a text body from the HTML.
|
||||
Default from your Mandrill account settings.
|
||||
|
||||
.. attribute:: url_strip_qs
|
||||
|
||||
``Boolean``: whether Mandrill should ignore any query parameters when aggregating
|
||||
URL tracking data. Default from your Mandrill account settings.
|
||||
|
||||
.. attribute:: preserve_recipients
|
||||
|
||||
``Boolean``: whether Mandrill should include all recipients in the "to" message header.
|
||||
Default from your Mandrill account settings.
|
||||
|
||||
.. attribute:: global_merge_vars
|
||||
|
||||
``dict``: merge variables to use for all recipients (most useful with :ref:`mandrill-templates`). ::
|
||||
|
||||
message.global_merge_vars = {'company': "ACME", 'offer': "10% off"}
|
||||
|
||||
.. attribute:: recipient_merge_vars
|
||||
|
||||
``dict``: per-recipient merge variables (most useful with :ref:`mandrill-templates`). The keys
|
||||
in the dict are the recipient email addresses, and the values are dicts of merge vars for
|
||||
each recipient::
|
||||
|
||||
message.recipient_merge_vars = {
|
||||
'wiley@example.com': {'offer': "15% off anvils"},
|
||||
'rr@example.com': {'offer': "instant tunnel paint"}
|
||||
}
|
||||
|
||||
.. attribute:: tags
|
||||
|
||||
``list`` of ``str``: tags to apply to the message, for filtering reports in the Mandrill
|
||||
dashboard. (Note that Mandrill prohibits tags longer than 50 characters or starting with
|
||||
underscores.) ::
|
||||
|
||||
message.tags = ["Order Confirmation", "Test Variant A"]
|
||||
|
||||
.. attribute:: google_analytics_domains
|
||||
|
||||
``list`` of ``str``: domain names for links where Mandrill should add Google Analytics
|
||||
tracking parameters. ::
|
||||
|
||||
message.google_analytics_domains = ["example.com"]
|
||||
|
||||
.. attribute:: google_analytics_campaign
|
||||
|
||||
``str`` or ``list`` of ``str``: the utm_campaign tracking parameter to attach to links
|
||||
when adding Google Analytics tracking. (Mandrill defaults to the message's from_email as
|
||||
the campaign name.)
|
||||
|
||||
.. attribute:: metadata
|
||||
|
||||
``dict``: metadata values Mandrill should store with the message for later search and
|
||||
retrieval. ::
|
||||
|
||||
message.metadata = {'customer': customer.id, 'order': order.reference_number}
|
||||
|
||||
.. attribute:: recipient_metadata
|
||||
|
||||
``dict``: per-recipient metadata values. Keys are the recipient email addresses,
|
||||
and values are dicts of metadata for each recipient (similar to
|
||||
:attr:`recipient_merge_vars`)
|
||||
|
||||
|
||||
These Mandrill-specific properties work with *any*
|
||||
:class:`~django.core.mail.EmailMessage`-derived object, so you can use them with
|
||||
many other apps that add Django mail functionality.
|
||||
|
||||
If you have questions about the python syntax for any of these properties,
|
||||
see :class:`DjrillMandrillFeatureTests` in :file:`tests/test_mandrill_send.py` for examples.
|
||||
|
||||
|
||||
.. _djrill-exceptions:
|
||||
|
||||
Exceptions
|
||||
----------
|
||||
|
||||
.. versionadded:: 0.3
|
||||
Djrill-specific exceptions
|
||||
|
||||
.. exception:: djrill.NotSupportedByMandrillError
|
||||
|
||||
If the email tries to use features that aren't supported by Mandrill, the send
|
||||
call will raise a :exc:`~!djrill.NotSupportedByMandrillError` exception (a subclass
|
||||
of :exc:`ValueError`).
|
||||
|
||||
|
||||
.. exception:: djrill.MandrillAPIError
|
||||
|
||||
If the Mandrill API fails or returns an error response, the send call will
|
||||
raise a :exc:`~!djrill.MandrillAPIError` exception (a subclass of :exc:`requests.HTTPError`).
|
||||
The exception's :attr:`status_code` and :attr:`response` attributes may
|
||||
help explain what went wrong.
|
||||
70
docs/usage/templates.rst
Normal file
70
docs/usage/templates.rst
Normal file
@@ -0,0 +1,70 @@
|
||||
Sending Template Mail
|
||||
=====================
|
||||
|
||||
.. _mandrill-templates:
|
||||
|
||||
Mandrill Templates
|
||||
------------------
|
||||
|
||||
.. versionadded:: 0.3
|
||||
Mandrill template support
|
||||
|
||||
To use a *Mandrill* (MailChimp) template stored in your Mandrill account,
|
||||
set a :attr:`template_name` and (optionally) :attr:`template_content`
|
||||
on your :class:`~django.core.mail.EmailMessage` object::
|
||||
|
||||
from django.core.mail import EmailMessage
|
||||
|
||||
msg = EmailMessage(subject="Shipped!", from_email="store@example.com",
|
||||
to=["customer@example.com", "accounting@example.com"])
|
||||
msg.template_name = "SHIPPING_NOTICE" # A Mandrill template name
|
||||
msg.template_content = { # Content blocks to fill in
|
||||
'TRACKING_BLOCK': "<a href='.../*|TRACKINGNO|*'>track it</a>"
|
||||
}
|
||||
msg.global_merge_vars = { # Merge tags in your template
|
||||
'ORDERNO': "12345", 'TRACKINGNO': "1Z987"
|
||||
}
|
||||
msg.merge_vars = { # Per-recipient merge tags
|
||||
'accounting@example.com': {'NAME': "Pat"},
|
||||
'customer@example.com': {'NAME': "Kim"}
|
||||
}
|
||||
msg.send()
|
||||
|
||||
If :attr:`template_name` is set, Djrill will use Mandrill's
|
||||
`messages/send-template API <https://mandrillapp.com/api/docs/messages.html#method=send-template>`_,
|
||||
and will ignore any `body` text set on the `EmailMessage`.
|
||||
|
||||
All of Djrill's other :ref:`Mandrill-specific options <mandrill-send-support>`
|
||||
can be used with templates.
|
||||
|
||||
|
||||
.. _django-templates:
|
||||
|
||||
Django Templates
|
||||
----------------
|
||||
|
||||
To compose email using *Django* templates, you can use Django's
|
||||
:func:`~django.template.loaders.django.template.loader.render_to_string`
|
||||
template shortcut to build the body and html.
|
||||
|
||||
Example that builds an email from the templates ``message_subject.txt``,
|
||||
``message_body.txt`` and ``message_body.html``::
|
||||
|
||||
from django.core.mail import EmailMultiAlternatives
|
||||
from django.template import Context
|
||||
from django.template.loader import render_to_string
|
||||
|
||||
template_data = {
|
||||
'ORDERNO': "12345", 'TRACKINGNO': "1Z987"
|
||||
}
|
||||
|
||||
plaintext_context = Context(autoescape=False) # HTML escaping not appropriate in plaintext
|
||||
subject = render_to_string("message_subject.txt", template_data, plaintext_context)
|
||||
text_body = render_to_string("message_body.txt", template_data, plaintext_context)
|
||||
html_body = render_to_string("message_body.html", template_data)
|
||||
|
||||
msg = EmailMessage(subject=subject, from_email="store@example.com",
|
||||
to=["customer@example.com"], body=text_body)
|
||||
msg.attach_alternative(html_body, "text/html")
|
||||
msg.send()
|
||||
|
||||
Reference in New Issue
Block a user