Skip to main content
MailCub Logo Image
Guidelines

Email Webhooks 101: Delivered, Bounced, Complaints, Unsubscribes

By MailCub TeamFeb 24, 202614 min read

“Send succeeded” is not the same as “email delivered.” After your provider accepts a message, it can still bounce, get deferred, be marked as spam, or trigger an unsubscribe.

That is why email webhooks matter. They let your provider send delivery events to your endpoint so your app can update state automatically without polling. For SaaS and development teams, this is the difference between guessing and knowing what happened to OTPs, password resets, receipts, and alerts.

In this guide, you will learn the core event types (delivered, bounced, complaints, unsubscribes), what actions to take for each, and how to build a production-ready webhook handler. We will also cover security, idempotency, retries, and how to connect events to suppression lists and user preferences.

You can use MailCub Transactional Email for sending and event tracking, and refer to the MailCub Documentation while implementing your webhook flow.

Quick Answer

  • Webhooks push email lifecycle events (delivered, bounced, complaint, unsubscribe) to your app via HTTP POST.
  • Process webhooks asynchronously (queue + worker) and return 2xx quickly.
  • Expect duplicates and out-of-order events, so build idempotency from day one.
  • Complaints and hard bounces should usually suppress future sends to that address.
  • Unsubscribes should update preferences and suppress marketing streams.

Why it matters

If you do not capture events, your support team cannot answer basic questions like “Did it bounce?” or “Was it delivered?” That turns simple incidents into long investigations.

Bounces and complaints also affect reputation. If you keep sending to invalid or unhappy recipients, future delivery gets worse. Webhooks let you react immediately by suppressing bad addresses and honoring preferences.

For transactional flows, this directly affects conversion and retention. A missed password reset is not just analytics. It is account access.

Email webhooks event types you must handle first

Different providers use different names, but these categories are common across providers.

Delivered

Meaning: The provider reports the message reached the recipient mailbox (this is not the same as opened).

What to do:

  • Mark the message status as DELIVERED.
  • Store a delivered timestamp.
  • Stop retry logic for that message.

Bounced

Meaning: Delivery failed. Some providers split bounce into hard vs soft. Others add deferred or blocked.

What to do:

  • If permanent (hard): suppress the recipient and stop retries.
  • If temporary (soft/deferred): retry with backoff and attempt limits.
  • Store the failure reason and any SMTP/enhanced code if available.

Complaints (spam reports)

Meaning: A user marked your message as spam.

What to do:

  • Suppress future non-critical sends to that recipient immediately.
  • Alert internally if complaint rate spikes.
  • Review templates, list hygiene, and sending patterns.

Unsubscribes

Meaning: The recipient opted out (usually from marketing streams).

What to do:

  • Update preference state (global or category-based).
  • Suppress marketing sends for that recipient.
  • Keep a clear policy for security/mandatory notices vs optional mail.
Event Store (minimum) Action (minimum)
delivered message_id, timestamp mark delivered; stop retries
bounced (hard) message_id, recipient, reason suppress recipient; stop future sends
deferred / soft bounce message_id, reason, attempt_count retry with backoff + caps
complaint recipient, timestamp, metadata suppress + alert on spikes
unsubscribed recipient, scope/list/category update preferences + suppress marketing

Step-by-step solution

1) Design your webhook endpoint contract

Pick one endpoint, for example:

POST /webhooks/email/events

Decide what formats you accept:

  • single event per request
  • batch of events per request

Keep the response simple:

  • 2xx for accepted requests
  • 4xx for invalid or unauthenticated requests

2) Secure email webhooks

Treat the endpoint like a payment callback. Minimum controls:

  • HTTPS only
  • shared secret or signature verification
  • strict JSON parsing and payload size limits
  • allowlisted headers if your provider documents them

Also log security failures like signature mismatch, schema invalid, and oversized payloads so your team can debug blocked events quickly.

3) Acknowledge fast, process async

Do not do heavy database work in the request thread.

Use this pattern:

  • validate
  • enqueue
  • return 2xx

Then let a worker process the event and update the database. This prevents timeouts and avoids provider retries caused by slow responses.

4) Implement idempotency because duplicates are normal

Webhook providers retry on timeouts, transient network issues, and non-2xx responses. Duplicate delivery is expected behavior.

Use a dedupe key such as:

  • event_id (preferred), or
  • a hash of provider_message_id + event_type + event_timestamp

Store dedupe keys with a TTL (for example 7–30 days) so your dedupe table stays manageable.

5) Normalize into your internal state machine

Keep state names simple and consistent, for example:

  • DELIVERED
  • DEFERRED
  • BOUNCED_HARD
  • BOUNCED_SOFT
  • COMPLAINT
  • UNSUBSCRIBED

Store the raw payload for short-term troubleshooting, and store normalized fields long-term for reporting and automation.

Use MailCub Documentation as your reference while wiring webhook events and delivery tracking into your app.

6) Connect events to product behavior

Webhook events should directly drive business rules:

  • Bounced hard → suppression list
  • Deferred/soft → retry scheduler
  • Complaint → suppression + alerts
  • Unsubscribe → preferences + suppress marketing streams

Make this behavior explicit in code reviews and documentation. Avoid hidden rules inside background workers.

7) Add monitoring that catches problems early

Track these metrics:

  • webhook received rate (by event type)
  • webhook failures (4xx/5xx)
  • processing lag (queue time)
  • duplicate rate (dedupe hits)
  • bounce and complaint rate by domain or customer

Alert on spikes and sustained drops. A silent webhook outage is often worse than a send outage because your app loses visibility.

You can review MailCub Pricing if you are planning production rollout and need to scale event tracking with your sending volume.

Common mistakes

  • Updating user state synchronously inside the webhook handler.
  • Skipping idempotency, which causes double suppression or duplicate actions.
  • Treating “accepted” as “delivered.”
  • Suppressing after one temporary failure without a retry strategy.
  • Mixing unsubscribe rules across transactional and marketing flows without a clear policy.

Troubleshooting

We are not receiving events

Check this list:

  • endpoint is reachable publicly
  • provider webhook URL is correct
  • your endpoint returns 2xx quickly
  • signature or secret validation is not rejecting silently
  • firewall or WAF is not blocking provider requests

We receive duplicates

This is expected behavior from many providers.

Fix it by adding:

  • dedupe keys + TTL
  • idempotent worker logic (no double side effects)
  • logs when duplicate events are dropped (so you can verify it is working)

Events arrive out of order

This is also common with retries, batching, and network delays.

Fix it by:

  • not assuming event order
  • storing latest state with timestamps
  • applying transitions only if the incoming event is newer than current state

FAQ

What are email webhooks?

Email webhooks are HTTP callbacks where your provider sends message lifecycle events to your server so you can update delivery status, suppression, and preferences automatically.

Delivered vs opened: what is the difference?

Delivered means the mailbox accepted the message. Opened is an engagement signal that can be blocked or inaccurate and should not drive critical application logic.

What should I do on a spam complaint event?

Suppress future non-critical sends to that recipient and investigate if complaint rates increase. Complaints are a strong stop-sending signal.

How should unsubscribes affect transactional email?

Unsubscribes should suppress marketing mail. Keep a clear policy for security or mandatory notices vs optional product messaging.

Why do webhook events duplicate or arrive out of order?

Retries, batching, and network variability are normal. Design for idempotency and timestamp-based transitions.

How do I handle hard vs soft bounces from webhook data?

Use provider hints (bounce vs deferred/blocked) and any SMTP code details available. Permanent failures should suppress. Temporary failures should retry with limits.

Conclusion

Email webhooks turn delivery outcomes into reliable application signals. Start with four core events—delivered, bounced, complaints, and unsubscribes—then build a handler that is secure, fast, idempotent, and observable.

If you do that, you will reduce “email not received” tickets, enforce preferences automatically, and protect sender reputation with suppression and smarter retries.

To implement this cleanly, use MailCub Documentation for integration details and MailCub Transactional Email for sending, logs, and event workflows.

Tags:
email webhookswebhook eventsdelivered webhookbounce webhookspam complaint webhookunsubscribe webhookwebhook securityidempotencysuppression listemail event trackingdelivery logs

You Might Also Like