How to Write a Regex for Email Validation (With Edge Cases)
A regex for email validation that actually works in production — plus-addressing, subdomains, and why a confirmation email is the real check.
Try it now: Regex Tester — Test JavaScript regular expressions against sample text with live match highlighting, named capture groups and a replace preview — all six flags explained.
The Truth Nobody Wants to Hear About Email Regex
Search “regex for email validation” and you'll eventually run into the fully spec-correct RFC 5322 pattern — the one that's often quoted as being roughly 6,300 characters long, full of nested groups for comments, folding whitespace and quoted strings nobody has typed into a signup form since 1987. It exists, it's technically correct, and almost no production codebase uses it, because being spec-correct was never actually the goal.
Here's the part that matters more: even a perfect RFC 5322 regex only tells you a string is shaped like an email address. It cannot tell you whether example.comhas a mail server, whether that mailbox exists, or whether the person typing it owns it. No regex can do that — it's a syntax check, not a proof of deliverability. That single fact reshapes the entire decision: once you accept that a regex can't prove an address is real, the question stops being “how do I make this pattern airtight” and becomes “how good does this pattern need to be before I hand the real verification job to a confirmation email.” Nearly every production system — Gmail's own signup form included — answers that with a simple pattern and an actual email sent to the address.
A Simple Email Regex Pattern That Actually Works
The email regex pattern that shows up in more production codebases than any other is short enough to read in one glance:
^[^\s@]+@[^\s@]+\.[^\s@]+$
Broken into its four pieces, it says exactly this:
^[^\s@]+— one or more characters that are not whitespace and not@, anchored to the start. This is the local part, before the@.@— literally one@sign, and exactly one.[^\s@]+— one or more non-whitespace, non-@characters again: the domain, up to its final dot.\.[^\s@]+$— a literal dot followed by one or more non-whitespace characters, anchored to the end. This forces at least one character after the last dot, souser@example.with nothing trailing it is rejected.
It's a javascript email validation regex in the sense that it's exactly what you'll see pasted into a z.string().regex(...) call or a form's pattern attribute across an enormous number of real apps, and it does the one job a regex should actually be asked to do here: catch obviously malformed input — no @, no domain, a stray space — without pretending to catch everything else. Its known limitation cuts both ways. It will happily accept a few strings that are not, strictly, valid email addresses (like [email protected], which passes the shape check but isn't a real domain), and it will reject a small number of rare but technically valid addresses covered below. Both of those are acceptable trade-offs for a signup form; neither is acceptable if you're building an actual RFC 5322 conformance checker, which is a different, much rarer job.
You can run this pattern — or any of the others on this page — against real addresses immediately in GenKitLab's Regex Tester, with live match highlighting so you can see exactly which part of a string a pattern accepts or rejects before it goes anywhere near a form.
Email Regex Edge Cases People Get Wrong
Most of the “my regex rejects a valid email” bug reports trace back to one of five specific edge cases. Here they are, with a real address for each one.
Plus-addressing
[email protected] is a completely valid, extremely common address. Gmail, Outlook, Fastmail and most other providers treat everything after a +in the local part as an optional tag that's stripped before delivery — people use it constantly to filter signup confirmations or track which site leaked their address. A pattern that only allows letters, digits, dots and underscores in the local part (a mistake copy-pasted from a lot of outdated tutorials) breaks on this and rejects a real user for no reason. The simple pattern above handles it fine, because +isn't whitespace or @.
Subdomains and multiple dots
[email protected] is valid, and so is [email protected]. A domain can have as many dots as it needs — a regex that assumes exactly one dot in the domain (something like @[^.]+\.[^.]+$) will reject legitimate corporate and subdomain addresses. The simple pattern again handles this correctly, since [^\s@]+ for the domain happily matches dots along with everything else.
Case sensitivity
The domain part of an email address is conventionally case-insensitive — [email protected] and [email protected] resolve to the same mail server, because DNS names are case-insensitive. The local part, per RFC 5321/5322, is technically allowed to be case-sensitive — [email protected] and [email protected]could theoretically be different mailboxes. In practice, almost no real mail provider honors that distinction; Gmail, Outlook and the rest all treat the local part case-insensitively too. The practical takeaway: lowercase the domain when you store an address for deduplication, but don't force-lowercase the local part and assume it's always safe — it's a spec detail that's mostly moot but occasionally bites someone running their own mail server.
Quoted local parts and rare special characters
RFC 5322 technically allows a quoted local part, so a string like "[email protected]"@example.com is, on paper, a valid email address — the quotes let the local part contain characters (spaces, extra @signs, extra dots) that would otherwise be illegal. This almost never appears in the real world. Essentially no signup form, no CRM and no mail client generates addresses like this, and most production regexes — including the simple pattern here — correctly choose not to support it. Supporting it means widening the pattern to accept exactly the kind of malformed-looking input you actually want to catch, in exchange for handling addresses that in practice don't exist. That's a bad trade for a signup form, which is why nearly every real system makes it on purpose.
International and Unicode addresses
Addresses like user@example.рф (an internationalized domain name) or a UTF-8 local part such as 用户@example.comare legitimately valid under modern standards (IDNA for domains, SMTPUTF8 for local parts), and a plain ASCII-only pattern — including the simple one above, applied naively — will reject them or mangle them depending on whether the input has already been punycode-encoded upstream. This is a real correctness gap in most naive email regexes, and it's worth naming honestly rather than promising a fix: full IDN and SMTPUTF8 support is a genuinely harder problem than a single regex line can solve well, and most consumer-facing forms in English-speaking markets accept the gap as a known limitation rather than solve it outright. If your product serves users who register with non-Latin addresses, that's a real accessibility issue worth flagging to whoever owns the signup flow — not something a slightly longer regex quietly fixes.
The Decision Framework: What to Actually Use on a Signup Form
Given all of that, here's the practical rule that most production systems converge on, once someone has been burned by trying to make the regex airtight:
- Use a simple, permissive pattern client-side. Its only job is to reject obvious garbage — a missing
@, no domain at all, a string that's clearly not an email — fast enough to give the user immediate feedback before they submit the form. - Don't chase spec completeness. Trying to make a client-side regex handle quoted local parts, comment syntax and every RFC 5322 corner case is a well-documented time sink: it adds complexity, makes the pattern harder to read and debug, and buys you correctness for addresses that essentially never occur in practice.
- Send a confirmation email as the real check. This is the step that actually proves anything — that the address exists, that it accepts mail, and that whoever submitted the form controls it. No regex, however good, does any of that. A syntax check and a delivery proof are two entirely different questions, and only one of them can be answered with a pattern match.
Test the simple pattern, or any variant you're considering, against the exact edge cases above — plus-addressing, subdomains, and a deliberately malformed string or two — in GenKitLab's Regex Tester. Seeing the match highlighted live against real sample addresses is a faster way to build confidence in a pattern than reading about it, and it catches the case where a “fix” for one edge case quietly breaks another. If you're building or debugging other patterns beyond email, the Regex Tester guide covers flags, capture groups and replace previews in full, and the Regex Generator guide covers building a pattern from matching and non-matching examples instead of writing one by hand.
Frequently asked questions
›What is the best regex for email validation?
For a signup form, the simple pattern ^[^\s@]+@[^\s@]+\.[^\s@]+$ is the most widely used because it rejects obviously malformed input (no @, no domain) without pretending to enforce the full RFC 5322 spec. There is no single 'best' pattern for every use case — a spec-conformance checker needs something far more elaborate, but almost nothing else does.
›Does the RFC 5322 email regex actually work?
It matches the spec correctly, but it's hundreds of characters long, hard to read, hard to debug, and — like every email regex — it still can't confirm the address is deliverable. Most teams that try it in production end up replacing it with a simpler pattern once they hit its complexity in code review or a debugging session.
›How do I write a JavaScript email validation regex?
Use the simple pattern directly in a RegExp: /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email). It runs in a browser or Node without any dependency, and it catches the same obvious-garbage cases (missing @, missing domain, embedded whitespace) that a longer pattern would, without the maintenance cost.
›Why does my email regex reject valid addresses like [email protected]?
Plus-addressing is valid and common — Gmail and most providers treat the +tag suffix in the local part as an optional filter, stripped before delivery. If your pattern only allows letters, digits and a few symbols in the local part, it will incorrectly reject these. The simple ^[^\s@]+@[^\s@]+\.[^\s@]+$ pattern allows + because it isn't whitespace or an @.
›Can a regex confirm an email address is real?
No. A regex can only check that a string is shaped like an email address — it has no way to check whether the domain has a mail server or whether the mailbox actually exists. The only real proof is sending a confirmation email and requiring the recipient to click a link or enter a code.
›Should I allow Unicode characters in an email regex?
A plain ASCII-only pattern will reject legitimately valid internationalized addresses — IDN domains and SMTPUTF8 local parts with non-Latin characters. That's a real correctness gap worth being aware of, though supporting it properly is a bigger job than adjusting one regex line, and most English-market signup forms accept the limitation rather than solve it fully.
›Are quoted email local parts like "[email protected]"@example.com valid?
Technically yes, under RFC 5322 — quoting a local part allows characters like spaces and extra @ signs that would otherwise be illegal. In practice this format essentially never appears in real addresses, and most production regexes, including the simple pattern here, deliberately don't support it, since doing so would mean accepting exactly the kind of malformed-looking input you actually want to reject.
Last updated