Regex for Email Validation: Patterns That Actually Work
Email validation is one of the most common regex use cases — and one of the most misunderstood. The RFC 5321 specification for email addresses is surprisingly complex, and no single regex can fully validate it. But practical patterns that cover 99.9% of real email addresses are both achievable and useful.
The Simple Pattern (Good Enough)
For most applications, this pattern works well:
^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$
What it matches: One or more allowed characters, followed by @, followed by a domain with at least one dot and a TLD of 2+ letters.
JavaScript:
const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
emailRegex.test('user@example.com'); // true
emailRegex.test('user@.com'); // false
Test this pattern with our Regex Tester.
Why Perfect Regex Validation Is Impossible
The email specification (RFC 5321/5322) allows structures that are valid but essentially never used in practice:
"john..doe"@example.com // Quoted local part with consecutive dots
user@[192.168.1.1] // IP address as domain
"very.(),:;<>[]".VERY."very@\ "very".unusual"@strange.example.com
A regex that handles all RFC-valid addresses is thousands of characters long and still may not cover every edge case. The practical approach: use a simple regex for basic format validation, then verify the email actually exists by sending a confirmation.
Pattern Breakdown
Local Part (before @)
[a-zA-Z0-9._%+-]+
- Letters (upper and lowercase)
- Digits
- Dots, underscores, percent, plus, hyphen
- One or more characters
Common mistakes:
- Allowing dots at the start or end (technically invalid)
- Allowing consecutive dots (technically invalid without quoting)
- Being too restrictive (blocking valid characters like
+used in Gmail aliases)
Domain Part (after @)
[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}
- Alphanumeric characters, dots, hyphens
- At least one dot
- TLD of 2+ alphabetic characters
Common mistakes:
- Restricting TLD length to 3-4 characters (
.museum,.photographyexist) - Not allowing hyphens in domain names
- Not handling subdomains (
user@mail.example.co.uk)
Better Patterns
HTML5 Standard
The HTML5 specification defines this pattern for <input type="email">:
^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$
This is more permissive in the local part and more strict about domain label lengths.
Practical Recommended Pattern
^[^\s@]+@[^\s@]+\.[^\s@]{2,}$
This minimal pattern simply ensures: no spaces, one @, at least one dot after @, TLD of 2+ characters. It is intentionally permissive — catching obviously wrong input without rejecting unusual but valid addresses.
Language-Specific Implementation
JavaScript
function isValidEmail(email) {
// Basic regex check
const regex = /^[^\s@]+@[^\s@]+\.[^\s@]{2,}$/;
if (!regex.test(email)) return false;
// Additional checks
if (email.length > 254) return false; // RFC 5321 limit
const [local] = email.split('@');
if (local.length > 64) return false; // RFC 5321 limit
return true;
}
Python
import re
def is_valid_email(email: str) -> bool:
pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
if not re.match(pattern, email):
return False
if len(email) > 254:
return False
local, domain = email.rsplit('@', 1)
if len(local) > 64:
return False
return True
Beyond Regex: Proper Email Validation
Regex is just the first line of defense. A complete validation strategy:
- Format check (regex): Reject obviously invalid formats
- Length check: Local part ≤ 64 chars, total ≤ 254 chars
- DNS check: Verify the domain has MX records
- Disposable email detection: Block temporary email services if needed
- Confirmation email: The only way to truly verify an email — send a message and confirm the user receives it
// DNS MX record check (Node.js)
const dns = require('dns');
const [, domain] = email.split('@');
dns.resolveMx(domain, (err, addresses) => {
if (err || !addresses.length) {
console.log('Domain has no email server');
}
});
Common Mistakes to Avoid
- Over-restrictive patterns: Blocking
user+tag@gmail.com(plus addressing) oruser@subdomain.example.com - Case sensitivity: Email local parts can be case-sensitive per RFC, but in practice, treat them as case-insensitive
- Trimming: Always trim whitespace before validation —
" user@example.com "should pass - International domains:
.münchenand用户@例え.jpare valid in internationalized email
For more regex patterns, see our Regex Cheat Sheet.
FAQ
Should I validate email with regex on the client or server?
Both. Client-side validation provides instant feedback (better UX). Server-side validation is mandatory for security (client checks can be bypassed). Never trust client-side validation alone.
Why do some websites reject my valid email address?
Overly restrictive regex patterns are the usual cause. Addresses with + (Gmail aliases), long TLDs (.technology), or subdomains often get rejected by poor validation. If you maintain a website, use permissive regex and verify with a confirmation email instead.
Related Resources
- Regex Tester — Test email validation patterns in real-time
- Regex Cheat Sheet — Complete regex pattern reference
- JSON Schema Validation — Validate email fields in JSON with format: email