Track email opens and clicks on recipient status.
Deploy Beta / unit-tests (push) Successful in 13s
Deploy Beta / docker (push) Successful in 17s
Deploy Beta / deploy-beta (push) Successful in 1m39s

SMTP2GO open/click webhooks now advance Message to opened/clicked, and the campaign engagement chart uses live stats instead of placeholder bars.
This commit is contained in:
2026-08-10 10:24:26 -05:00
parent 8680c082fe
commit f7f3174e1c
8 changed files with 252 additions and 33 deletions
+38 -2
View File
@@ -382,7 +382,7 @@ class Smtp2goEmailWebhookTests(TestCase):
).exists()
)
def test_open_records_event_keeps_delivered(self):
def test_open_records_event_sets_opened(self):
self.message.status = Message.Status.DELIVERED
self.message.save(update_fields=["status"])
url = reverse("messaging:email_webhook")
@@ -395,13 +395,46 @@ class Smtp2goEmailWebhookTests(TestCase):
},
)
self.message.refresh_from_db()
self.assertEqual(self.message.status, Message.Status.DELIVERED)
self.assertEqual(self.message.status, Message.Status.OPENED)
self.assertTrue(
ProviderEvent.objects.filter(
message=self.message, event_type="open"
).exists()
)
def test_click_sets_clicked_from_sent(self):
url = reverse("messaging:email_webhook")
self.client.post(
url,
data={
"event": "click",
"rcpt": "pat@example.com",
"X-Monica-Message-Id": str(self.message.pk),
},
)
self.message.refresh_from_db()
self.assertEqual(self.message.status, Message.Status.CLICKED)
self.assertTrue(
ProviderEvent.objects.filter(
message=self.message, event_type="click"
).exists()
)
def test_open_does_not_downgrade_clicked(self):
self.message.status = Message.Status.CLICKED
self.message.save(update_fields=["status"])
url = reverse("messaging:email_webhook")
self.client.post(
url,
data={
"event": "open",
"rcpt": "pat@example.com",
"X-Monica-Message-Id": str(self.message.pk),
},
)
self.message.refresh_from_db()
self.assertEqual(self.message.status, Message.Status.CLICKED)
def test_hard_bounce_suppresses_contact(self):
url = reverse("messaging:email_webhook")
self.client.post(
@@ -449,6 +482,9 @@ class Smtp2goEmailWebhookTests(TestCase):
self.assertEqual(response.status_code, 200)
data = response.json()
self.assertEqual(data["stats"]["opens"], 1)
self.assertIn("chart_bars", data["stats"])
labels = [bar["label"] for bar in data["stats"]["chart_bars"]]
self.assertEqual(labels, ["Sent", "Delivered", "Opens", "Clicks", "Failed"])
def test_bearer_authorization_header(self):
import json