Pangram verdict · v3.3
We believe that this document is fully human-written
AI likelihood · overall
HumanArticle text · 1,666 words · 5 segments analyzed
Mono Font
2026-06-06T22:54:55-04:00TL;DR: Don't overthink it, just send a verification email.
Bear with me, because some of these “lies” are going to feel obvious, or like unimportant trivia. In all honesty, that’s not that far from the truth. However, I hope you’ll let me try to build a detailed and fun illustration showing how something as mundane as email can break our expectations in surprising ways. We’ll cover a lot of edge cases, stumble over some small blocks, and even discover a few technically-correct things that are valid, but not commonly supported even in big systems like Gmail (probably for good reason, to be fair). Each example isn’t necessarily meant to be a meaningful use-case that you need to go make sure you’re handling correctly. But, all together, they’re meant to gradually build toward one main point: Email addresses are mired in old history, and the definitions of valid and invalid components of the system continue to subtly change over time. It’s easy to make a common-sense decision that is unexpectedly problematic. On top of that, older devs (and older systems) may have expectations that were correct in the past but don’t work anymore. And without further ado, on to the lies… “Email addresses can just be validated with a regex” Let’s get the low-hanging-fruit out of the way. I’m far from the first person to say this online and I certainly won’t be the last. But I feel it’s justified repetition because, even after a thousand blog posts posted, tweets twote, and reddit comments moderated, this antipattern stubbornly persists in 2026. The regex approach has three main avenues for causing heartache for you, your business, and your customers:
It is relatively expensive to run, for very little-to-no real benefit
To be fair, this point used to hit harder, before we started throwing simple queries at giant clusters of power-hogging GPUs.
Regex is hard, regex wizardry is rare, and regex engine implementations are inconsistent. It’s very, very easy to accidentally get it wrong without realizing it.
We’ll go over a couple of the ways it could go wrong through the rest of this post.
Even if you copypaste one of the “good” regexes, the world is evolving. What’s valid today may be legacy tomorrow,
The internet is littered with advice that was good 20 years ago. It’s also littered with regular expressions that were good 20 years ago, because legacy is forever.
Opinion alert: Input validation is more about helping the user by making it harder to make simple mistakes. It should be restrictive enough to make your user’s life easier, but only just. Don’t rely on input validation to protect you from your users; use it to protect your users from themselves. In that sense, there’s a valid argument for using regex tests to improve UX, which is worth considering. UX is important and I won’t dismiss that fact. However, to play devil’s advocate for a moment, perhaps the risk outweighs the reward. In the year of our lord 2026, you can reasonably expect your users to know how to type their own email address - or even better, auto-input from their OS, browser, keyboard app, or password manager. It’s likely that more people out there are being filtered by badly-implemented form validation than there are being filtered by their own need of hand-holding. On that note, then…
Don’t validate email addresses. If you simply must, use a simple client regex to help users avoid common mistakes and typos.
Try to keep it as non-restrictive as possible. Something like ^[^@]+@[^@\s]+$, which only makes sure your user has input “something@something”
If you have validation on the API or form handler, use THE SAME regex, for consistency with the frontend.
This comes back to that “don’t use input validation to protect you from your users” point. By default, protect yourself by sanitizing inputs, not by rejecting them.
Verify the address, don’t worry about validating it.
Send an email, let your user click a verification link or input a verification code.
That’s it. It doesn’t need to be more complicated than that.
You don’t need to check the domain’s MX record; your email service does this as part of the whole “sending the email” thing (Also, spoiler alert, but there’s some more MX Record fun below). And you definitely don’t need to do a big regex. In fact you’re probably already sending a verification email anyway! If you are, this might be an excuse to delete code, which is every programmer’s actual favorite thing! Now with the easy part out of the way, let’s go over some of the specific points that make email handling fun and confusing! “An email address needs to be valid, and email providers support any valid addresses” This may shock you, but the Internet is made of software. And if there’s any universal through-line on software, it’s the fact that it very frequently diverges from your expectations. Email server software, from big providers like Gmail to open-source projects like Postfix, have varying levels of support for the official rules of email formats. Postfix only added support for SMTPUTF8 around 2015 but it wasn’t enabled by default until years layer. Dovecot, on the other hand, still doesn’t support it in 2026. This isn’t limited to open-source; Gmail puts restrictions on allowed characters when creating an address, but it does appear to support sending with UTF8. We’ll dive into SMTPUTF8 and RFC 6531 a bit more in a later section. But let’s look at another example, where we can go explicitly against the restrictions of every relevant RFC. Let’s look at RFC 5321 Section 4.5.3, which defines length limits. 4.5.3.1.1. Local-part
The maximum total length of a user name or other local-part is 64 octets. That’s a pretty simple restriction, and thankfully easy to understand! But there are some terms that might be unfamiliar for some readers:
“local-part.”
Simply put, the local-part is everything that comes before the @ character.
(Let’s keep it that simple for this example, but we’ll come back to the local-part for some other parts of the article)
octet
An octet is a standard 8-bit byte (Wikipedia)
So now, the email address entirelytoomanycharactersinthisemailwhatisevenhappeningblahblahdonttrythisathome@gitpush–force.com, which has an 80-byte local-part, is 100% unambiguously invalid. So naturally it doesn’t work.
Yeah, remember that thing about software diverging from expectations? You can actually send email to me at that address. Your provider will (probably) allow it without complaining, my provider will happily deliver it to my inbox. “An email address can only have ASCII characters” This belief will probably be more commonly held in the English-speaking world, but I’m curious: If you’re not in the Anglosphere, do you still expect emails to require ASCII latin characters? Back in 2012, which is simultaneously recent and ancient in the world of tech, Email Internationalization became a thing through a set of RFCs corresponding to different parts of the email stack. For email addresses specifically, RFC 6531 defines the SMTPUTF8 extension, which allows for non-ASCII characters in the local-part of an email address. In that sense, it’s actually pretty surprising that so much of the world’s population wasn’t able to put their own name, in its native written form, in an email address until just 14 years ago. International characters were technically working and allowed even before 2012, under things like Punycode through RFC 3490, something of an encoding hack where unicode characters were encoded in ASCII under-the-hood. But at that time, it only applied to the domain name, and the local-part was still limited to ASCII. “An email address needs to be human-readable” Now that we’ve covered the whole Latin character thing, let’s go a bit deeper down the rabbit hole. With internationalization, the local part is defined as an octet stream. You can technically put bytes that don’t map to a valid character in standard unicode. I could put in an email address, and it would be valid. But it’s not human-readable in any language.
“Email addresses always have a second-level domain (SLD) and a top-level domain (TLD)” Think of the familiar email addresses you work with every day. An @icloud.com island in a sea of @gmail.com, with a smattering of ISP, @employer.com, and @school.edu emails. All follow this familiar pattern: something-dot-something. There are three types of valid addresses which don’t follow this pattern, in descending order of importance.
Addresses which have subdomains, therefore multiple dots in the domain.
Hopefully, at least this one isn’t that surprising. If you’re outside the US or Canada, you’re probably used to seeing things like .co.uk, .co.au, etc. But many smart people have accidentally excluded these users with well-intentioned regexes.
Addresses without a dot
In the real world, this is only important for things like intranet addresses, where each machine on your network has a hostname. It’s important for email software to support, but not likely to be a consideration for most of us. Technically someone at ICANN or Verisign or whoever could register an address like admin@net, but let’s be real.
Addresses which use an IP Address instead of a domain name. RFC 5321 Section 4.1.3 explicitly lays out support for this, which it calls “Address Literals.”
This is very uncommon, but it is valid in the real world. Related, you can also reach me at ben@[50.169.39.178] if your email client supports it.
Sadly, Gmail’s web client seems to have issues with this. But I think if you use a client like Thunderbird, it’ll still work through Gmail. Gmail’s web client sends the email, but in my testing it seems to strip away the [] square brace characters specified in the “Address Literals” section of the RFC, and needed to send to an unnamed host.
“Email addresses always have a ’normal’ TLD” My actual personal email address is not on a .com or .net domain, it’s a .email domain. This is something that I like quite a lot, because I’m a dork who loves things that are silly and weird just for the sake of being silly and weird.