Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Allow + in regex email validate email [duplicate]

Regex is blowing my mind. How can I change this to validate emails with a plus sign? so I can sign up with [email protected]

if(!preg_match("/^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*$/i", $_GET['em'])) {
like image 241
wesbos Avatar asked Mar 31 '11 16:03

wesbos


3 Answers

It seems like you aren't really familiar with what your regex is doing currently, which would be a good first step before modifying it. Let's walk through your regex using the email address [email protected] (in each section below, the bolded part is what is matched by that section):

  1. ^ is the start of string anchor. It specifies that any match must begin at the beginning of the string. If the pattern is not anchored, the regex engine can match a substring, which is often undesired.

    Anchors are zero-width, meaning that they do not capture any characters.

  2. [_a-z0-9-]+ is made up of two elements, a character class and a repetition modifer:

    • [...] defines a character class, which tells the regex engine, any of these characters are valid matches. In this case the class contains the characters a-z, numbers 0-9 and the dash and underscore (in general, a dash in a character class defines a range, so you can use a-z instead of abcdefghijklmnopqrstuvwxyz; when given as the last character in the class, it acts as a literal dash).
    • + is a repetition modifier that specifies that the preceding token (in this case, the character class) can be repeated one or more times. There are two other repetition operators: * matches zero or more times; ? matches exactly zero or one times (ie. makes something optional).

    (captures john[email protected])

  3. (\.[_a-z0-9-]+)* again contains a repeated character class. It also contains a group, and an escaped character:

    • (...) defines a group, which allows you to group multiple tokens together (in this case, the group will be repeated as a whole).
      Let's say we wanted to match 'abc', zero or more times (ie. abcabcabc matches, abcccc doesn't). If we tried to use the pattern abc*, the repetition modifier would only apply to the c, because c is the last token before the modifier. In order to get around this, we can group abc ((abc)*), in which case the modifier would apply to the entire group, as if it was a single token.
    • \. specifies a literal dot character. The reason this is needed is because . is a special character in regex, meaning any character. Since we want to match an actual dot character, we need to escape it.

    (captures john.robert.smith@mail.com)

  4. @ is not a special character in regex, so, like all other non-special characters, it matches literally.
    (captures john.robert.smith@mail.com)

  5. [a-z0-9-]+ again defines a repeated character class, like item #2 above.
    (captures john.robert.smith@mail.com)

  6. (\.[a-z0-9-]+)* is almost exactly the same pattern as #3 above.
    (captures john.robert.smith@mail.com)

  7. $ is the end of string anchor. It works the same as ^ above, except matches the end of the string.


With that in mind, it should be a bit clearer how to add a section with captures a plus segment. As we saw above, + is a special character so it has to be escaped. Then, since the + has to be followed by some characters, we can define a character class with the characters we want to match and define its repetition. Finally, we should make the whole group optional because email addresses don't need to have a + segment:

(\+[a-z0-9-]+)?

When inserted into your regex, it'd look like this:

/^[_a-z0-9-]+(\.[_a-z0-9-]+)*(\+[a-z0-9-]+)?@[a-z0-9-]+(\.[a-z0-9-]+)*$/i
like image 145
Daniel Vandersluis Avatar answered Sep 27 '22 16:09

Daniel Vandersluis


Save your sanity. Get a pre-made PHP RFC 822 Email address parser

like image 21
Tony Miller Avatar answered Sep 27 '22 16:09

Tony Miller


I've used this regex to validate emails, and it works just fine with emails that contain a+:

/^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
like image 26
Matt Ball Avatar answered Sep 27 '22 15:09

Matt Ball