Step one: find the server that handles the domain
Before any SMTP happens, the verifier queries DNS for the domain's MX records. Each record has a preference number and a hostname, and lower numbers are tried first. Under RFC 5321, a domain with no MX record falls back to its A or AAAA record, which is why a missing MX is not strictly proof that a domain cannot receive mail, although most mail that relies on the fallback is misconfigured.
One special case is worth handling explicitly. RFC 7505 defines a null MX, a single record with the hostname ".", which means the domain has declared that it accepts no mail at all. There is nothing to connect to, so the address can be marked undeliverable without opening a socket.
$ dig +short MX gmail.com
5 gmail-smtp-in.l.google.com.
10 alt1.gmail-smtp-in.l.google.com.
20 alt2.gmail-smtp-in.l.google.com.Step two: the conversation, and where it stops
The verifier connects to the preferred host on port 25 and walks through the start of a normal delivery. EHLO introduces the client. MAIL FROM names an envelope sender. RCPT TO names the address being tested, and the reply to that command is the whole point of the exercise.
The session then ends with QUIT. A message is only sent after the DATA command, and DATA never happens, so nothing reaches the mailbox and the recipient sees nothing.
S: 220 mx.example.com ESMTP ready
C: EHLO verifier.example.net
S: 250-mx.example.com
S: 250 STARTTLS
C: MAIL FROM:<probe@verifier.example.net>
S: 250 2.1.0 Ok
C: RCPT TO:<jane@example.com>
S: 250 2.1.5 Ok <-- the answer
C: QUIT
S: 221 2.0.0 ByeThe older VRFY command was designed for exactly this question, but almost every server disables it because it makes harvesting addresses trivial. RCPT TO is what is left.
Reading the reply codes
SMTP replies have a three-digit code. The first digit is the category: 2 is success, 4 is a temporary failure and 5 is a permanent one. Many servers add an enhanced status code from RFC 3463 after it, which is more specific. The text after the codes is free-form and differs between providers, so it helps with diagnosis but should not drive logic on its own.
- 250: the server will accept mail for this recipient. It does not prove a human reads the mailbox, or that the message will not bounce later.
- 550 with 5.1.1: the mailbox does not exist. This is the clearest negative answer the protocol offers.
- 552 or 452: over quota or too many recipients. The mailbox may be real, but it cannot take mail right now.
- 451 or 450: try again later, often greylisting or a temporary server problem. This says nothing about the address yet.
- 550 with a policy message: the server rejected you, not the address, often because of the IP's reputation. Treating this as an invalid mailbox is the most common source of false negatives.
Where a yes does not mean yes
Catch-all domains accept every RCPT TO and sort things out afterwards, so a 250 carries no information. The standard test is to probe a random address that cannot exist at the same domain. If that is accepted too, the domain is catch-all and the original answer is meaningless. The honest result is risky, not deliverable.
Some providers also accept at RCPT time and bounce later, which is known as deferred rejection. Large consumer providers can behave differently depending on the sender's reputation, and security gateways may return uniform answers so that outsiders cannot map a company's staff. No verifier sees past these from the outside, which is why every honest tool has an unknown or risky category.
Where a no does not mean no
Greylisting temporarily rejects the first attempt from an unfamiliar sender, on the theory that real mail servers retry and spam tools do not. A verifier that gives up on the first 451 reports unknown for a perfectly good mailbox. Handling it properly means retrying after a delay, usually a few minutes, from the same IP, which is hard to do inside a synchronous API call.
Rate limiting and blocking look similar. Many connections from one IP will draw 421 replies, or a 550 that really means the IP is on a blocklist. If that gets read as a mailbox failure, a batch can suddenly report a whole domain as invalid. Telling these apart depends on the enhanced code and message text, on retry behaviour, and on spreading connections sensibly across sending IPs.
Why you cannot just script this yourself
The protocol is simple enough to try in a few lines, and it is worth trying once to see it work. Running it in production is the hard part. Most cloud providers block outbound port 25 by default, and residential networks usually do too. Even with the port open, a new IP with no reverse DNS and no sending history gets rejected or tarpitted by the servers you most care about.
Your probing IP also matters beyond verification. If it shares a reputation with your real mail, enough rejected probes can hurt your actual deliverability. Keep the two separate, whatever you decide to build.
- Set a valid EHLO hostname with matching forward and reverse DNS. Many servers reject mismatches outright.
- Use a real envelope sender on a domain you control, or a null sender where the server allows it.
- Set connect and per-command timeouts. Servers can tarpit you by answering very slowly, on purpose.
- Limit concurrent connections per MX host, not just per domain, because thousands of domains share a handful of providers.
- Cache results. Probing the same address repeatedly looks like harvesting, and the answer rarely changes within days.
Turning replies into a decision
The useful output is not the reply code but what you should do about it. That is why VeriDock returns four statuses rather than a boolean: deliverable, undeliverable, risky and unknown, with a reason code for rules that need more detail. A catch-all is risky rather than good, a greylisted address is unknown rather than bad, and you are not billed for unknown results.
Whichever tool you use, make sure unknown is treated differently from undeliverable in your code. Deleting every address that could not be confirmed quietly throws away real customers.
Key takeaways
0/5Try it on a real address
Run syntax, DNS, MX, disposable, and role checks on any address. No signup needed.
Enter an address and press Check.
Runs real syntax, DNS and mail-server checks.
This demo checks syntax, domain, mail server, disposable and role-address rules. Sign up free for live mailbox checks.
Frequently asked questions
Verify addresses with one API call.
250 free checks every month, recurring. Unknown results are never billed.