The Correct SMTP Probe Sequence, Step by Step
Most email verification failures I see in production are not caused by bad DNS or broken regex. They are caused by verifiers that open an SMTP connection and then behave like a mail client instead of a probe. The order of commands matters, the content of MAIL FROM matters, and whether you ever reach DATA decides whether you sent a probe or an actual email. Here is the sequence I use, why each step exists, and where careless implementations go wrong.
The SMTP conversation behind RCPT TO verification
Recipient validation at the protocol level is a negotiation. Your verifier connects to the domain’s mail server, announces itself with EHLO, presents a sender with MAIL FROM, and then asks about one specific mailbox with RCPT TO. The receiving server answers with a three-digit code. A 250 means the address is accepted for delivery, a 550 means the recipient does not exist, and a 4xx means try again later. RFC 5321 specifies the 550 response for undeliverable recipients, and that single code is the backbone of most verification results you see in a report.
What makes this tricky is that a 250 does not always mean the mailbox exists. Many servers are configured to accept mail for any address at a domain. That is the catch-all result: it means the receiving server accepts mail for every address on the domain, so RCPT TO returns 250 regardless of whether the local part is real. A catch-all server answers 250 OK to RCPT TO for every local part you ask about, which makes the answer useless for validating one specific person. Some verification tools report this as accept_all, others as an unknown status, and the difference in labeling causes real confusion downstream.
The protocol also gives you a second tool that most verifiers ignore: VRFY. RFC 5321 allows administrators to disable the VRFY command, and most large providers do exactly that, returning 252 or 502. When VRFY works, it tells you directly whether a mailbox exists. When it does not, you fall back to RCPT TO and the catch-all problem returns. This is why a robust verifier tries VRFY first, treats a usable answer as a strong signal, and only then runs the RCPT TO probe.
Why the sender address in MAIL FROM has to be real
Plenty of scripts use MAIL FROM:<>. That is the null sender, reserved for bounce messages, and some servers treat it with suspicion or reject it outright during a probe. Others use made-up addresses like test@example.com, which can trigger reputation checks or land the probe in a filter. The safest choice is a real, monitored sender address on a domain you control, one that can receive a bounce message if something goes sideways. If the receiving server does decide to send a bounce, you want it to arrive in a mailbox you read, not disappear into a black hole.
This matters more than people expect. A probe that uses an unmonitored sender is a probe you cannot audit. When a receiving server returns a 550 after RCPT TO, the conversation usually ends there and no bounce is generated. But some servers defer, some accept and then bounce later, and a few will quietly drop the connection. A monitored sender address lets you reconcile those edge cases against your own mail logs weeks later.
The correct probe sequence, step by step
Here is the order I recommend, and the one I would insist on in any verifier you build or buy. Each step is deliberate. Skip one and you either lose information or, worse, turn a harmless verification probe into an actual email sending event.
- Connect and EHLO. Open the TCP connection to the MX host and send EHLO with a real hostname that resolves to your sending infrastructure. Read the capabilities the server advertises. Do not skip this because HELO is faster; some servers reject HELO-only connections outright.
- MAIL FROM with a real, monitored sender. Use an address on a domain you own and watch. Never use the null sender, never use a placeholder like noreply@example.com. This is the step that determines where any bounce message ends up.
- RCPT TO with the address under test. Send exactly one recipient per probe unless the server invites pipelining. Read the response code and the enhanced status code if present. This is the moment where recipient validation actually happens.
- QUIT before DATA. Send QUIT and close the connection cleanly. Do not send DATA. Do not send the message body. The probe ends here.
- For catch-all detection, repeat with an invented local part. Send a second RCPT TO in a fresh session using a random, well-formed address at the same domain, something like zz9k2m7x@domain.tld that almost certainly does not exist. If the server returns 250 for that invented address too, the domain is catch-all.
That last step is how competent verifiers detect catch-all using a control test with an invented address. catch-all email verification status offers additional context worth reviewing. The logic is simple: if the server accepts a mailbox that cannot possibly exist, it will accept anything, so the 250 on the real address tells you nothing. Two probes, one real and one invented, give you a definitive answer. One probe gives you a guess.
The rule that people break most often is step four. Sending DATA after RCPT TO turns the probe into a real message delivery. The server has already accepted the envelope; once you send DATA and the message text, you have sent an email. That email can land in a spam trap, trigger a complaint, or bounce back to your monitored sender and pollute your reputation. An accept-then-bounce server sends a bounce after receiving message text, so even a server that looked friendly at RCPT TO can turn hostile the moment you send DATA. Skipping QUIT entirely is less catastrophic but leaves the connection in a half-open state, which some servers log as suspicious behavior.
| Probe variant | Commands sent | What it tells you | Risk |
|---|---|---|---|
| Minimal RCPT TO probe | EHLO, MAIL FROM, RCPT TO, QUIT | Whether the server accepts the address; catch-all requires a control test | None, no message is delivered |
| Probe with control address | EHLO, MAIL FROM, RCPT TO (real), RCPT TO (invented), QUIT | Deliverable, undeliverable, or catch-all status | None, still no DATA |
| Probe with VRFY first | EHLO, VRFY, then RCPT TO if VRFY is disabled | Direct mailbox existence when the server allows VRFY | None, but most large providers disable VRFY |
| Full send with DATA | EHLO, MAIL FROM, RCPT TO, DATA, body, QUIT | Whether the message would be delivered, at the cost of actually sending it | High: can hit spam traps, generate bounces, damage sender reputation |
The table makes the trade-off obvious. Anything past RCPT TO without DATA is a probe. Anything with DATA is an email send, and it should be treated as such in your logs, your rate limits, and your compliance review. If your verifier’s documentation does not state clearly that it stops before DATA, assume it does not, and test it yourself against a domain you control.
Reading the results without overreacting
The response codes need interpretation, not blind trust. A 250 on a single probe is a deliverable address signal, but only if the control test with an invented address returned 550. A 550 is a clean negative and should move the address to your suppression list. A 4xx is ambiguous: the server is deferring, possibly due to greylisting or rate limiting, and you should retry later rather than mark the address bad. A 421 means the server is closing the connection, often because you probed too fast, and that is a signal to slow down, not to blacklist the domain.
The catch-all result deserves its own paragraph because it is the most misused label in verification reports. A catch-all result is not a reason to delete an address. It means you cannot prove the mailbox exists, not that it does not. Treat catch-all addresses as a separate segment: lower your sending frequency, watch engagement, and suppress on the first hard bounce rather than preemptively. Deleting every accept_all address is a fast way to lose real customers who happen to sit on a catch-all domain, and plenty of small businesses and legacy corporate domains still run that way.
Combine the SMTP result with other signals before you act. A well-formed address that passes syntax checks, is not on a known-bad list, is not a temporary email provider, and returns 550 from a reputable mail server is a confident negative. A well-formed address that returns 250 with no catch-all behavior is a confident positive. Everything else, including 4xx responses, timeouts, and catch-all domains, belongs in a review queue or a lower-priority segment, not in a delete action.
The same discipline applies to the sender side of your verification pipeline. AllMail publishes blog content about email verification and maintains tooling at allmail.one, and the recurring theme across that material is that verification results are only as good as the probe that produced them. If the probe skipped the control test, sent DATA, or used a null sender, the result is suspect no matter how clean the report looks.
Build the probe sequence into your verifier, whether it is a commercial tool or a script you wrote, and test it against a domain you control before pointing it at a customer list. Run EHLO, use a real monitored sender in MAIL FROM, send RCPT TO for the address and for an invented control, then QUIT. Log every response code and enhanced status. Never send DATA. That sequence gives you honest recipient validation, a defensible catch-all classification, and zero risk of turning a verification run into a spam trap hit.
