Delivery status via webhooks, not polling
Why it matters
Polling the ESP's message status API on a timer introduces latency (you learn about a hard bounce minutes later, not seconds), consumes API quota on every poll cycle, and misses events that occur between polling intervals. Gmail and Yahoo's 2024 bulk sender requirements mandate one-click unsubscribe processing — a webhook-less implementation cannot honor those events promptly. CWE-345 covers insufficient verification of data authenticity; a webhook without HMAC signature verification lets anyone inject fake delivery events and manipulate your suppression list.
Severity rationale
High because missing webhook processing means delivery failures, bounces, and unsubscribe events are never recorded, leading to repeated sends to invalid addresses and sender reputation damage.
Remediation
Register a webhook endpoint at app/api/webhooks/sendgrid/route.ts (Next.js App Router) that verifies the HMAC signature before processing events:
const signature = req.headers.get('x-twilio-email-event-webhook-signature') ?? ''
const timestamp = req.headers.get('x-twilio-email-event-webhook-timestamp') ?? ''
const payload = timestamp + await req.text()
const computed = crypto.createHmac('sha256', process.env.SENDGRID_WEBHOOK_SECRET!)
.update(payload).digest('base64')
if (computed !== signature) return new Response('Invalid signature', { status: 401 })
Process at minimum delivered, bounce, and spamreport event types and update your emailSendLog table accordingly.
DetectionPro
The detection method for this pattern is part of AuditBuffet Pro.
The full method (what to look for, pass and fail conditions, and how results get reported) ships inside the Sending Pipeline & Infrastructure Audit. The pattern definition, severity rationale, and remediation remain openly licensed under CC-BY-4.0.
External references
- cwe · CWE-345 — Insufficient Verification of Data Authenticity
- external · gmail-yahoo-bulk-sender-2024 — Google/Yahoo Bulk Sender Requirements (2024)
Taxons
History
- 2026-04-18·v1.0.0·Initial import from sending-pipeline-infrastructure·automated