Skip to content

Commit

Permalink
feat: unofficial brevo first open via proxy.
Browse files Browse the repository at this point in the history
  • Loading branch information
originell committed Jul 25, 2024
1 parent e266b9d commit c0e732d
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 2 deletions.
2 changes: 2 additions & 0 deletions anymail/webhooks/brevo.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ def parse_events(self, request):
"unique_opened": (EventType.OPENED, None),
# open, but "loaded via proxy" (e.g., Apple Mail)
"proxy_open": (EventType.OPENED, None),
# first open; but "loaded via proxy" (e.g., Apple Mail)
"unique_proxy_open": (EventType.OPENED, None),
"click": (EventType.CLICKED, None),
"unsubscribe": (EventType.UNSUBSCRIBED, None),
"error": (EventType.FAILED, None),
Expand Down
8 changes: 6 additions & 2 deletions docs/esps/brevo.rst
Original file line number Diff line number Diff line change
Expand Up @@ -340,11 +340,15 @@ deliver both events for the first open, so be sure to check their current behavi
if duplicate first open events might cause problems for you. You might be able to use
the event timestamp to de-dupe.).

Furthermore, there is the "Loaded by Proxy" event. Primarily, it is sent for opens
that happen in Apple Mail, due to Apple proxying these to protect user's IP addresses.
Furthermore, there is the "Loaded by Proxy" event. Primarily, it is sent for every open
that happens in Apple Mail, due to Apple proxying these to protect user's IP addresses.
Anymail normalizes this to "opened" as well. See the `Brevo docs on this`_ for more
details.

Unofficially, there is also a "First open but loaded by Proxy" event. This is not sent
by default. Not even if you check the webhook event "loaded by Proxy" in the Brevo UI.
You can, however, let the support activate it. Anymail will then handle it as "open".

Brevo will report these Anymail :attr:`~anymail.signals.AnymailTrackingEvent.event_type`\s:
queued, rejected, bounced, deferred, delivered, opened (see note above), clicked, complained,
unsubscribed, subscribed (though this should never occur for transactional email).
Expand Down
33 changes: 33 additions & 0 deletions tests/test_brevo_webhooks.py
Original file line number Diff line number Diff line change
Expand Up @@ -435,6 +435,39 @@ def test_proxy_open_event(self):
event = kwargs["event"]
self.assertEqual(event.event_type, "opened")

def test_unique_proxy_open_event(self):
# Sadly, undocumented in Brevo.
# Equivalent to "First Open but loaded via Proxy".
# This is sent when a tracking pixel is loaded via a 'privacy proxy server'.
# This technique is used by Apple Mail, for example, to protect user's IP
# addresses.
raw_event = {
"event": "unique_proxy_open",
"email": "[email protected]",
"id": 1,
"date": "2020-10-09 00:00:00",
"message-id": "[email protected]",
"subject": "My first Transactional",
"tag": ["transactionalTag"],
"sending_ip": "xxx.xxx.xxx.xxx",
"s_epoch": 1534486682000,
"template_id": 1,
}
response = self.client.post(
"/anymail/brevo/tracking/",
content_type="application/json",
data=json.dumps(raw_event),
)
self.assertEqual(response.status_code, 200)
kwargs = self.assert_handler_called_once_with(
self.tracking_handler,
sender=BrevoTrackingWebhookView,
event=ANY,
esp_name="Brevo",
)
event = kwargs["event"]
self.assertEqual(event.event_type, "opened")

def test_clicked_event(self):
raw_event = {
"event": "click",
Expand Down

0 comments on commit c0e732d

Please sign in to comment.