Presets include valid newer gTLDs, plus-addressing, subdomains, and one obviously broken local part.
Waiting for input.
Waiting for input.
Waiting for input.
If your signup form still expects most legitimate addresses to end in .com, .net,
or .info, this guide can help bring it up to date.
It explains why newer gTLDs are normal, why [a-z]{2,4} causes avoidable mistakes,
where HTML5 helps, where regex stops, and what practical validation looks like in 2026.
Native HTML5 validation is intentionally lightweight. The pragmatic regex below is stricter about obvious mistakes. Neither one proves delivery. That comes later.
Presets include valid newer gTLDs, plus-addressing, subdomains, and one obviously broken local part.
Waiting for input.
Waiting for input.
Waiting for input.
Many validators were written for an older internet and simply need a more current rule set.
[a-z]{2,4} treats .photography like a syntax error, even though it is a perfectly valid modern TLD.
Rejecting +, -, or dots in the local part breaks aliases, filters, and security-minded users who compartmentalize mail.
Even a perfect parser cannot prove the mailbox exists, accepts mail, or belongs to the person typing it.
.com|.net|.org instead of allowing the broader range of TLDs now in use.user+tag@domain.com even though plus-addressing is a normal and useful workflow.user+tag@domain.com.New gTLDs were not a fad. They were a policy shift, a DNS rollout, and a clear signal that validators needed to evolve.
.email, .solutions, .engineering, and .photography.
If your validation rule still assumes the domain space ends around .museum, it is probably time for a refresh.
[a-z]{2,4} bugDevelopers copied TLD-length caps from old blog posts and baked them into validation logic. That assumption was always brittle, and it became actively wrong once long branded and descriptive TLDs arrived.
RFC 1035 permits DNS labels up to 63 octets. Real modern TLDs like
.cancerresearch (14 characters) and .northwesternmutual (19 characters)
are both far longer than the old {2,4} assumption.
The same era also produced validators that rejected perfectly normal plus-addressing such as
user+tag@domain.com, and sometimes even disallowed dots or hyphens in the local part.
That breaks aliases, filtering workflows, and mailbox organization patterns that many users rely on every day.
Then there are IDNs and EAI: internationalized domains can appear as Punycode such as xn--bcher-kva.example,
and RFC 6530 / RFC 6531 allow non-ASCII email addresses in systems that support Email Address Internationalization.
ASCII-only regex is still common, but it does not reflect the full range of real-world email usage.
The platform already gives you a lightweight browser validator. Production systems usually want a pragmatic regex on top, not an oversized pattern that is difficult to maintain and reason about.
type="email" patternThe living-standard regex is intentionally simplified. It is there to catch obvious input errors and provide consistent browser UX, not to implement every edge case from RFC 5322.
/^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@<a>a-zA-Z0-9</a>?(?:\.<a>a-zA-Z0-9</a>?)*$/
Yes, that weird <a> markup artifact is exactly how this snippet gets mangled when copied through HTML. The actual point is simple:
browsers intentionally use a much smaller, more maintainable rule than full RFC 5322 because full RFC 5322 is not a humane UX strategy.
The oversized pattern floating around the internet is hard to review, hard to maintain, and can introduce catastrophic backtracking and ReDoS risk into your signup form. Smaller, reviewable rules are usually the safer choice.
!#$%&'*+/=?^_`{|}~-.{2,4} or {2,6}.“At least 2 alphabetic characters” is a clear product rule. “At most 4” is usually a leftover assumption that no longer fits the current domain landscape.
<input
type="email"
name="email"
autocomplete="email"
inputmode="email"
required
/>
const EMAIL_RE =
/^[A-Za-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[A-Za-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[A-Za-z0-9](?:[A-Za-z0-9-]{0,61}[A-Za-z0-9])?\.)+[A-Za-z]{2,63}$/;
import re
EMAIL_RE = re.compile(
r"^[A-Za-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[A-Za-z0-9!#$%&'*+/=?^_`{|}~-]+)*@"
r"(?:[A-Za-z0-9](?:[A-Za-z0-9-]{0,61}[A-Za-z0-9])?\.)+[A-Za-z]{2,63}$"
)
var emailRE = regexp.MustCompile(
"^[A-Za-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\\\.[A-Za-z0-9!#$%&'*+/=?^_`{|}~-]+)*@" +
"(?:[A-Za-z0-9](?:[A-Za-z0-9-]{0,61}[A-Za-z0-9])?\\\\.)+[A-Za-z]{2,63}$",
)
EMAIL_RE =
/\A[A-Za-z0-9!#$%&'*+\/=?^_`{|}~-]+(?:\.[A-Za-z0-9!#$%&'*+\/=?^_`{|}~-]+)*@(?:[A-Za-z0-9](?:[A-Za-z0-9-]{0,61}[A-Za-z0-9])?\.)+[A-Za-z]{2,63}\z/
Effective validation pipelines stack inexpensive checks first and stronger confirmation later.
Use HTML5 type="email" and a pragmatic regex to catch missing @, broken domains, and obvious typos.
This is UX polish and typo-catching, not proof of existence.
Trim whitespace, lowercase the domain only, preserve local-part case semantics, and convert IDNs to Punycode before deeper checks. Clean input first so every downstream step is evaluating the same canonical form.
Check for MX records and fall back to A / AAAA per RFC 5321 section 5.1.
If the domain does not resolve or has no mail target, the address cannot receive mail no matter how pretty the regex result looked.
The definitive test is still a double opt-in, magic link, or confirmation token sent to the mailbox. The user clicking the link beats every theoretical parser on earth.
SMTP VRFY / RCPT TO probing may sound appealing, but greylisting and tarpits can return temporary
450 / 451 errors, catch-all domains may accept everything, and large providers may treat your IP like a harvesting bot.
It is usually a poor trade compared with confirmation email and normal deliverability monitoring.