18

i am looking for a regular express to validate a list of email addresses like the following

test1@abd.com;test.test@abc.com;test3@test.com

and

test1@abd.com;test.test@abc.com;test3@test.com;

optional ";" at the end of the list.

thanks,

Eatdoku
  • 6,569
  • 13
  • 63
  • 98

6 Answers6

24

Update

Don't. Split on the delimiter and validate each one separately. I would also recommend setting a match timeout and/or non-backtracking flag to prevent excessive CPU usage when matching.


Original Answer

From: http://regexlib.com/RETester.aspx?regexp_id=1007

^(([a-zA-Z0-9_\-\.]+)@([a-zA-Z0-9_\-\.]+)\.([a-zA-Z]{2,5}){1,25})+([;.](([a-zA-Z0-9_\-\.]+)@([a-zA-Z0-9_\-\.]+)\.([a-zA-Z]{2,5}){1,25})+)*$
Evan Mulawski
  • 54,662
  • 15
  • 117
  • 144
  • I dropped this one into Expresso and it complained that it couldnt parse it – rtpHarry Dec 04 '10 at 01:31
  • At first glance, this will allow any number of email addresses, without any separators, followed by any number of semicolons each followed by at least one character. So this would be valid: "example@domain.comexample2@domain.com;$;8;asdf" – eyelidlessness Dec 04 '10 at 01:38
  • 1
    The entire expression did not post properly. The correct expression is on the site li ked in the post. – Evan Mulawski Dec 04 '10 at 02:46
  • @Evan: it didn't post properly because you used `` tags instead of SO's own formatting capabilities. You should try to use the SO version whenever you can; it's quite good. – Alan Moore Dec 04 '10 at 08:04
  • @Alan: Because I posted with an iPad, I did not have access to the formatting tools. – Evan Mulawski Dec 04 '10 at 14:25
  • 1
    Evan: Does iPad not let you insert four spaces at the beginning of a line? I see now that iPad is backtick-challenged, but all other SO markup can be typed in manually. And there seem to be some workarounds for the backtick thing: http://meta.stackoverflow.com/search?q=iPad – Alan Moore Dec 04 '10 at 19:17
  • what happen i would like to allow an optional ";" at the end of the email list? – Eatdoku Dec 06 '10 at 22:11
  • add [;]{0,1} at the end before $ to allow optional ";" at the end of the email list. – Eatdoku Dec 06 '10 at 23:06
  • That certainly does not look RFC compliant to me. – tchrist Feb 01 '11 at 00:38
  • -1 .... this produces a mess when I test it against a@b.com at: http://www.regular-expressions.info/javascriptexample.html – dsdsdsdsd Nov 13 '13 at 08:52
  • 2
    i found this issue At first glance, this will allow any number of email addresses, without any separators, followed by any number of semicolons each followed by at least one character. So this would be valid: "example@domain.comexample2@domain.com;$;8;asdf" .how to fix this.any help – Coder Jan 27 '17 at 04:51
  • @NikhilVC: You may want to just split the string on a separator of your choice and validate each address individually. – Evan Mulawski Jan 27 '17 at 14:58
  • 1
    @Evan Mulawski:then why would use this regex – Coder Feb 02 '17 at 13:12
  • @NikhilVC - True, I just found this error as well. To fix this, I removed the 3rd `+` sign (and the parens `()` around the first mega group), then I changed `[;.]` to a plain `;` - I actually changed that part to `;[ ]{0,1}` in case the user puts a space after the semi-colon, but this isn't necessary – Blundering Philosopher Feb 18 '18 at 12:05
  • @NikhilVC - I added this as [**an answer**](https://stackoverflow.com/questions/4351349/regular-expression-for-delimited-email-address/48851660#48851660) below - Hopefully it works for you. – Blundering Philosopher Feb 18 '18 at 12:28
7

“You call that a knife???” —Crocodile Dundee

Actually, all those are very poor patterns for matching a mail address. To strictly validate an RFC 5322 mail address with zero false negatives and zero false positives, you need this precise pattern:

  (?x)

  (?(DEFINE)

     (?<address>         (?&mailbox) | (?&group))
     (?<mailbox>         (?&name_addr) | (?&addr_spec))
     (?<name_addr>       (?&display_name)? (?&angle_addr))
     (?<angle_addr>      (?&CFWS)? < (?&addr_spec) > (?&CFWS)?)
     (?<group>           (?&display_name) : (?:(?&mailbox_list) | (?&CFWS))? ; (?&CFWS)?)
     (?<display_name>    (?&phrase))
     (?<mailbox_list>    (?&mailbox) (?: , (?&mailbox))*)

     (?<addr_spec>       (?&local_part) \@ (?&domain))
     (?<local_part>      (?&dot_atom) | (?&quoted_string))
     (?<domain>          (?&dot_atom) | (?&domain_literal))
     (?<domain_literal>  (?&CFWS)? \[ (?: (?&FWS)? (?&dcontent))* (?&FWS)?
                                   \] (?&CFWS)?)
     (?<dcontent>        (?&dtext) | (?&quoted_pair))
     (?<dtext>           (?&NO_WS_CTL) | [\x21-\x5a\x5e-\x7e])

     (?<atext>           (?&ALPHA) | (?&DIGIT) | [!#\$%&'*+-/=?^_`{|}~])
     (?<atom>            (?&CFWS)? (?&atext)+ (?&CFWS)?)
     (?<dot_atom>        (?&CFWS)? (?&dot_atom_text) (?&CFWS)?)
     (?<dot_atom_text>   (?&atext)+ (?: \. (?&atext)+)*)

     (?<text>            [\x01-\x09\x0b\x0c\x0e-\x7f])
     (?<quoted_pair>     \\ (?&text))

     (?<qtext>           (?&NO_WS_CTL) | [\x21\x23-\x5b\x5d-\x7e])
     (?<qcontent>        (?&qtext) | (?&quoted_pair))
     (?<quoted_string>   (?&CFWS)? (?&DQUOTE) (?:(?&FWS)? (?&qcontent))*
                          (?&FWS)? (?&DQUOTE) (?&CFWS)?)

     (?<word>            (?&atom) | (?&quoted_string))
     (?<phrase>          (?&word)+)

     # Folding white space
     (?<FWS>             (?: (?&WSP)* (?&CRLF))? (?&WSP)+)
     (?<ctext>           (?&NO_WS_CTL) | [\x21-\x27\x2a-\x5b\x5d-\x7e])
     (?<ccontent>        (?&ctext) | (?&quoted_pair) | (?&comment))
     (?<comment>         \( (?: (?&FWS)? (?&ccontent))* (?&FWS)? \) )
     (?<CFWS>            (?: (?&FWS)? (?&comment))*
                         (?: (?:(?&FWS)? (?&comment)) | (?&FWS)))

     # No whitespace control
     (?<NO_WS_CTL>       [\x01-\x08\x0b\x0c\x0e-\x1f\x7f])

     (?<ALPHA>           [A-Za-z])
     (?<DIGIT>           [0-9])
     (?<CRLF>            \x0d \x0a)
     (?<DQUOTE>          ")
     (?<WSP>             [\x20\x09])
   )

   (?&address)  # finally, match a mail address

I discuss this in more detail in this answer.

That needs a Perl Compatible Regular Expression (PCRE) library, or Perl itself, to work properly. I cannot guarantee that perl incompatible pattern engines will correctly handle the recursion.

Community
  • 1
  • 1
tchrist
  • 78,834
  • 30
  • 123
  • 180
6

@Evan's answer is close, but the expression matches these scenarios which are invalid:

  1. a@test.comb@test.comc@test.com (no delimiters)
  2. a@test.com;b@test.com.c@test.com (period . accepted as delimiter)
  3. a@test.com;b@test.comc@test.com (only 1st delimiter matched - extension of problem #1)

To fix these (and simplify a little bit), I made these changes:

  1. Removed the 3rd + sign, and the outer parens () surrounding the first email address.
  2. Change [;.] to a plain ; delimiter - I actually changed that part to ;[ ]{0,1} because I wanted the expression to match spaces after the semi-colon delimiter.
  3. Similar to #1, remove the final + sign in the expression, and the outer parens () between the delimiter (step #2) and the final closing paren with the star after it - )*

Here is the final expression (allowing an optional space after the ; delimiter:

/^([a-zA-Z0-9_\-\.]+)@([a-zA-Z0-9_\-\.]+)\.([a-zA-Z]{2,5}){1,25}(;[ ]{0,1}([a-zA-Z0-9_\-\.]+)@([a-zA-Z0-9_\-\.]+)\.([a-zA-Z]{2,5}){1,25})*$/
Blundering Philosopher
  • 6,245
  • 2
  • 43
  • 59
  • 2
    I've upvoted as I found this helpful, but will be tweaking for my own use. Underscores aren't allowed in domains, so that's one tweak. The standards (and my employer) permits apostrophes in the local part, which are valid but very problematic for lots of systems, so I'm adding those too, and may also need to add support for some other of the rarer characters. – Steve Lovell Jul 14 '21 at 15:44
3

I use this:

^(([a-zA-Z0-9_\-\.]+)@([a-zA-Z0-9_\-\.]+)\.([a-zA-Z]{2,5}){1,25}(($)|( *;+ *$)|( *;+ *(?=[a-zA-Z0-9_\-\.]))))*$

https://regexr.com/3gth7

alexander.polomodov
  • 5,396
  • 14
  • 39
  • 46
Jck
  • 61
  • 2
  • 5
  • This one actually allows for the optional semicolon at the end, as requested in the initial question. Upvote! – Joe Coyle Sep 24 '19 at 12:39
0

I needed to allow for the presence of white space around the delimiter, so I used this modification of Evan Mulawski's answer:

^(([a-zA-Z0-9_\-\.]+)@([a-zA-Z0-9_\-\.]+)\.([a-zA-Z]{2,5}){1,25})+(\s*[;.]\s*(([a-zA-Z0-9_\-\.]+)@([a-zA-Z0-9_\-\.]+)\.([a-zA-Z]{2,5}){1,25})+)*$

Test it at: http://regexlib.com/RETester.aspx?regexp_id=13126

Tim S
  • 2,309
  • 16
  • 23
-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])+)\])
Machavity
  • 30,841
  • 27
  • 92
  • 100
  • Wow, these REs are so complex, and yours more than the others here. It would help a lot of you described what you've added and how it works. – joanis Sep 24 '21 at 14:15
  • There was a web link which presumably provided background but it was edited out by a mod. – tripleee Sep 24 '21 at 14:38
  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Sep 24 '21 at 16:05
  • The link was the source of this Reg, but a mod removed it leaving it worst even. I agree I could have added a little description but removing information just made it worst. – Jorge Cornejo Bellido Sep 25 '21 at 15:23