Delivery Events and Diagnostics
The delivery-event taxonomy an ESP/MTA emits (processed, deferred, delivered, bounce, blocked, dropped, spam-report, open, click), plus insights reporting, delay diagnosis, and engagement-quality scoring — the instrumentation layer beneath the troubleshooting playbooks.
Operational12 min read
Who it is for ESP operators, Senders
Applies to senders on any platform
ContentsOn this page — 6 sections
When you need to know what happened to a message, or why a campaign is underperforming, the answer starts in the event stream. Every message an email service provider (ESP) handles passes through a series of states. Each change of state is an event that the platform records and can stream to you.
Bounce and complaint rates, estimates of inbox placement for each provider, delay analysis and engagement scores are all built from these events. The SendGrid Event Webhook is used below as the reference example, because it is fully specified. After the events come the reporting, delay diagnosis and engagement scoring built on them.
For the thresholds these events feed and the corrective actions they trigger, see Metrics and Benchmarks. For step-by-step diagnosis, see Delivery Troubleshooting Playbooks. Both rely on the data described here.
The event taxonomy
Events fall into three families. Delivery events record what the sending system and the receiving servers did with the message. Engagement events record what the recipient did. Account events record changes of status at platform level. SendGrid's Event Webhook posts these as JSON. The names are SendGrid's labels, but every sending infrastructure produces equivalent states.
Delivery events
| Event | Meaning | What triggers it |
|---|---|---|
| processed | The platform accepted the message and can deliver it | The message was injected, validated and queued for the outbound mail transfer agent (MTA) |
| deferred | The receiving server temporarily refused the message | A 4.x.x reply from the remote MTA (greylisting, a rate limit, "try again later"); the platform retries |
| delivered | The receiving server accepted the message (250 OK) |
The remote MTA returned a 2.x.x success reply to DATA |
| bounce | The receiving server rejected the message | A 5.x.x permanent rejection (or a temporary failure after all retries were used up), returned during the SMTP session or later in an asynchronous delivery status notification (DSN) |
| blocked | A soft bounce subtype: a temporary rejection for reasons of reputation, content or a technical problem | The remote MTA rejected the message, but not because the address is invalid; recorded as a bounce with type: "blocked" |
| dropped | The platform itself refused to send, so the message never left | The recipient is on a suppression list (after an earlier bounce, unsubscribe, spam report or invalid address), the content was flagged as spam, a header or template was invalid, or a quota was exceeded |
The distinctions an operator needs to know well:
- A deferral is not a bounce. A deferral is a temporary refusal that the platform keeps retrying. It becomes a bounce only if the retries run out. Persistent deferrals are the classic sign of throttling or rate limiting (see Delay and latency diagnosis).
- Bounced and blocked are different. SendGrid records both as a
bounceevent and tells them apart with thetypefield.type: "bounce"is a hard bounce, which is permanent (for example, the address does not exist).type: "blocked"is a soft bounce: a temporary rejection because of reputation, content or a technical problem. In the Bounces & Blocks reports in the interface, a Bounce means an invalid email address (one that never existed or was deactivated), while a Block means the message was rejected for "content and reputation issues or technical failures." A block is the receiver's judgment of you, not of the address, and it can clear once the reputation or content problem behind it is fixed. See Blocklists and Spamhaus. - A drop is the platform protecting you, or your own mistake. The platform suppressed the send before transmitting it. Most drops are healthy, because suppressing a known-bad address protects reputation. A spike in drops for unexpected reasons (an invalid template, an exceeded quota) points to a defect on the sending side, not to a problem at the receiver. Suppression-List Architecture explains how suppression is scoped.
- Delivered does not mean in the inbox.
deliveredis posted when the receiving server answers250 OK. After that, the receiver may still put the message in the inbox, queue it, file it in the spam or junk folder, drop it silently, or (at Gmail) sort it into a tab, and the sending platform receives no further signal about any of it. The only later evidence is recipient engagement (opens and clicks). A high delivered rate with near-zero engagement is the typical sign of mail going to the spam folder. This is why inbox placement can only be estimated, with seed tests and provider postmaster dashboards, and never read directly from the delivery events. See Tracking and Measurement Distortion and Reputation Monitoring.
Bounce classification
For bounce events, SendGrid adds a bounce_classification that places the SMTP failure in a category of cause an operator can act on:
| Classification | Meaning and what the operator should do |
|---|---|
| Invalid Address | The address does not exist or never existed. Remove it permanently (list hygiene) |
| Mailbox Unavailable | The mailbox is full or temporarily unreachable. Often soft; may recover |
| Technical | A DNS, connection, protocol or TLS failure, on the infrastructure side |
| Content | The message content triggered a rejection or filtering. Fix the content or links |
| Reputation | The reputation of the sending IP address or domain caused the rejection. Work on reputation |
| Frequency/Volume | The sending rate or volume is too high for the receiver. Throttle (see MTA Delivery Tuning) |
| Unclassified | The failure could not be mapped to a category |
The Content and Reputation categories feed engagement quality scoring (below) as an early warning, because they show that the receiver is judging you, not that the address is bad.
Engagement events
| Event | Meaning | What triggers it |
|---|---|---|
| open | The recipient displayed the HTML message | The open-tracking pixel loaded (Open Tracking must be enabled) |
| click | The recipient clicked a tracked link | A wrapped link was followed (Click Tracking must be enabled) |
| spamreport | The recipient marked the message as spam (a complaint) | The recipient's "mark as spam" action, passed on through the provider's feedback loop |
| unsubscribe | The recipient clicked the global link to opt out of all mail | Subscription Tracking is enabled |
| group_unsubscribe | The recipient unsubscribed from one suppression group | A group unsubscribe link or the preferences page |
| group_resubscribe | The recipient subscribed to a group again | The preferences page (Subscription Tracking enabled) |
Two cautions keep the engagement events from misleading you:
- Machine opens. SendGrid sets
sg_machine_open: truewhen Apple Mail Privacy Protection (MPP), rather than a person, generated the open. Filter these out of any real measure of engagement. Gmail's image prefetching also triggers opens without a person. See Tracking and Measurement Distortion and Non-Human Interactions. - spamreport is your complaint signal. It is the part of the provider feedback loop that the sender sees. A sustained spamreport rate is the most damaging single input to reputation. See Complaint Feedback Loops.
Account events
SendGrid emits account_status_change when the platform changes an account's standing for compliance reasons (phishing, high spam rates, "other bad behavior"). The type field gives the action, in increasing severity:
type |
Effect |
|---|---|
compliance_suspend |
Blocks delivery; queues messages and bounces them at delivery time |
compliance_deactivate |
Blocks delivery; rejects queues; deletes queued messages; bans the user after 48 hours |
compliance_ban |
Blocks delivery; rejects and deletes queues; removes console access; cancels billing; removes IP addresses |
reactivate |
Returns the account to active status |
For how an ESP operator detects and contains these problems and applies the enforcement ladder, see Compromised Accounts, Outbound Monitoring and Multi-Tenant Architecture.
Event payload fields
The webhook JSON has a common set of fields plus fields specific to each event. These are the fields you correlate to answer "what happened to this message?"
| Field | Type | Events | Meaning |
|---|---|---|---|
email |
string | all | Recipient address |
timestamp |
int (UNIX) | all | When the event occurred |
event |
string | all | Event type identifier |
sg_event_id |
string | all | Unique event ID (URL-safe, ≤100 characters), the key for removing duplicates |
sg_message_id |
string | all | Unique message ID, the key that joins all events for one message |
smtp-id |
string | delivery events, plus bounce, spam and group events | Message-ID assigned by the originating system |
category |
string or array | delivery and engagement | Custom tags the sender sets to organize mail |
asm_group_id |
int | most | Unsubscribe (suppression) group ID |
marketing_campaign_id and _name |
int and string | delivery and engagement | Campaign identifiers |
pool |
object {name, id} |
processed | IP pool the message was sent from |
ip |
string | delivered, open, click, group unsubscribe and resubscribe | Sending IP address (delivered) or recipient IP address (engagement) |
response |
string | delivered, deferred | Full text of the receiving server's response |
reason |
string | bounce, deferred, dropped | Readable reason for the error or drop |
status |
string X.Y.Z |
bounce, dropped | Enhanced status code (see Enhanced Status Codes) |
attempt |
int | deferred | Number of delivery attempts so far |
type |
string | bounce, account | bounce or blocked, or the account status action |
bounce_classification |
string | bounce | Category of cause (table above) |
tls |
bool | bounce, delivered | Whether the connection used TLS |
url |
string | click, group unsubscribe and resubscribe | The URL involved |
url_offset |
int | click | Zero-based position of the link in the HTML (repeated URLs get different positions) |
useragent |
string | open, click, group unsubscribe and resubscribe | Client program that generated the event |
sg_machine_open |
bool | open | True if Apple MPP generated the open |
unique_args |
object | delivery and engagement | Custom parameters supplied by the sender |
SendGrid warns never to put personal data in
categoryorunique_args. The platform may use these fields for internal operations, they cannot be redacted, and they may be kept for a long time.
A typical diagnostic query joins all events that share an sg_message_id and sorts them by timestamp to rebuild the full history of one message: processed, then deferred one or more times, then delivered, then opened. Another aggregates by event, bounce_classification and receiving domain to find which provider is rejecting which category of mail.
Deliverability-insights reporting
A diagnostic dashboard built from the event stream follows the "Deliverability Insights" pattern (in SendGrid, under Stats, then Deliverability Insights). Its data is roughly 48 hours behind real time. It has four views:
| View | Shows |
|---|---|
| Overview | Processed ("how much mail you tried to send"), Delivered (% accepted by mailbox providers), Bounce & Blocked (% not delivered) and Unique Opens (% of delivered messages that were opened), as trends over time |
| Mailbox Providers | The same metrics for each provider (Gmail, Yahoo, Microsoft, AOL, …): delivered rate, open rate, and the split between bounces and blocks |
| Bounces & Blocks | The two failure types separately: a Bounce is an invalid address; a Block is a rejection for reasons of content, reputation or a technical problem |
| Spam & Unsubscribes | Complaints and opt-outs, by provider |
The most important design choice is segmenting by mailbox provider. A combined delivered rate of 95% can hide a complete block at one provider. Reputation is held separately at each provider, so diagnosis and remediation must be done provider by provider too (see Reputation Monitoring and Per-Provider Tuning Baselines). SendGrid publishes these thresholds for reading this view:
| Signal | Threshold |
|---|---|
| Block rate | Target ≤ 3% at each main mailbox provider |
| Spam report rate | ≥ 0.1% at any single provider is excessive |
| Bounce rate | consistently over 5% is concerning |
| Sunset trigger | No opens or clicks for 3 months: stop mailing that address |
These are consistent with the thresholds gathered from several sources in Metrics and Benchmarks: the consensus of ≤0.1% complaints and <5% bounces, and the 0.3% line that Gmail and Yahoo treat as a violation.
Delay and latency diagnosis
"Delay" can mean two very different things, and confusing them sends the diagnosis in the wrong direction.
1. Delay at the receiver (deferrals and throttling). The message has left the platform, but the receiver is holding it back through greylisting, rate limiting or "try again later". This shows up as deferred events with a rising attempt count and a 4.x.x response. The platform retries on a schedule. SendGrid retries deferred messages for up to 72 hours, then turns the message into a bounce.
Persistent deferrals concentrated at one provider mean you are going beyond what that provider accepts in rate or volume. The remedy is to shape traffic for that receiver (reduce concurrency or rate, spread the send over more hours), not to retry more. See MTA Delivery Tuning and Greylisting (RFC 6647).
2. Delay on the platform or at injection (stuck in Processing). The message never reaches a receiver; it stays in the processed state. SendGrid documents several causes:
- A volume limit on a new dedicated IP address. A volume cap applies for the first 3 days on a new dedicated IP address, to prevent abuse. Increase volume gradually with the IP warm-up process.
- A compliance hold. For an account under review, or one where unusual activity was detected, sending is paused until the Compliance team confirms.
- Backpressure in the MTA queue. Very high sending volume can back messages up in the outbound MTA queue. Pause sending or bring another IP address online.
- Suspension of a dormant account. Accounts with no logins are suspended automatically.
Messages stay pending for up to 72 hours. If the underlying problem is not resolved by then, they become hard bounces.
3. Transport latency (integration and network). The message is slow getting into the platform. SendGrid's guidance focuses on throughput and the network path:
- Use the official client libraries (C#, PHP, Ruby, Node.js, Python, Go, Java) rather than code written from scratch.
- SMTP throughput: up to 5000 messages per connection, and up to 1000
To:recipients per message (through thex-smtpapiheader). - Open more concurrent connections, up to a recommended maximum of ~10 concurrent connections.
- Network diagnostics:
hpingandTest-NetConnectionmeasure response time and TTL, and anything above ~150 ms of response time is a first warning sign. Traceroute mode shows the latency at each hop; watch for sudden jumps between hops. Header analyzers (such as Google's) show the message's path through each MTA and how long it waited at each hop. Wireshark captures the SMTP conversation for close inspection.
Diagnose in this order. Check the event state first. processed points to a platform or compliance issue; deferred points to throttling by the receiver; delivered but no engagement points to the spam folder, which is a placement problem, not a delay. Use transport latency tools only once you have confirmed the message is leaving the platform normally.
Engagement-quality scoring
The highest level of aggregation turns the whole event stream into a single health score. SendGrid's Engagement Quality (SEQ) API is the reference example. It returns a score from 1 to 5, where higher means better engagement and deliverability. The score lets an operator rank senders and subusers at scale and spot a decline before it becomes a reputation incident.
A score is generated only with open tracking enabled and ≥ 1,000 messages sent in the previous 30 days. Scores are kept for a maximum of 90 days. The endpoints return scores for the account and for each subuser.
The score combines five weighted components, which are the event signals described above, condensed:
| Component | What it measures |
|---|---|
| Engagement Recency | The % of unique addresses mailed in the past 30 days that also engaged (opened or clicked) in the past 90 days |
| Unique Open Rate | The lowest rate over the last 7 and 30 days at the top 5 mailbox providers, excluding Apple machine opens and messages not delivered |
| Bounce Rate | The permanent bounce % over the last 7 and 30 days, using the higher (worse) of the two |
| Bounce Classification | Gives weight to bounces classified as Reputation or Content, the categories where the receiver is judging you |
| Spam Rate | Recent spam complaints over a 7-day window |
The design shows what a platform actually treats as quality: recent engagement (are you mailing people who still want the mail?), real rather than machine opens at the providers that matter, permanent bounces moving in the wrong direction, reputation and content bounces in particular, and complaints. An ESP can use these scores to group subusers into IP pools, flag underperforming senders for outbound monitoring, and decide when to move senders between shared and dedicated infrastructure.
Related articles
- Delivery Troubleshooting Playbooks
- Metrics and Benchmarks
- Enhanced Status Codes (RFC 3463), for reading the
statusfield - Delivery Status Notifications (RFC 3464), the format of asynchronous bounces
- Tracking and Measurement Distortion, on why opens and clicks mislead
- MTA Delivery Tuning
- Complaint Feedback Loops (RFC 6449)
- Reputation Monitoring
Check your own record
The free check reads what your domain publishes in DNS.
In this topic
- Deliverability Metrics and Benchmarks
- List Hygiene and Sunset Policies
- Sending Infrastructure Practices
- MTA Delivery Tuning