TL;DR
- Find the domain's mail server (MX record), connect on port 25, and walk the SMTP conversation as far as
RCPT TO. ThenQUIT. No email is sent. 250means accepted;550 5.1.1means no such mailbox. Also test a random address, because a catch-all server says 250 to everything.- From a home or cloud connection it often fails: port 25 blocked, IP on a blocklist, greylisting. That's what verification services handle for you.
Step 1: find the mail server
Look up the domain's MX (mail exchanger) records. Lower preference numbers are tried first.
$ dig +short MX acme.com
10 mx1.acme-mail.net.
20 mx2.acme-mail.net.
# Windows, or without dig:
> nslookup -type=mx acme.com
No MX record at all, or the domain doesn't exist? The address can't receive mail, so you're done: it's invalid. (RFC 5321 allows falling back to
the domain's own A record, but many verifiers, including us, treat an MX-less domain as unable to receive mail.) A single MX of
0 . is a "null MX": the domain says outright that it takes no email.
Step 2: talk to it
Connect on port 25 and type the commands yourself. Your lines are the ones without a number in front:
$ telnet mx1.acme-mail.net 25
220 mx1.acme-mail.net ESMTP ready
EHLO mail.yourdomain.com
250-mx1.acme-mail.net Hello
250-STARTTLS
250 OK
MAIL FROM:<>
250 OK
RCPT TO:<[email protected]>
250 OK ← mailbox accepted
RCPT TO:<[email protected]>
550 5.1.1 User unknown ← random address refused: not catch-all
QUIT
221 Bye
A few notes:
MAIL FROM:<>is the null sender, which keeps your own domain out of it. Some servers refuse it; if so, use an address on a domain you control.- Use
EHLOwith a real hostname that resolves. Servers judge you by it. - If the server insists on encryption, use
openssl s_client -starttls smtp -connect mx1.acme-mail.net:25instead of telnet. - Never type
DATA. That's the step where a message is actually sent. Stopping before it is what makes this a check, not an email.
Step 3: read the answer
| Reply to RCPT TO | What it means |
|---|---|
250 for the address, 550 for the random one | The mailbox exists. |
250 for both | Catch-all domain. You can't tell whether the person exists. |
550 5.1.1, "user unknown", "does not exist" | The mailbox doesn't exist. It would hard bounce. |
550 5.7.1, "blocked", "Spamhaus", "client host" | The server is refusing you, not the address. The result tells you nothing about the mailbox. |
421, 450, 451 | Try later. Often greylisting or rate limiting. |
More codes are in email bounce codes.
Why it often fails when you do it yourself
- Port 25 is blocked. Most home broadband providers and many cloud hosts block outbound port 25 to stop spam. The connection just hangs.
- Your IP is on a blocklist. Residential IP ranges are commonly listed by Spamhaus as "should not send mail directly". Microsoft's servers in particular answer such connections with a 5.7.x block before you get to ask anything.
- Greylisting. Some servers refuse the first attempt from an unknown sender with a 4xx and only accept a retry several minutes later.
- Catch-alls. A large share of B2B domains accept every address, so the check can't confirm anyone.
- Rate limits. Check a few dozen addresses at one provider quickly and you'll start getting 421s, or a block.
Other "without sending" methods, and why they're weaker
VRFYcommand. Designed for exactly this, but almost every server disables it or answers252("can't verify, but will accept").- Password-reset or login pages. Some webmail sites reveal whether an account exists. It's slow, unreliable and against most sites' terms.
- Syntax and MX checks alone. Fast, but they pass every dead mailbox on a healthy domain. See verification vs validation.
Why use a service
A verification service runs this same conversation from dedicated servers that can reach port 25, paces its checks per provider, retries greylisted domains after a pause, runs the catch-all test in the same session, and tells a block apart from a dead mailbox. MailExchange does all of that for a whole CSV at once (how it works), returns a clear status and reason for every row, and refunds unknowns.