RFC 5322 allows a wider range of characters in email local parts than most developers or validators expect. This lesson catalogs exactly what is and isn't allowed, and shows how to test for over-restrictive validators.
The Complete atext Character Set
In the dot-atom (unquoted) local part form, the allowed characters are defined as atext in RFC 5322 section 3.2.3:
atext = ALPHA / DIGIT / "!" / "#" / "$" / "%" / "&" / "'" /
"*" / "+" / "-" / "/" / "=" / "?" / "^" / "_" /
"`" / "{" / "|" / "}" / "~"
Expanded, the complete list of allowed symbols (non-alphanumeric):
! # $ % & ' * + - / = ? ^ _ ` { | } ~
All of these are valid in an unquoted email local part.
The characters NOT in atext (and therefore requiring quoting or being invalid entirely):
( ) [ ] \ , ; : < > @ space
Double quote " cannot appear unquoted either — it would be interpreted as the start of a quoted string.
Testing Each Special Character
The systematic test: for each special character in atext, construct a minimal email using only that character in the local part and verify it is accepted:
| Local part | Full address | Should be |
|---|---|---|
user!name |
user!name@example.com |
valid |
user#name |
user#name@example.com |
valid |
user$name |
user$name@example.com |
valid |
user%name |
user%name@example.com |
valid |
user&name |
user&name@example.com |
valid |
user'name |
user'name@example.com |
valid |
user*name |
user*name@example.com |
valid |
user+name |
user+name@example.com |
valid |
user-name |
user-name@example.com |
valid |
user/name |
user/name@example.com |
valid |
user=name |
user=name@example.com |
valid |
user?name |
user?name@example.com |
valid |
user^name |
user^name@example.com |
valid |
user_name |
user_name@example.com |
valid |
user`name |
user`name@example.com |
valid |
user{name |
user{name@example.com |
valid |
user\|name |
user\|name@example.com |
valid |
user}name |
user}name@example.com |
valid |
user~name |
user~name@example.com |
valid |
Any rejection from this list is a validator defect.
The Quoted String Form
When the local part is enclosed in double quotes, the constraints change dramatically. Inside quotes:
- Spaces are allowed:
"user name"@example.com - Most special characters that are normally forbidden are allowed:
"user(name)"@example.com - The
@symbol is allowed:"user@alias"@example.com - Backslash-escaped characters are allowed:
"user\"name"@example.com
The quoted string rules:
- The entire local part must be wrapped in quotes (not just part of it)
- Inside quotes,
"and\must be escaped:\"and\\ - Printable ASCII characters (except
"and\) do not need escaping
This is the most commonly unsupported valid form. Real mail addresses using quoted local parts are vanishingly rare, but per the RFC, they must be accepted by conformant parsers.
Dot Rules in Detail
Even with the full atext character set, dots have specific rules:
Rule 1: No dot at the start of the local part
.user@example.com— invalid. user@example.com— invalid
Rule 2: No dot at the end of the local part
user.@example.com— invaliduser. @example.com— invalid
Rule 3: No two consecutive dots
user..name@example.com— invaliduser.name..more@example.com— invalid
Valid uses of dots:
user.name@example.com— single dot between wordsuser.middle.name@example.com— multiple single dotsfirst.last+tag@example.com— dots combined with other specials
The Most Common Validator Failure
Based on real-world testing of production applications, the most commonly rejected valid characters are:
+(plus sign) — rejected by roughly 30% of email validators'(apostrophe) — rejected by about 25%=(equals sign) — rejected by about 20%!(exclamation mark) — rejected by about 15%- Quoted strings — rejected by nearly all simple regex validators
The + case is particularly impactful because Gmail's address tagging feature (user+newsletter@gmail.com) is widely used and involves real addresses that your users will submit.
What to Include in Your Test Suite
At minimum, test these cases for any email validation:
user+tag@example.com— plus sign (most commonly broken)user_name@example.com— underscoreuser.name@example.com— dot (valid use).user@example.com— leading dot (should fail)user.@example.com— trailing dot (should fail)user..name@example.com— consecutive dots (should fail)"user name"@example.com— quoted string (should succeed per RFC; often fails)