TL;DR
- Deliverable: safe to send. Undeliverable: remove it.
- Risky: probably exists, with a known risk. The reason says which: catch-all, role or disposable.
- Unknown: the server gave no clear answer. Don't send yet; the credit is refunded.
All states and reasons
Other tools use different words for the same ideas: "valid" for deliverable, "invalid" for undeliverable, "accept-all" for catch-all. The meaning is the same.
| State | Reason | What it means | What to do |
|---|---|---|---|
| deliverable | accepted_email |
The server accepted the mailbox and refused our random test address, so its "yes" is meaningful. | Send. |
| risky | low_deliverability |
Catch-all (accept-all) domain: the server also accepted a random address, so the mailbox can't be confirmed. More. | Separate campaign, low volume, established domains. |
| risky | low_quality |
Role address such as info@ or sales@. The mailbox exists, but it's a shared inbox. More. | Keep only where no named contact exists. |
| risky | disposable |
A throwaway email provider. The address may work today and vanish tomorrow. | Don't send cold email. Block at signup. |
| undeliverable | rejected_email |
The server refused the mailbox with a permanent error, typically 550 5.1.1 "user unknown". | Remove. |
| undeliverable | invalid_domain |
The domain doesn't exist, publishes no MX record, or publishes a "null MX" saying it takes no mail. | Remove. |
| undeliverable | invalid_email |
The address isn't valid syntax: missing @, illegal characters, a local part over 64 characters, and so on. | Remove, or fix the typo. |
| unknown | unavailable_smtp |
The server kept answering "try later" (4xx) even after a retry, or reported the mailbox as over its storage limit. | Re-check later. |
| unknown | blocked_by_server |
The server refused our check (a 5.7.x policy or blocklist reply), which says nothing about the mailbox. | Re-check later, or treat as risky. |
| unknown | no_connect |
We couldn't hold a conversation with any of the domain's mail servers (timeout or connection error). | Re-check later. |
| unknown | dns_error |
The domain's DNS didn't answer, so we couldn't find its mail servers. | Re-check later. |
How a result is decided
The checks run in order and the first decisive one wins (how it works):
- Syntax. A malformed address stops here:
invalid_email. - Domain. No domain, no MX or a null MX:
invalid_domain. - Disposable list. A disposable domain is marked risky without contacting its server.
- Mailbox check. We connect to the domain's mail server and ask about the address, then stop before sending
anything. A permanent (5xx) refusal of the mailbox, such as "no such user", is
rejected_email. A 4xx deferral is retried after a pause of a few minutes, to get past greylisting. No clear answer after that isunknown. - Catch-all test. If the address was accepted, we also ask about a random address at the same domain. If that's
accepted too, the result is
low_deliverability. - Role check. An accepted address on a normal domain with a role prefix is
low_quality. Everything else accepted isdeliverable.
Two consequences worth knowing. A role address the server rejects is undeliverable, not risky. And a role address on a catch-all domain is reported as catch-all, because that's the bigger risk.
Why blocks are "unknown", not "undeliverable"
Some servers reject verification traffic with a 5xx reply that's about the connecting server, for example
550 5.7.1 ... Client host blocked using Spamhaus. Counting that as a dead mailbox would throw away good contacts, so we
report blocked_by_server instead. The exception: if a 5.7.x reply clearly says the recipient doesn't exist
("Recipient address rejected: user does not exist"), it's still rejected_email. Codes are explained in
email bounce codes.
Which ones to send to
- Main campaign: deliverable only.
- Secondary, slower campaign: risky catch-alls and hand-picked role addresses, from established inboxes (catch-all playbook).
- Never: undeliverable and disposable.
- Later: unknowns, after re-checking.