Skip to content

Commit 7e90818

Browse files
committed
Postmark: support "clicked" tracking events
Handle Postmark's new click webhook. Closes #78
1 parent 930753e commit 7e90818

File tree

3 files changed

+57
-4
lines changed

3 files changed

+57
-4
lines changed

anymail/webhooks/postmark.py

+4-1
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ class PostmarkTrackingWebhookView(PostmarkBaseWebhookView):
4949
'DMARCPolicy': (EventType.REJECTED, RejectReason.BLOCKED),
5050
'TemplateRenderingFailed': (EventType.FAILED, None),
5151
# DELIVERED doesn't have a Type field; detected separately below
52-
# CLICKED doesn't have a Postmark webhook (yet?)
52+
# CLICKED doesn't have a Type field; detected separately below
5353
# OPENED doesn't have a Type field; detected separately below
5454
# INBOUND doesn't have a Type field; should come in through different webhook
5555
}
@@ -62,6 +62,8 @@ def esp_to_anymail_event(self, esp_event):
6262
except KeyError:
6363
if 'FirstOpen' in esp_event:
6464
event_type = EventType.OPENED
65+
elif 'OriginalLink' in esp_event:
66+
event_type = EventType.CLICKED
6567
elif 'DeliveredAt' in esp_event:
6668
event_type = EventType.DELIVERED
6769
elif 'From' in esp_event:
@@ -103,4 +105,5 @@ def esp_to_anymail_event(self, esp_event):
103105
tags=tags,
104106
timestamp=timestamp,
105107
user_agent=esp_event.get('UserAgent', None),
108+
click_url=esp_event.get('OriginalLink', None),
106109
)

docs/esps/postmark.rst

+3-2
Original file line numberDiff line numberDiff line change
@@ -191,8 +191,9 @@ If you use multiple Postmark servers, you'll need to repeat entering the webhook
191191
settings for each of them.
192192

193193
Postmark will report these Anymail :attr:`~anymail.signals.AnymailTrackingEvent.event_type`\s:
194-
rejected, failed, bounced, deferred, delivered, autoresponded, opened, complained,
195-
unsubscribed, subscribed. (Postmark does not support sent or clicked events.)
194+
rejected, failed, bounced, deferred, delivered, autoresponded, opened, clicked, complained,
195+
unsubscribed, subscribed. (Postmark does not support sent--what it calls "processed"--events
196+
through webhooks.)
196197

197198
The event's :attr:`~anymail.signals.AnymailTrackingEvent.esp_event` field will be
198199
a `dict` of Postmark `delivery <http://developer.postmarkapp.com/developer-delivery-webhook.html>`_,

tests/test_postmark_webhooks.py

+50-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import json
22
from datetime import datetime
33

4-
from django.utils.timezone import get_fixed_timezone
4+
from django.utils.timezone import get_fixed_timezone, utc
55
from mock import ANY
66

77
from anymail.signals import AnymailTrackingEvent
@@ -109,3 +109,52 @@ def test_open_event(self):
109109
self.assertEqual(event.user_agent, "Mozilla/5.0 (Windows NT 5.1; rv:11.0) Gecko Firefox/11.0")
110110
self.assertEqual(event.tags, [])
111111
self.assertEqual(event.metadata, {})
112+
113+
def test_click_event(self):
114+
raw_event = {
115+
"ClickLocation": "HTML",
116+
"Client": {
117+
"Name": "Chrome 35.0.1916.153",
118+
"Company": "Google",
119+
"Family": "Chrome"
120+
},
121+
"OS": {
122+
"Name": "OS X 10.7 Lion",
123+
"Company": "Apple Computer, Inc.",
124+
"Family": "OS X 10"
125+
},
126+
"Platform": "Desktop",
127+
"UserAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_5) etc.",
128+
"OriginalLink": "https://example.com/click/me",
129+
"Geo": {
130+
"CountryISOCode": "RS",
131+
"Country": "Serbia",
132+
"RegionISOCode": "VO",
133+
"Region": "Autonomna Pokrajina Vojvodina",
134+
"City": "Novi Sad",
135+
"Zip": "21000",
136+
"Coords": "45.2517,19.8369",
137+
"IP": "8.8.8.8"
138+
},
139+
"MessageID": "f4830d10-9c35-4f0c-bca3-3d9b459821f8",
140+
"ReceivedAt": "2017-10-25T15:21:11.9065619Z",
141+
"Tag": "welcome-email",
142+
"Recipient": "[email protected]"
143+
}
144+
response = self.client.post('/anymail/postmark/tracking/',
145+
content_type='application/json', data=json.dumps(raw_event))
146+
self.assertEqual(response.status_code, 200)
147+
kwargs = self.assert_handler_called_once_with(self.tracking_handler, sender=PostmarkTrackingWebhookView,
148+
event=ANY, esp_name='Postmark')
149+
event = kwargs['event']
150+
self.assertIsInstance(event, AnymailTrackingEvent)
151+
self.assertEqual(event.event_type, "clicked")
152+
self.assertEqual(event.esp_event, raw_event)
153+
self.assertEqual(event.timestamp, datetime(2017, 10, 25, 15, 21, 11, microsecond=906561,
154+
tzinfo=utc))
155+
self.assertEqual(event.message_id, "f4830d10-9c35-4f0c-bca3-3d9b459821f8")
156+
self.assertEqual(event.recipient, "[email protected]")
157+
self.assertEqual(event.user_agent, "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_5) etc.")
158+
self.assertEqual(event.click_url, "https://example.com/click/me")
159+
self.assertEqual(event.tags, ["welcome-email"])
160+
self.assertEqual(event.metadata, {})

0 commit comments

Comments
 (0)