diff --git a/djrill/tests/test_mandrill_webhook.py b/djrill/tests/test_mandrill_webhook.py index 661d42e..0c24d09 100644 --- a/djrill/tests/test_mandrill_webhook.py +++ b/djrill/tests/test_mandrill_webhook.py @@ -101,3 +101,22 @@ class DjrillWebhookViewTests(TestCase): }) self.assertEqual(response.status_code, 200) self.assertEqual(self.signal_received_count, 1) + + def test_webhook_sync_event(self): + # Mandrill sync events use a different format from other events + # https://mandrill.zendesk.com/hc/en-us/articles/205583297-Sync-Event-Webhook-format + self.signal_received_count = 0 + test_event = {"type": "whitelist", "action": "add"} + + def my_callback(sender, event_type, data, **kwargs): + self.signal_received_count += 1 + self.assertEqual(event_type, 'whitelist_add') # synthesized event_type + self.assertEqual(data, test_event) + + webhook_event.connect(my_callback) + + response = self.client.post('/webhook/?secret=abc123', { + 'mandrill_events': json.dumps([test_event]) + }) + self.assertEqual(response.status_code, 200) + self.assertEqual(self.signal_received_count, 1) diff --git a/djrill/views.py b/djrill/views.py index 833bde6..7cb14ab 100644 --- a/djrill/views.py +++ b/djrill/views.py @@ -79,6 +79,21 @@ class DjrillWebhookView(DjrillWebhookSecretMixin, DjrillWebhookSignatureMixin, V for event in data: webhook_event.send( - sender=None, event_type=event['event'], data=event) + sender=None, event_type=self.get_event_type(event), data=event) return HttpResponse() + + def get_event_type(self, event): + try: + # Message event: https://mandrill.zendesk.com/hc/en-us/articles/205583307 + # Inbound event: https://mandrill.zendesk.com/hc/en-us/articles/205583207 + event_type = event['event'] + except KeyError: + try: + # Sync event: https://mandrill.zendesk.com/hc/en-us/articles/205583297 + # Synthesize an event_type like "whitelist_add" or "blacklist_change" + event_type = "%s_%s" % (event['type'], event['action']) + except KeyError: + # Unknown future event format + event_type = None + return event_type diff --git a/docs/history.rst b/docs/history.rst index 48c08c2..89e98ce 100644 --- a/docs/history.rst +++ b/docs/history.rst @@ -15,6 +15,8 @@ Djrill 2.x Version 2.1 (in development): +* Handle Mandrill rejection whitelist/blacklist sync event webhooks + Version 2.0: diff --git a/docs/usage/webhooks.rst b/docs/usage/webhooks.rst index 3e0f6bc..e33dce3 100644 --- a/docs/usage/webhooks.rst +++ b/docs/usage/webhooks.rst @@ -138,6 +138,15 @@ Examples: data['msg']['subject'] ) + @receiver(webhook_event) + def handle_whitelist_sync(sender, event_type, data, **kwargs): + if event_type == 'whitelist_add' or event_type == 'whitelist_remove': + print "Rejection whitelist update: %s email %s (%s)" % ( + data['action'], + data['reject']['email'], + data['reject']['reason'] + ) + 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 @@ -147,11 +156,11 @@ 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`_. +`sent-message webhooks`_, `inbound webhooks`_, and `whitelist/blacklist sync webooks`_. .. _Django signal: https://docs.djangoproject.com/en/stable/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 - - +.. _whitelist/blacklist sync webooks: + https://mandrill.zendesk.com/hc/en-us/articles/205583297-Sync-Event-Webhook-format