6

I realize that there are a ton of regex email validations, but I can't seem to find one that adheres to the RFC 2822 standard.

The ones I find keep letting in junk like ..@abc.com get through.

Forgive me if the one of the questions is already answered adhering to RFC 2822 (but not annotated that it is).

Community
  • 1
  • 1
myermian
  • 31,823
  • 24
  • 123
  • 215
  • Are you trying to validate the email addresses? That standard appears to be more concerned with the messaging format itself. If so, what's wrong with example@abc.com - I would have thought that would be valid enough... – Reddog May 24 '11 at 20:30
  • 2
    @Reddog I thought he meant literally "..@abc.com". – Chris Farmer May 24 '11 at 20:32
  • @Chris - aaah, then surely that particular case could be added to any regex? – Reddog May 24 '11 at 20:38
  • @Reddog, I mean I want to validate the email addresses that RFC 2822 states is acceptable. Half the regex patterns you find through google allow junk to filter through, such as my example `..@abc.com` (and that's just ONE example of the "valid" emails that pass through these patterns I find through google. Ugh. – myermian May 24 '11 at 20:38
  • To make matters worse, I found that many pages do appear to not accept valid adresses as valid. I happen to have a domain with a german umlaut in it, and there are quite a few sites out there (and I am not referring to "mom and pop" pages) that reject adresses with domains that contain "non-ascii" characters. – Cornelius May 24 '11 at 21:55
  • @ClearsTheScreen: I'm not surprised. While internationalized domains exist, there's no finished standard for internationalized email addresses yet. All the RFCs on it are still in the draft stage: http://www.potaroo.net/ietf/html/ids-wg-eai.html – porges May 24 '11 at 22:22
  • @Porges Yes, I should have known better, yet was surprised about it. Then again, it took a while for Unicode to find it's way into the minds of the developers. And even when the standards are decided upon, I bet retro-fitting all the email systems around the world is a huge pain. :( – Cornelius May 26 '11 at 12:35

4 Answers4

4

I did a post on this a short while ago. Yes, it is possible using .NET regex, since they have a non-regular feature called "balancing groups".

The Perl RFC822 one that is often posted doesn't fully match email addresses, since it requires preprocessing to remove comments. It's also for a very old RFC (from 1982!).

This regex is for RFC5322, which is current. It also handles all comments and folding whitespace correctly.

Here is the regex:

^(?'localPart'((((\((((?'paren'\()|(?'-paren'\))|([\u0021-\u
0027\u002a-\u005b\u005d-\u007e]|[\u0001-\u0008\u000b\u000c\u
000e-\u001f\u007f])|([ \t]+((\r\n)[ \t]+)?|((\r\n)[ \t]+)+)|
\\([\u0021-\u007e]|[ \t]|[\r\n\0]|[\u0001-\u0008\u000b\u000c
\u000e-\u001f\u007f]))*(?(paren)(?!)))\))|([ \t]+((\r\n)[ \t
]+)?|((\r\n)[ \t]+)+))*?(([a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+)|(
"(([ \t]+((\r\n)[ \t]+)?|((\r\n)[ \t]+)+)?(([\u0021\u0023-\u
005b\u005d-\u007e]|[\u0001-\u0008\u000b\u000c\u000e-\u001f\u
007f])|\\([\u0021-\u007e]|[ \t]|[\r\n\0]|[\u0001-\u0008\u000
b\u000c\u000e-\u001f\u007f])))*([ \t]+((\r\n)[ \t]+)?|((\r\n
)[ \t]+)+)?"))((\((((?'paren'\()|(?'-paren'\))|([\u0021-\u00
27\u002a-\u005b\u005d-\u007e]|[\u0001-\u0008\u000b\u000c\u00
0e-\u001f\u007f])|([ \t]+((\r\n)[ \t]+)?|((\r\n)[ \t]+)+)|\\
([\u0021-\u007e]|[ \t]|[\r\n\0]|[\u0001-\u0008\u000b\u000c\u
000e-\u001f\u007f]))*(?(paren)(?!)))\))|([ \t]+((\r\n)[ \t]+
)?|((\r\n)[ \t]+)+))*?)(\.(((\((((?'paren'\()|(?'-paren'\))|
([\u0021-\u0027\u002a-\u005b\u005d-\u007e]|[\u0001-\u0008\u0
00b\u000c\u000e-\u001f\u007f])|([ \t]+((\r\n)[ \t]+)?|((\r\n
)[ \t]+)+)|\\([\u0021-\u007e]|[ \t]|[\r\n\0]|[\u0001-\u0008\
u000b\u000c\u000e-\u001f\u007f]))*(?(paren)(?!)))\))|([ \t]+
((\r\n)[ \t]+)?|((\r\n)[ \t]+)+))*?(([a-zA-Z0-9!#$%&'*+/=?^_
`{|}~-]+)|("(([ \t]+((\r\n)[ \t]+)?|((\r\n)[ \t]+)+)?(([\u00
21\u0023-\u005b\u005d-\u007e]|[\u0001-\u0008\u000b\u000c\u00
0e-\u001f\u007f])|\\([\u0021-\u007e]|[ \t]|[\r\n\0]|[\u0001-
\u0008\u000b\u000c\u000e-\u001f\u007f])))*([ \t]+((\r\n)[ \t
]+)?|((\r\n)[ \t]+)+)?"))((\((((?'paren'\()|(?'-paren'\))|([
\u0021-\u0027\u002a-\u005b\u005d-\u007e]|[\u0001-\u0008\u000
b\u000c\u000e-\u001f\u007f])|([ \t]+((\r\n)[ \t]+)?|((\r\n)[
\t]+)+)|\\([\u0021-\u007e]|[ \t]|[\r\n\0]|[\u0001-\u0008\u0
00b\u000c\u000e-\u001f\u007f]))*(?(paren)(?!)))\))|([ \t]+((
\r\n)[ \t]+)?|((\r\n)[ \t]+)+))*?))*))@(?'domain'((((\((((?'
paren'\()|(?'-paren'\))|([\u0021-\u0027\u002a-\u005b\u005d-\
u007e]|[\u0001-\u0008\u000b\u000c\u000e-\u001f\u007f])|([ \t
]+((\r\n)[ \t]+)?|((\r\n)[ \t]+)+)|\\([\u0021-\u007e]|[ \t]|
[\r\n\0]|[\u0001-\u0008\u000b\u000c\u000e-\u001f\u007f]))*(?
(paren)(?!)))\))|([ \t]+((\r\n)[ \t]+)?|((\r\n)[ \t]+)+))*?(
([a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+)|("(([ \t]+((\r\n)[ \t]+)?|
((\r\n)[ \t]+)+)?(([\u0021\u0023-\u005b\u005d-\u007e]|[\u000
1-\u0008\u000b\u000c\u000e-\u001f\u007f])|\\([\u0021-\u007e]
|[ \t]|[\r\n\0]|[\u0001-\u0008\u000b\u000c\u000e-\u001f\u007
f])))*([ \t]+((\r\n)[ \t]+)?|((\r\n)[ \t]+)+)?"))((\((((?'pa
ren'\()|(?'-paren'\))|([\u0021-\u0027\u002a-\u005b\u005d-\u0
07e]|[\u0001-\u0008\u000b\u000c\u000e-\u001f\u007f])|([ \t]+
((\r\n)[ \t]+)?|((\r\n)[ \t]+)+)|\\([\u0021-\u007e]|[ \t]|[\
r\n\0]|[\u0001-\u0008\u000b\u000c\u000e-\u001f\u007f]))*(?(p
aren)(?!)))\))|([ \t]+((\r\n)[ \t]+)?|((\r\n)[ \t]+)+))*?)(\
.(((\((((?'paren'\()|(?'-paren'\))|([\u0021-\u0027\u002a-\u0
05b\u005d-\u007e]|[\u0001-\u0008\u000b\u000c\u000e-\u001f\u0
07f])|([ \t]+((\r\n)[ \t]+)?|((\r\n)[ \t]+)+)|\\([\u0021-\u0
07e]|[ \t]|[\r\n\0]|[\u0001-\u0008\u000b\u000c\u000e-\u001f\
u007f]))*(?(paren)(?!)))\))|([ \t]+((\r\n)[ \t]+)?|((\r\n)[
\t]+)+))*?(([a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+)|("(([ \t]+((\r\
n)[ \t]+)?|((\r\n)[ \t]+)+)?(([\u0021\u0023-\u005b\u005d-\u0
07e]|[\u0001-\u0008\u000b\u000c\u000e-\u001f\u007f])|\\([\u0
021-\u007e]|[ \t]|[\r\n\0]|[\u0001-\u0008\u000b\u000c\u000e-
\u001f\u007f])))*([ \t]+((\r\n)[ \t]+)?|((\r\n)[ \t]+)+)?"))
((\((((?'paren'\()|(?'-paren'\))|([\u0021-\u0027\u002a-\u005
b\u005d-\u007e]|[\u0001-\u0008\u000b\u000c\u000e-\u001f\u007
f])|([ \t]+((\r\n)[ \t]+)?|((\r\n)[ \t]+)+)|\\([\u0021-\u007
e]|[ \t]|[\r\n\0]|[\u0001-\u0008\u000b\u000c\u000e-\u001f\u0
07f]))*(?(paren)(?!)))\))|([ \t]+((\r\n)[ \t]+)?|((\r\n)[ \t
]+)+))*?))*)|(((\((((?'paren'\()|(?'-paren'\))|([\u0021-\u00
27\u002a-\u005b\u005d-\u007e]|[\u0001-\u0008\u000b\u000c\u00
0e-\u001f\u007f])|([ \t]+((\r\n)[ \t]+)?|((\r\n)[ \t]+)+)|\\
([\u0021-\u007e]|[ \t]|[\r\n\0]|[\u0001-\u0008\u000b\u000c\u
000e-\u001f\u007f]))*(?(paren)(?!)))\))|([ \t]+((\r\n)[ \t]+
)?|((\r\n)[ \t]+)+))*?\[(([ \t]+((\r\n)[ \t]+)?|((\r\n)[ \t]
+)+)?([!-Z^-~]|[\u0001-\u0008\u000b\u000c\u000e-\u001f\u007f
]))*([ \t]+((\r\n)[ \t]+)?|((\r\n)[ \t]+)+)?\]((\((((?'paren
'\()|(?'-paren'\))|([\u0021-\u0027\u002a-\u005b\u005d-\u007e
]|[\u0001-\u0008\u000b\u000c\u000e-\u001f\u007f])|([ \t]+((\
r\n)[ \t]+)?|((\r\n)[ \t]+)+)|\\([\u0021-\u007e]|[ \t]|[\r\n
\0]|[\u0001-\u0008\u000b\u000c\u000e-\u001f\u007f]))*(?(pare
n)(?!)))\))|([ \t]+((\r\n)[ \t]+)?|((\r\n)[ \t]+)+))*?))\z

Some caveats, however. RFC5322 is more liberal with domain names than the actual domain RFCs, and there are other restrictions that apply from various RFCs such as the actual SMTP RFC itself (which specifies a maximum length). So even though an email is correct according to 5322 it can be invalid by various other measures.

The golden test is still to send an email to the address with a validation code.

porges
  • 30,133
  • 4
  • 83
  • 114
2

This is for RFC822, not for the newer one. But it seems the address format has not been changed, so should be what you're looking for.

(note the remark below the regexp--it still assumes that the address has been preprocessed)

Community
  • 1
  • 1
liori
  • 40,917
  • 13
  • 78
  • 105
1

This runs in PCRE: http://code.iamcal.com/php/rfc822/full_regexp.txt

It's 32k, apparently.

Seriously - maybe consider backing off using a single regexp, or accepting ALL possible email forms.

Cheeso
  • 189,189
  • 101
  • 473
  • 713
0

I would look at this: http://www.regular-expressions.info/email.html, which explains a lot about using regular expressions to match email addresses, and includes a full RFC 2822 expression which honestly I would almost never recommended using.

daalbert
  • 1,465
  • 9
  • 7