92

When users create an account on my site I want to make server validation for emails to not accept every input.

I will send a confirmation, in a way to do a handshake validation.

I am looking for something simple, not the best, but not too simple that doesn't validate anything. I don't know where limitation must be, since any regular expression will not do the correct validation because is not possible to do it with regular expressions.

I'm trying to limit the sintax and visual complexity inherent to regular expressions, because in this case any will be correct.

What regexp can I use to do that?

Jannie Theunissen
  • 28,256
  • 21
  • 100
  • 127
eKek0
  • 23,005
  • 25
  • 91
  • 119
  • Thought "simplest" was exactly as subjective as "best", ceteris paribus, and that thread had a cornucopia of regexes, but if you think so... *shrug* – Mihai Limbășan Apr 12 '09 at 21:26
  • If you do an regex validation why limiting the expression to something simple? Let's use something good, this will have no impact on your code providing better results. – twk Apr 12 '09 at 21:32
  • Where in your application would this validation would be? On POST? What are you doing for sanitizing input? – Braiam Feb 06 '19 at 12:50
  • ^(?i)[A-Z0-9+_.-]+@(?:.*).(?:.*)$, ^ denotes start, $ denotes end, (?i) case insensitive match. before @ only allow alphanumeric, '+', '_', '-'. this one, ?: for no partial match subgroup formation, only 1 full match – Satish Patro Nov 09 '19 at 08:54

5 Answers5

270

It's possible to write a regular expression that only accept email addresses that follow the standards. However, there are some email addresses out there that doesn't strictly follow the standards, but still work.

Here are some simple regular expressions for basic validation:

Contains a @ character:

@

Contains @ and a period somewhere after it:

@.*?\.

Has at least one character before the @, before the period and after it:

.+@.+\..+

Has only one @, at least one character before the @, before the period and after it:

^[^@]+@[^@]+\.[^@]+$

User AmoebaMan17 suggests this modification to eliminate whitespace:

^[^@\s]+@[^@\s]+\.[^@\s]+$

And for accepting only one period [external edit: not recommended, does not match valid email adresses]:

^[^@\s]+@[^@\s\.]+\.[^@\.\s]+$
Blackbam
  • 17,496
  • 26
  • 97
  • 150
Guffa
  • 687,336
  • 108
  • 737
  • 1,005
  • 12
    IF you take a look at what is coming down the pipe with RFC 6531 and if you take a hard look at RFC 3696 you'll probably come to the conclusion that the only way to validate an email is to send a confirmation email. I think the real focus with using regex's on email addresses should be with helping the user prevent typos and that is where simple regex's like this come into play. – Bob Barker Sep 29 '14 at 01:22
  • Perfect, @AmoebaMan17. RegEx can validate the **format** of the email address, it can't validate the **content** of the email address. That said, yours validates the format completely. Sending the email is the only way to validate the content. – Craig Jan 20 '15 at 17:05
  • won't work on `test@test.com` ? – Abdul Hameed Jul 16 '18 at 13:07
  • 2
    To prevent the string from ending with a period, I made this modification: ^[^@\s]+@[^@\s]+\.[^@\.\s]+$ – fyrite Sep 24 '18 at 21:08
  • I'd suggest stripping AmoebaMan17's version of the initial ^ and terminal $ so that leading/trailing whitespace doesn't stop you extracting the email i.e. `[^@\s]+@[^@\s]+\.[^@\s]+` – Tom Wagstaff Jul 03 '19 at 13:04
  • The last regex doesn't match `foo@mail.example.com` – semicolon Aug 23 '20 at 21:57
  • 6
    Yeah, don't use the last one. It doesn't match a lot of valid options. me@provider.co.uk for example. – s.meijer Sep 12 '20 at 09:58
  • 1
    I would suggest using @fyrite version, or mine which is the same but also don't allow a dot directly after '@'. `^[^@\s]+@[^@\s.]+\.[^@\s.]+$` – Adnan Aug 15 '22 at 11:43
122
^\S+@\S+$
chaos
  • 122,029
  • 33
  • 303
  • 309
  • 3
    This will match invalid addresses. Any regex will, but this one will match common mis-spellings such as test@stackoverflow..com (note the double dots.) Please provide a better example. – Mihai Limbășan Apr 12 '09 at 21:29
  • 75
    It's supposed to be a maximally simple, very rough filter, and I don't see why doubled periods are privileged over all the other screwups with similar complexity costs to cover them. – chaos Apr 12 '09 at 21:33
  • 2
    Yeah, if you don't want to use the full validating regex, this is a good simple approximation – rampion Apr 12 '09 at 21:36
  • This is a very comon screwup, but if you think the fractional microsecond cost of a better regex is not worth it... *shrug again* Retracted downvote, enjoy. – Mihai Limbășan Apr 12 '09 at 21:36
  • Heh, thanks. It's not the fractional microsecond, it's the visual/syntactic complexity of the expression; my impression was that the OP was wanting to minimize that. – chaos Apr 12 '09 at 21:56
  • 11
    +1 Trying to “validate” an e-mail address fully via regex is a fool's errand. This works to catch the simplest mis-types; the rest can be found by trying to send the mail. The above also allows Unicode (->Punycode) domains, where most “clever” regexes fail it. – bobince Apr 12 '09 at 22:11
  • +1 because it is "something simple, not the best" – dfa Apr 13 '09 at 00:36
  • I'm picky, but a dot in the domain part is not required. And this one looks simple, but its not better than no test at all. Its not much better than string search for an @ character. Check JP's answer for a _correct_ one. – Frunsi Dec 28 '09 at 12:54
  • Edited to remove the dot, since yeah, you can have an email address on a TLD, and I vaguely feel that the "maximum simplicity" answer (one more time, @frunsi, he didn't ask for *good*, he asked for *simple*, and unlike JP I answered *the question asked*) may throw lots of false positives, but it shouldn't throw any false negatives. – chaos May 25 '11 at 04:01
  • 1
    I personally would extend this to ^\S+@\S+.\S+$ – Relequestual Jan 15 '15 at 12:10
  • @Relequestual: That will throw false negatives, because any DNS name, including a bare TLD, can have email addresses on it. – chaos Jan 15 '15 at 15:44
  • @chaos Interesting. According to this, bare TLD's are banned by ICANN https://www.icann.org/news/announcement-2013-08-30-en Can you provide any real world examples of where DNS names are used for email? – Relequestual Jan 16 '15 at 10:21
  • @Relequestual: Try reading that for the loopholes instead of your preferred interpretation, and see https://tools.ietf.org/html/rfc7085#section-2.3 . – chaos Jan 21 '15 at 19:22
  • 2
    Pretty old at this point, but you might consider start/end of string, rather than start/end of line [like so](http://rubular.com/r/3L4drZmgoz) `\A\S+@\S+\z` – brad Jun 15 '15 at 13:25
  • 1
    @brad: The `^` and `$` means start and end of the string unless you specifically use the multiline option. – Guffa Apr 06 '16 at 14:31
7

^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+.[a-zA-Z0-9-.]+$

  • Only 1 @
  • Several domains and subdomains
coto
  • 2,255
  • 1
  • 19
  • 32
  • 4
    This will fail on `O'Connor@example.com` and lots of others. Apostrophes and other characters are more common in emails than you think, especially outside the US. I advise not using this regex. – degenerate Apr 22 '21 at 17:51
4

I think this little tweak to the expression by AmoebaMan17 should stop the address from starting/ending with a dot and also stop multiple dots next to each other. Trying not to make it complex again whilst eliminating a common issue.

(?!.*\.\.)(^[^\.][^@\s]+@[^@\s]+\.[^@\s\.]+$)

It appears to be working (but I am no RegEx-pert). Fixes my issue with users copy&pasting email addresses from the end of sentences that terminate with a period.

i.e: Here's my new email address tabby@coolforcats.com.

1

Take your pick.

Here's the one that complies with RFC 2822 Section 3.4.1 ...

(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])

Just in case you are curious. :)

Community
  • 1
  • 1
JP Alioto
  • 44,864
  • 6
  • 88
  • 112