From c3da0432602aca26991567d5aa87540ab7b66a04 Mon Sep 17 00:00:00 2001 From: medmunds Date: Wed, 17 Apr 2013 16:02:29 -0700 Subject: [PATCH] Document webhook support --- AUTHORS.txt | 1 + README.rst | 2 + docs/history.rst | 1 + docs/index.rst | 1 + docs/installation.rst | 7 ++ docs/usage/webhooks.rst | 152 ++++++++++++++++++++++++++++++++++++++++ 6 files changed, 164 insertions(+) create mode 100644 docs/usage/webhooks.rst diff --git a/AUTHORS.txt b/AUTHORS.txt index f3734b6..33cc945 100644 --- a/AUTHORS.txt +++ b/AUTHORS.txt @@ -9,3 +9,4 @@ Théo Crevon Rafael E. Belliard Jared Morse peillis +José Padilla diff --git a/README.rst b/README.rst index e9a642a..35d8a3c 100644 --- a/README.rst +++ b/README.rst @@ -26,6 +26,8 @@ package. It includes: * Support for HTML, attachments, extra headers, and other features of `Django's built-in email `_ * Mandrill-specific extensions like tags, metadata, tracking, and MailChimp templates +* Optional support for Mandrill inbound email and other webhook notifications, + via Django signals * An optional Django admin interface Djrill is released under the BSD license. It is tested against Django 1.3, 1.4, and 1.5 diff --git a/docs/history.rst b/docs/history.rst index e5ecf39..ce40a5a 100644 --- a/docs/history.rst +++ b/docs/history.rst @@ -3,6 +3,7 @@ Release Notes Version 0.5 (development): +* Support for incoming mail and other Mandrill webhooks * Support for Mandrill send options :attr:`auto_html`, :attr:`tracking_domain` and :attr:`signing_domain`. diff --git a/docs/index.rst b/docs/index.rst index 169b3a3..f1ed306 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -26,6 +26,7 @@ Documentation usage/sending_mail usage/templates usage/multiple_backends + usage/webhooks contributing history diff --git a/docs/installation.rst b/docs/installation.rst index d9af9ac..464fcb7 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -33,6 +33,13 @@ In your project's :file:`settings.py`: EMAIL_BACKEND = "djrill.mail.backends.djrill.DjrillBackend" +Mandrill Webhooks (Optional) +---------------------------- + +Djrill includes optional support for Mandrill webhooks, including inbound email. +See the Djrill :ref:`webhooks ` section for configuration details. + + Admin (Optional) ---------------- diff --git a/docs/usage/webhooks.rst b/docs/usage/webhooks.rst new file mode 100644 index 0000000..8874cf5 --- /dev/null +++ b/docs/usage/webhooks.rst @@ -0,0 +1,152 @@ +.. _webhooks: + +Mandrill Webhooks and Inbound Email +=================================== + +`Mandrill webhooks`_ are used for notification about outbound messages +(bounces, clicks, etc.), and also for delivering inbound email +processed through Mandrill. + +Djrill includes optional support for Mandrill's webhook notifications. +If enabled, it will send a Django signal for each event in a webhook. +Your code can connect to this signal for further processing. + +.. versionadded:: 0.5 + Webhook support + + +.. warning:: Webhook Security + + Webhooks are ordinary urls---they're wide open to the internet. + You must take steps to secure webhooks, or anyone could submit + random (or malicious) data to your app simply by invoking your + webhook URL. For security: + + * Your webhook should only be accessible over SSL (https). + (This is beyond the scope of Djrill.) + + * Your webhook must include a random, secret key, known only to your + app and Mandrill. Djrill will verify calls to your webhook, and will + reject calls without the correct key. + + +.. _Mandrill webhooks: http://help.mandrill.com/entries/21738186-Introduction-to-Webhooks +.. _securing webhooks: http://apidocs.mailchimp.com/webhooks/#securing-webhooks + + +.. _webhooks-config: + +Configuration +------------- + +To enable Djrill webhook processing you need to create and set a webhook +secret in your project settings, include the Djrill url routing, and +then add the webhook in the Mandrill control panel. + +1. In your project's :file:`settings.py`, add a :setting:`DJRILL_WEBHOOK_SECRET`: + + .. code-block:: python + + DJRILL_WEBHOOK_SECRET = "" + + substituting a secret you've generated just for Mandrill webhooks. + (Do *not* use your Mandrill API key or Django SECRET_KEY for this!) + + An easy way to generate a random secret is to run the command below in a shell: + + .. code-block:: console + + $ python -c "from django.utils import crypto; print crypto.get_random_string(16)" + + +2. In your base :file:`urls.py`, add routing for the Djrill urls: + + .. code-block:: python + + urlpatterns = patterns('', + ... + url(r'^djrill/', include(djrill.urls)), + ) + + +3. Now you need to tell Mandrill about your webhook: + + * For receiving events on sent messages (e.g., bounces or clickthroughs), + you'll do this in Mandrill's `webhooks control panel`_. + * For setting up inbound email through Mandrill, you'll add your webhook + to Mandrill's `inbound settings`_ under "Routes" for your domain. + * And if you want both, you'll need to add the webhook in both places. + + In all cases, the "Post to URL" is + :samp:`{https://yoursite.example.com}/djrill/webhook/?secret={your-secret}` + substituting your app's own domain, and changing *your-secret* to the secret + you created in step 1. + + (For sent-message webhooks, don't forget to tick the "Trigger on Events" + checkboxes for the events you want to receive.) + + +Once you've completed these steps and your Django app is live on your site, +you can use the Mandrill "Test" commands to verify your webhook configuration. +Then see the next section for setting up Django signal handlers to process +the webhooks. + +Incidentally, you have some control over the webhook url. +If you'd like to change the "djrill" prefix, that comes from +the url config in step 2. And if you'd like to change +the *name* of the "secret" query string parameter, you can set +:setting:`DJRILL_WEBHOOK_SECRET_NAME` in your :file:`settings.py`. + + +.. _webhooks control panel: https://mandrillapp.com/settings/webhooks +.. _inbound settings: https://mandrillapp.com/inbound + + +.. _webhook-usage: + +Webhook Notifications +--------------------- + +Once you've enabled webhooks, Djrill will send a ``djrill.signals.webhook_event`` +custom `Django signal`_ for each Mandrill event it receives. +You can connect to this signal for further processing. +Examples: + +.. code-block:: python + + from djrill.signals import webhook_event + from django.dispatch import receiver + + @receiver(webhook_event) + def handle_bounce(sender, event_type, data, **kwargs): + if event_type == 'hard_bounce' or event_type == 'soft_bounce': + print "Message to %s bounced: %s" % ( + data['msg']['email'], + data['msg']['bounce_description'] + ) + + @receiver(webhook_event) + def handle_inbound(sender, event_type, data, **kwargs): + if event_type == 'inbound': + print "Inbound message from %s: %s" % ( + data['msg']['from_email'], + data['msg']['subject'] + ) + + +Note that your webhook_event signal handlers will be called for all Mandrill +webhook callbacks, so you should always check the `event_type` param as shown +in the examples above to ensure you're processing the expected events. + +Mandrill batches up multiple events into a single webhook call. +Djrill will invoke your signal handler once for each event in the batch. + +The available fields in the `data` param are described in Mandrill's documentation: +`sent-message webhooks`_ and `inbound webhooks`_. + +.. _Django signal: https://docs.djangoproject.com/en/dev/topics/signals/ +.. _inbound webhooks: + http://help.mandrill.com/entries/22092308-What-is-the-format-of-inbound-email-webhooks- +.. _sent-message webhooks: http://help.mandrill.com/entries/21738186-Introduction-to-Webhooks + +