How to validate an email address

By Nikita Chernyi

Originally published on 2022-11-12 at /posts/how-to-validate-email-address/; republished here on 2026-09-23 with links updated.

Hey, Email validation is hard. Do you know how to validate an email address for sure? Neither do I, but here is a report on what I found while working on postmoogle (opens in new tab).

So, what’s your wild guess? Regular expressions? Well:

So, how you can really do that?

First of all - don’t use regexp. You either have to be a god or… Nah, that’s the only option to create a regular expression that will match all possible variations of a valid email address. So - use a library that does all those validations (e.g. in Go there is mail.ParseAddress (opens in new tab) in stdlib that makes your life simpler).

But that will validate the format only, and it won’t check if the address itself is valid. For example, here is an email address with a 100% valid format, but it’s still invalid: spammers@gtfo.out

Why is it invalid? Well, because there is no such address. It’s forged. I sense a “(x) doubt” feelings from you! You may ask “Okay, but why would I worry about that? Email address’ format is valid? Valid. I don’t care.”

You have to.

Email is the most spammed thing nowadays, so all email providers have some kind of spam protection, both for incoming and outgoing mail. If you don’t care, your email provider will ban/suspend your account for a high bounce rate.

That’s a serious problem. For example, from my experience, AWS SES will just freeze your email operations completely, until you contact support and prove that you fixed the reason of the high bounce rate on your side.

So, the question is:

How to be sure that an email address is actually valid?

So… You want to hear a story, eh? One about treasure hunters? Haha, have I got a story for you! Pandora… accidental borderlands (opens in new tab) reference.

A story about rocket science, again. What did you expect, 3 lines of code to validate an email? Hahaha, you’re a funny one.

Jokes aside, let’s try to do that with a justexample@iana.org email (yes, a simple email address, not even a not-simple-but-still-valid undisclosed-recipients:; email address, just for the sake of simplicity):

  1. Try to get the server address from an email address, usually, it’s a domain name after the @ symbol. In our case: iana.org.
  2. Try to get MX records of that server address (e.g. by using tools like dig or your programming language’s MX lookup). You’re lucky! There are some MX records: pechora1.icann.org, pechora2.icann.org, pechora3.icann.org, pechora4.icann.org, pechora5.icann.org.
  3. if you are not lucky and there are no MX records - just use the server address itself (actually, according to RFC5321 (opens in new tab), you have to go through multiple record types in a specific order, but your programming language stdlib is usually smart enough to do that automatically).
  4. Now, try to connect the discovered servers, one per step, in a for loop. If you successfully connect to the <serveraddress>:25 - you’re lucky again! But if not - try the same address with port 587 (yes it’s not RFC-compatible, but I saw several mail servers configured to accept submissions from other MTAs on that port. Don’t ask me why - that post is a kind of study report, not a ready-to-use instruction with all edge cases covered). If it doesn’t work - run the next cycle.
  5. Finally, you found a working SMTP server that supposedly can give you a clue about the validity of the specific email address.
  6. After you found a working SMTP server and connected to it, you have to start an SMTP session (HELO/EHLO), send MAIL and RCPT TO commands

The Final Part is the answer of the SMTP server to the RCPT TO command:

Why I used server address instead of domain name? Because user@111.111.111.111 is a valid email, too. Now, live with it.

You may ask “How should I decide if the email address is valid or not if I was greylisted?” Have no idea. I just mark such emails as invalid, because even if that email exists and you actually can send it email, there is no clarity whether will it greylist you again when you’ll try to send an email or not, and (more important, IMO) how will your email service define greylisting? Even Postmark (opens in new tab) considers such cases as bounce, so why should I care? If the user’s email provider preemptively greylists even simple validity checks - that’s the user’s problem, not mine. ¯\_(ツ)_/¯

What did you expect? A solution? Oh, my sweet summer child (opens in new tab), there is none.

Hope that helps :D

PS: How is that relate to postmoogle (opens in new tab)? It uses the same steps described above to validate incoming (and send outgoing) emails.

llms.txt