I wanted to find a regular expression to validate e-mail addresses, but when I searched I found dozens of slightly different versions of the same expression. Almost all of them had people leaving comments about how it failed to validate or invalidate some rare but completely valid/invalid address syntax. But dispite all the criticism, I couldn't find a definitive "best" expression. So, I setup arrays of some of the most promising expressions as well as a (hopefully) complete sampling of valid and invalid addresses. It's my philosophy that it's better to accept a few invalid addresses than reject any valid ones, so I'm shooting for 0 false-positives and as few false-negatives as possible. If you have any sample addresses or expressions that you think should be added to the list, or if you can further improve the best expression please e-mail me at:

Conclusion:
Geert De Deckere from the Kohana project has developed a near perfect one:
/^[-_a-z0-9\'+*$^&%=~!?{}]++(?:\.[-_a-z0-9\'+*$^&%=~!?{}]+)*+@(?:(?![-.])[-a-z0-9.]+(?<![-.])\.[a-z]{2,6}|\d{1,3}(?:\.\d{1,3}){3})(?::\d++)?$/iD
Notes:
| These should be valid | |
| l3tt3rsAndNumb3rs@domain.com | valid |
| has-dash@domain.com | valid |
| hasApostrophe.o'leary@domain.org | valid |
| uncommonTLD@domain.museum | valid |
| uncommonTLD@domain.travel | valid |
| uncommonTLD@domain.mobi | valid |
| countryCodeTLD@domain.uk | valid |
| lettersInDomain@911.com | valid |
| underscore_inLocal@domain.net | valid |
| IPInsteadOfDomain@127.0.0.1 | valid |
| IPAndPort@127.0.0.1:25 | valid |
| subdomain@sub.domain.com | valid |
| local@dash-inDomain.com | valid |
| dot.inLocal@foo.com | valid |
| a@singleLetterLocal.org | valid |
| singleLetterDomain@x.org | valid |
| &*=?^+{}'~@validCharsInLocal.net | valid |
| These should be invalid | |
| missingDomain@.com | invalid |
| @missingLocal.org | invalid |
| missingatSign.net | invalid |
| missingDot@com | invalid |
| two@@signs.com | invalid |
| colonButNoPort@127.0.0.1: | invalid |
| invalid | |
| someone-else@127.0.0.1.26 | invalid |
| .localStartsWithDot@domain.com | invalid |
| localEndsWithDot.@domain.com | invalid |
| two..consecutiveDots@domain.com | invalid |
| domainStartsWithDash@-domain.com | invalid |
| domainEndsWithDash@domain-.com | invalid |
| TLDDoesntExist@domain.moc | valid |
| numbersInTLD@domain.c0m | invalid |
| missingTLD@domain. | invalid |
| ! "#$%(),/;<>[]`|@invalidCharsInLocal.org | invalid |
| invalidCharsInDomain@! "#$%(),/;<>_[]`|.org | invalid |
| local@SecondLevelDomainNamesAreInvalidIfTheyAreLongerThan64Charactersss.org | valid |
Valid: 17/17
Invalid: 17/19
| These should be valid | |
| l3tt3rsAndNumb3rs@domain.com | valid |
| has-dash@domain.com | valid |
| hasApostrophe.o'leary@domain.org | valid |
| uncommonTLD@domain.museum | valid |
| uncommonTLD@domain.travel | invalid |
| uncommonTLD@domain.mobi | invalid |
| countryCodeTLD@domain.uk | valid |
| lettersInDomain@911.com | valid |
| underscore_inLocal@domain.net | valid |
| IPInsteadOfDomain@127.0.0.1 | valid |
| IPAndPort@127.0.0.1:25 | valid |
| subdomain@sub.domain.com | valid |
| local@dash-inDomain.com | invalid |
| dot.inLocal@foo.com | valid |
| a@singleLetterLocal.org | valid |
| singleLetterDomain@x.org | valid |
| &*=?^+{}'~@validCharsInLocal.net | valid |
| These should be invalid | |
| missingDomain@.com | invalid |
| @missingLocal.org | invalid |
| missingatSign.net | invalid |
| missingDot@com | invalid |
| two@@signs.com | invalid |
| colonButNoPort@127.0.0.1: | invalid |
| invalid | |
| someone-else@127.0.0.1.26 | invalid |
| .localStartsWithDot@domain.com | invalid |
| localEndsWithDot.@domain.com | invalid |
| two..consecutiveDots@domain.com | invalid |
| domainStartsWithDash@-domain.com | invalid |
| domainEndsWithDash@domain-.com | invalid |
| TLDDoesntExist@domain.moc | invalid |
| numbersInTLD@domain.c0m | invalid |
| missingTLD@domain. | invalid |
| ! "#$%(),/;<>[]`|@invalidCharsInLocal.org | invalid |
| invalidCharsInDomain@! "#$%(),/;<>_[]`|.org | invalid |
| local@SecondLevelDomainNamesAreInvalidIfTheyAreLongerThan64Charactersss.org | valid |
Valid: 14/17
Invalid: 18/19
| These should be valid | |
| l3tt3rsAndNumb3rs@domain.com | valid |
| has-dash@domain.com | valid |
| hasApostrophe.o'leary@domain.org | valid |
| uncommonTLD@domain.museum | valid |
| uncommonTLD@domain.travel | valid |
| uncommonTLD@domain.mobi | valid |
| countryCodeTLD@domain.uk | valid |
| lettersInDomain@911.com | valid |
| underscore_inLocal@domain.net | valid |
| IPInsteadOfDomain@127.0.0.1 | invalid |
| IPAndPort@127.0.0.1:25 | valid |
| subdomain@sub.domain.com | valid |
| local@dash-inDomain.com | valid |
| dot.inLocal@foo.com | valid |
| a@singleLetterLocal.org | valid |
| singleLetterDomain@x.org | valid |
| &*=?^+{}'~@validCharsInLocal.net | invalid |
| These should be invalid | |
| missingDomain@.com | invalid |
| @missingLocal.org | invalid |
| missingatSign.net | invalid |
| missingDot@com | invalid |
| two@@signs.com | invalid |
| colonButNoPort@127.0.0.1: | valid |
| invalid | |
| someone-else@127.0.0.1.26 | valid |
| .localStartsWithDot@domain.com | valid |
| localEndsWithDot.@domain.com | valid |
| two..consecutiveDots@domain.com | valid |
| domainStartsWithDash@-domain.com | valid |
| domainEndsWithDash@domain-.com | valid |
| TLDDoesntExist@domain.moc | valid |
| numbersInTLD@domain.c0m | valid |
| missingTLD@domain. | invalid |
| ! "#$%(),/;<>[]`|@invalidCharsInLocal.org | invalid |
| invalidCharsInDomain@! "#$%(),/;<>_[]`|.org | invalid |
| local@SecondLevelDomainNamesAreInvalidIfTheyAreLongerThan64Charactersss.org | valid |
Valid: 15/17
Invalid: 9/19
| These should be valid | |
| l3tt3rsAndNumb3rs@domain.com | valid |
| has-dash@domain.com | valid |
| hasApostrophe.o'leary@domain.org | invalid |
| uncommonTLD@domain.museum | valid |
| uncommonTLD@domain.travel | valid |
| uncommonTLD@domain.mobi | valid |
| countryCodeTLD@domain.uk | valid |
| lettersInDomain@911.com | valid |
| underscore_inLocal@domain.net | valid |
| IPInsteadOfDomain@127.0.0.1 | invalid |
| IPAndPort@127.0.0.1:25 | invalid |
| subdomain@sub.domain.com | valid |
| local@dash-inDomain.com | valid |
| dot.inLocal@foo.com | valid |
| a@singleLetterLocal.org | valid |
| singleLetterDomain@x.org | valid |
| &*=?^+{}'~@validCharsInLocal.net | invalid |
| These should be invalid | |
| missingDomain@.com | invalid |
| @missingLocal.org | invalid |
| missingatSign.net | invalid |
| missingDot@com | invalid |
| two@@signs.com | invalid |
| colonButNoPort@127.0.0.1: | invalid |
| invalid | |
| someone-else@127.0.0.1.26 | valid |
| .localStartsWithDot@domain.com | valid |
| localEndsWithDot.@domain.com | valid |
| two..consecutiveDots@domain.com | valid |
| domainStartsWithDash@-domain.com | valid |
| domainEndsWithDash@domain-.com | valid |
| TLDDoesntExist@domain.moc | valid |
| numbersInTLD@domain.c0m | valid |
| missingTLD@domain. | invalid |
| ! "#$%(),/;<>[]`|@invalidCharsInLocal.org | invalid |
| invalidCharsInDomain@! "#$%(),/;<>_[]`|.org | invalid |
| local@SecondLevelDomainNamesAreInvalidIfTheyAreLongerThan64Charactersss.org | valid |
Valid: 13/17
Invalid: 10/19
| These should be valid | |
| l3tt3rsAndNumb3rs@domain.com | valid |
| has-dash@domain.com | valid |
| hasApostrophe.o'leary@domain.org | invalid |
| uncommonTLD@domain.museum | invalid |
| uncommonTLD@domain.travel | invalid |
| uncommonTLD@domain.mobi | invalid |
| countryCodeTLD@domain.uk | invalid |
| lettersInDomain@911.com | valid |
| underscore_inLocal@domain.net | valid |
| IPInsteadOfDomain@127.0.0.1 | invalid |
| IPAndPort@127.0.0.1:25 | invalid |
| subdomain@sub.domain.com | invalid |
| local@dash-inDomain.com | invalid |
| dot.inLocal@foo.com | invalid |
| a@singleLetterLocal.org | valid |
| singleLetterDomain@x.org | valid |
| &*=?^+{}'~@validCharsInLocal.net | invalid |
| These should be invalid | |
| missingDomain@.com | invalid |
| @missingLocal.org | invalid |
| missingatSign.net | invalid |
| missingDot@com | invalid |
| two@@signs.com | invalid |
| colonButNoPort@127.0.0.1: | invalid |
| invalid | |
| someone-else@127.0.0.1.26 | invalid |
| .localStartsWithDot@domain.com | invalid |
| localEndsWithDot.@domain.com | invalid |
| two..consecutiveDots@domain.com | invalid |
| domainStartsWithDash@-domain.com | invalid |
| domainEndsWithDash@domain-.com | invalid |
| TLDDoesntExist@domain.moc | invalid |
| numbersInTLD@domain.c0m | invalid |
| missingTLD@domain. | invalid |
| ! "#$%(),/;<>[]`|@invalidCharsInLocal.org | invalid |
| invalidCharsInDomain@! "#$%(),/;<>_[]`|.org | invalid |
| local@SecondLevelDomainNamesAreInvalidIfTheyAreLongerThan64Charactersss.org | valid |
Valid: 6/17
Invalid: 18/19
| These should be valid | |
| l3tt3rsAndNumb3rs@domain.com | valid |
| has-dash@domain.com | valid |
| hasApostrophe.o'leary@domain.org | invalid |
| uncommonTLD@domain.museum | valid |
| uncommonTLD@domain.travel | invalid |
| uncommonTLD@domain.mobi | valid |
| countryCodeTLD@domain.uk | valid |
| lettersInDomain@911.com | valid |
| underscore_inLocal@domain.net | valid |
| IPInsteadOfDomain@127.0.0.1 | invalid |
| IPAndPort@127.0.0.1:25 | invalid |
| subdomain@sub.domain.com | valid |
| local@dash-inDomain.com | valid |
| dot.inLocal@foo.com | valid |
| a@singleLetterLocal.org | invalid |
| singleLetterDomain@x.org | invalid |
| &*=?^+{}'~@validCharsInLocal.net | invalid |
| These should be invalid | |
| missingDomain@.com | invalid |
| @missingLocal.org | invalid |
| missingatSign.net | invalid |
| missingDot@com | invalid |
| two@@signs.com | invalid |
| colonButNoPort@127.0.0.1: | invalid |
| invalid | |
| someone-else@127.0.0.1.26 | invalid |
| .localStartsWithDot@domain.com | invalid |
| localEndsWithDot.@domain.com | invalid |
| two..consecutiveDots@domain.com | invalid |
| domainStartsWithDash@-domain.com | invalid |
| domainEndsWithDash@domain-.com | invalid |
| TLDDoesntExist@domain.moc | valid |
| numbersInTLD@domain.c0m | invalid |
| missingTLD@domain. | invalid |
| ! "#$%(),/;<>[]`|@invalidCharsInLocal.org | invalid |
| invalidCharsInDomain@! "#$%(),/;<>_[]`|.org | invalid |
| local@SecondLevelDomainNamesAreInvalidIfTheyAreLongerThan64Charactersss.org | valid |
Valid: 10/17
Invalid: 17/19
| These should be valid | |
| l3tt3rsAndNumb3rs@domain.com | valid |
| has-dash@domain.com | valid |
| hasApostrophe.o'leary@domain.org | invalid |
| uncommonTLD@domain.museum | invalid |
| uncommonTLD@domain.travel | invalid |
| uncommonTLD@domain.mobi | valid |
| countryCodeTLD@domain.uk | valid |
| lettersInDomain@911.com | valid |
| underscore_inLocal@domain.net | valid |
| IPInsteadOfDomain@127.0.0.1 | invalid |
| IPAndPort@127.0.0.1:25 | invalid |
| subdomain@sub.domain.com | valid |
| local@dash-inDomain.com | valid |
| dot.inLocal@foo.com | valid |
| a@singleLetterLocal.org | valid |
| singleLetterDomain@x.org | valid |
| &*=?^+{}'~@validCharsInLocal.net | invalid |
| These should be invalid | |
| missingDomain@.com | invalid |
| @missingLocal.org | invalid |
| missingatSign.net | invalid |
| missingDot@com | invalid |
| two@@signs.com | invalid |
| colonButNoPort@127.0.0.1: | invalid |
| invalid | |
| someone-else@127.0.0.1.26 | invalid |
| .localStartsWithDot@domain.com | valid |
| localEndsWithDot.@domain.com | valid |
| two..consecutiveDots@domain.com | valid |
| domainStartsWithDash@-domain.com | valid |
| domainEndsWithDash@domain-.com | valid |
| TLDDoesntExist@domain.moc | valid |
| numbersInTLD@domain.c0m | invalid |
| missingTLD@domain. | invalid |
| ! "#$%(),/;<>[]`|@invalidCharsInLocal.org | invalid |
| invalidCharsInDomain@! "#$%(),/;<>_[]`|.org | invalid |
| local@SecondLevelDomainNamesAreInvalidIfTheyAreLongerThan64Charactersss.org | valid |
Valid: 11/17
Invalid: 12/19
| These should be valid | |
| l3tt3rsAndNumb3rs@domain.com | valid |
| has-dash@domain.com | valid |
| hasApostrophe.o'leary@domain.org | invalid |
| uncommonTLD@domain.museum | valid |
| uncommonTLD@domain.travel | valid |
| uncommonTLD@domain.mobi | valid |
| countryCodeTLD@domain.uk | valid |
| lettersInDomain@911.com | valid |
| underscore_inLocal@domain.net | valid |
| IPInsteadOfDomain@127.0.0.1 | invalid |
| IPAndPort@127.0.0.1:25 | invalid |
| subdomain@sub.domain.com | valid |
| local@dash-inDomain.com | valid |
| dot.inLocal@foo.com | valid |
| a@singleLetterLocal.org | valid |
| singleLetterDomain@x.org | invalid |
| &*=?^+{}'~@validCharsInLocal.net | invalid |
| These should be invalid | |
| missingDomain@.com | invalid |
| @missingLocal.org | invalid |
| missingatSign.net | invalid |
| missingDot@com | invalid |
| two@@signs.com | invalid |
| colonButNoPort@127.0.0.1: | invalid |
| invalid | |
| someone-else@127.0.0.1.26 | invalid |
| .localStartsWithDot@domain.com | valid |
| localEndsWithDot.@domain.com | valid |
| two..consecutiveDots@domain.com | valid |
| domainStartsWithDash@-domain.com | invalid |
| domainEndsWithDash@domain-.com | invalid |
| TLDDoesntExist@domain.moc | valid |
| numbersInTLD@domain.c0m | invalid |
| missingTLD@domain. | invalid |
| ! "#$%(),/;<>[]`|@invalidCharsInLocal.org | invalid |
| invalidCharsInDomain@! "#$%(),/;<>_[]`|.org | invalid |
| local@SecondLevelDomainNamesAreInvalidIfTheyAreLongerThan64Charactersss.org | valid |
Valid: 12/17
Invalid: 14/19
| These should be valid | |
| l3tt3rsAndNumb3rs@domain.com | valid |
| has-dash@domain.com | valid |
| hasApostrophe.o'leary@domain.org | valid |
| uncommonTLD@domain.museum | valid |
| uncommonTLD@domain.travel | valid |
| uncommonTLD@domain.mobi | valid |
| countryCodeTLD@domain.uk | valid |
| lettersInDomain@911.com | valid |
| underscore_inLocal@domain.net | valid |
| IPInsteadOfDomain@127.0.0.1 | valid |
| IPAndPort@127.0.0.1:25 | invalid |
| subdomain@sub.domain.com | valid |
| local@dash-inDomain.com | valid |
| dot.inLocal@foo.com | valid |
| a@singleLetterLocal.org | valid |
| singleLetterDomain@x.org | valid |
| &*=?^+{}'~@validCharsInLocal.net | valid |
| These should be invalid | |
| missingDomain@.com | invalid |
| @missingLocal.org | invalid |
| missingatSign.net | invalid |
| missingDot@com | invalid |
| two@@signs.com | invalid |
| colonButNoPort@127.0.0.1: | invalid |
| invalid | |
| someone-else@127.0.0.1.26 | valid |
| .localStartsWithDot@domain.com | invalid |
| localEndsWithDot.@domain.com | invalid |
| two..consecutiveDots@domain.com | invalid |
| domainStartsWithDash@-domain.com | valid |
| domainEndsWithDash@domain-.com | valid |
| TLDDoesntExist@domain.moc | valid |
| numbersInTLD@domain.c0m | valid |
| missingTLD@domain. | invalid |
| ! "#$%(),/;<>[]`|@invalidCharsInLocal.org | invalid |
| invalidCharsInDomain@! "#$%(),/;<>_[]`|.org | invalid |
| local@SecondLevelDomainNamesAreInvalidIfTheyAreLongerThan64Charactersss.org | valid |
Valid: 16/17
Invalid: 13/19
| These should be valid | |
| l3tt3rsAndNumb3rs@domain.com | valid |
| has-dash@domain.com | valid |
| hasApostrophe.o'leary@domain.org | invalid |
| uncommonTLD@domain.museum | valid |
| uncommonTLD@domain.travel | valid |
| uncommonTLD@domain.mobi | valid |
| countryCodeTLD@domain.uk | valid |
| lettersInDomain@911.com | valid |
| underscore_inLocal@domain.net | valid |
| IPInsteadOfDomain@127.0.0.1 | invalid |
| IPAndPort@127.0.0.1:25 | invalid |
| subdomain@sub.domain.com | valid |
| local@dash-inDomain.com | valid |
| dot.inLocal@foo.com | valid |
| a@singleLetterLocal.org | valid |
| singleLetterDomain@x.org | valid |
| &*=?^+{}'~@validCharsInLocal.net | invalid |
| These should be invalid | |
| missingDomain@.com | invalid |
| @missingLocal.org | invalid |
| missingatSign.net | invalid |
| missingDot@com | invalid |
| two@@signs.com | invalid |
| colonButNoPort@127.0.0.1: | invalid |
| invalid | |
| someone-else@127.0.0.1.26 | invalid |
| .localStartsWithDot@domain.com | invalid |
| localEndsWithDot.@domain.com | invalid |
| two..consecutiveDots@domain.com | invalid |
| domainStartsWithDash@-domain.com | valid |
| domainEndsWithDash@domain-.com | valid |
| TLDDoesntExist@domain.moc | valid |
| numbersInTLD@domain.c0m | invalid |
| missingTLD@domain. | invalid |
| ! "#$%(),/;<>[]`|@invalidCharsInLocal.org | invalid |
| invalidCharsInDomain@! "#$%(),/;<>_[]`|.org | invalid |
| local@SecondLevelDomainNamesAreInvalidIfTheyAreLongerThan64Charactersss.org | valid |
Valid: 13/17
Invalid: 15/19
| These should be valid | |
| l3tt3rsAndNumb3rs@domain.com | valid |
| has-dash@domain.com | valid |
| hasApostrophe.o'leary@domain.org | valid |
| uncommonTLD@domain.museum | valid |
| uncommonTLD@domain.travel | valid |
| uncommonTLD@domain.mobi | valid |
| countryCodeTLD@domain.uk | valid |
| lettersInDomain@911.com | valid |
| underscore_inLocal@domain.net | valid |
| IPInsteadOfDomain@127.0.0.1 | valid |
| IPAndPort@127.0.0.1:25 | invalid |
| subdomain@sub.domain.com | valid |
| local@dash-inDomain.com | valid |
| dot.inLocal@foo.com | valid |
| a@singleLetterLocal.org | valid |
| singleLetterDomain@x.org | valid |
| &*=?^+{}'~@validCharsInLocal.net | valid |
| These should be invalid | |
| missingDomain@.com | invalid |
| @missingLocal.org | invalid |
| missingatSign.net | invalid |
| missingDot@com | valid |
| two@@signs.com | invalid |
| colonButNoPort@127.0.0.1: | invalid |
| invalid | |
| someone-else@127.0.0.1.26 | valid |
| .localStartsWithDot@domain.com | invalid |
| localEndsWithDot.@domain.com | invalid |
| two..consecutiveDots@domain.com | invalid |
| domainStartsWithDash@-domain.com | valid |
| domainEndsWithDash@domain-.com | valid |
| TLDDoesntExist@domain.moc | valid |
| numbersInTLD@domain.c0m | valid |
| missingTLD@domain. | invalid |
| ! "#$%(),/;<>[]`|@invalidCharsInLocal.org | invalid |
| invalidCharsInDomain@! "#$%(),/;<>_[]`|.org | invalid |
| local@SecondLevelDomainNamesAreInvalidIfTheyAreLongerThan64Charactersss.org | valid |
Valid: 16/17
Invalid: 12/19