29

I got a Regex that validates my mail-addresses like this:

([a-zA-Z0-9_\-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)

This works perfectly fine, but only allows one e-mail to be entered. Now I wanted to extend that and allow multiple mail-addresses to be added (just like MS Outlook, for example) with a semicolon as a mail-splitter.

mail1@tld.com;mail2@tld.com;mail3@tld.com

Now I've searched and found this one:

([A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4}(;|$))

This works on one point, but sadly requires a semicolon at the end of a mail:

mail1@tld.com;

This is not what I want when the user only enters one e-mail.

How can I extend my regex above (the first one) to allow multiple mail-addresses to be added while let them be splitted through a semicolon?

SeToY
  • 5,317
  • 10
  • 45
  • 89
  • 1
    You could write a function that will do the splitting for you, and then perform the regex on each individual email. – Matthew Mar 21 '12 at 17:04
  • 1
    possible duplicate of [How to use a regular expression to validate an email addresses?](http://stackoverflow.com/questions/201323/how-to-use-a-regular-expression-to-validate-an-email-addresses) - link to **the regular expression** - http://ex-parrot.com/~pdw/Mail-RFC822-Address.html (about one page long). – Alexei Levenkov Mar 21 '12 at 17:10
  • 2
    don't forget, that email addresses can be very hard to validate, eg, foo@host is a valid address – IanNorton Mar 21 '12 at 17:17
  • http://stackoverflow.com/questions/9780582/how-to-validate-multiple-emails-using-regex/9808247#9808247 – kirilloid Mar 21 '12 at 17:25

10 Answers10

64

This is your original expression, changed so that it allows several emails separated by semicolon and (optionally) spaces besides the semicolon. It also allows a single email address that doesn't end in semicolon.

This allows blank entries (no email addresses). You can replace the final * by + to require at least one address.

(([a-zA-Z0-9_\-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)(\s*;\s*|\s*$))*

If you need to allow comma, apart from semicolon, you can change this group:

(\s*;\s*|\s*$)

by this one:

(\s*(;|,)\s*|\s*$)

Important note: as states in the comment by Martin, if there are additional text before or after the correct email address list, the validation will not fail. So it would work as an "email searcher". To make it work as a validator you need to add ^ at the beginning of the regex, and $ at the end. This will ensure that the expression matches all the text. So the full regex would be:

^(([a-zA-Z0-9_\-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)(\s*;\s*|\s*$))*$

You can add an extra \s* after the ^ to tolerate blanks at the beginning of the list, like this. I.e. include ^\s* instead of simply ^ The expression already tolerates blanks at the end as is.

Michiel
  • 3,782
  • 3
  • 28
  • 40
JotaBe
  • 34,736
  • 7
  • 85
  • 109
  • 1
    Hmm this looks promising, but requires the user to ALWAYS add a semicolon after a mail-address, even if only one has been specified – SeToY Mar 21 '12 at 17:42
  • 1
    No, it doesn't requiere a semicolon at the end at all! The last group (\s*;\s*|\s*$), accepts two possibilities: 1) \s*;\s*, whis is a semicolon with optional spaces before or after it, and 2) \s*$ which is the end of the line with optional spaces before it. This requires the semicolon if it's not the end (because there are more than one address), but allows no semicolon if it's the end. I've tested it. If it doesn't work for you get sure to trim spaces at the beggining and end of the expression. It can also have to do with regex options. Let me know if I can be of further help. – JotaBe Mar 21 '12 at 18:28
  • 4
    Here is a slightly modified version that will provide a single capture group matching the full match. It is also anchored so the entire input must match the pattern, which is helpful since you're validating input. `^((?:(?:[a-zA-Z0-9_\-\.]+)@(?:(?:\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(?:(?:[a-zA-Z0-9\-]+\.)+))(?:[a-zA-Z]{2,4}|[0-9]{1,3})(?:\]?)(?:\s*;\s*|\s*$))*)$` – Ricky Smith Jan 28 '13 at 20:24
  • 1
    I try to use it in the validation by regex in mvc5 and it seems to be broken fr some reason. Anyone tried to do that as well? – Ricker Silva Feb 07 '14 at 18:45
  • What is exactly failing? Does a dummy regex, like ".*" wor for you? If so, which case is failing for you? This regex works in C# as well as in JavaScript (tested on regexplanet.com) so there is no reason for it to fail in MVC. – JotaBe Feb 10 '14 at 10:51
  • (\s*(\r\n|,\n)\s*|\s*$) - for multiline – Misi May 21 '14 at 10:01
  • This regex is correct for pulling a string of emails out of text, but if you use it for validation, it will not reject malformed email addresses. The regex needs to begin with ^ and end with $ to do that -- otherwise it will "successfully" match 0 instances of a correct email address before or after the non-email text, meaning you will see IsMatch coming back true, but Match will be empty. – Martin Jun 15 '16 at 21:40
  • Great work! Recommend that you update this for the new TLDs - many are longer than 4 characters. – Brian MacKay Sep 29 '16 at 14:52
  • @NikhilVC Please, see the "important note". In other words, add ^at the start and $ at the end. – JotaBe Feb 03 '17 at 12:04
7

Old post - needed the same RegEx. The accepted answer did not work for me, however, this did.

^(|([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})+)*$

Retrieved from this post, however, the accepted answer did not work either, but the Regex on the link WITHIN the post did.

abc@abc.com - validates

abc@abc.com;123@qwer.com - validates

abc@abc.com; - does not validate

empty string - validates

If you want to validate against an empty string, then remove the | at the beginning of the regex

Community
  • 1
  • 1
Rob Scott
  • 7,306
  • 4
  • 34
  • 57
3

Please try this

^([\w+-.%]+@[\w-.]+\.[A-Za-z]{2,4};?)+$
PraveenVenu
  • 7,825
  • 4
  • 28
  • 38
2

Why not just split on the semicolon and then validate each potential email address using your existing regexp ? Writing one huge regexp is going to be very difficult and a maintenance nightmare, I suspect.

Brian Agnew
  • 254,044
  • 36
  • 316
  • 423
  • It's not possible to write C# Code to split the string, the regex always gets the entire string to check. Is there a regex-way to split? – SeToY Mar 21 '12 at 17:13
  • 2
    @SeToY, C# is Turing-complete, so it should be perfectly possible to write code that splits string, in fact String.Split does exactly that. – Alexei Levenkov Mar 21 '12 at 17:16
  • @Alexei Levenkov That's not the point, I know how to split strings with C#, but I am not allowed to :) – SeToY Mar 21 '12 at 17:17
  • 1
    @SeToY please understand that "not possible" and "not allowed" have entirely different meanings - confusing them is a waste of many people's time – Code Jockey Mar 21 '12 at 17:22
  • @SeToY, if you have particular restrictions - you should state them in your question. Also if it is homework of some sort - make sure to add "homework" tag so people have better idea what type of answer would work best. – Alexei Levenkov Mar 21 '12 at 17:23
  • @Alexei Levenkov: Haha, I take this as a compliment - way too old to be in school these days :P – SeToY Mar 21 '12 at 17:31
1

In an old regex book they stated that you cannot write a regex to match all valid email addresses (although you can come close).

Here is a website dealing with regex and email addresses.

I would recommend that you split the string at ; and , boundaries and check each email address separately for being valid/invalid with your regex.

Uwe Keim
  • 36,867
  • 50
  • 163
  • 268
1

Domain names are actually way more complex. For example, most TLDs are now using Unicode domain names, which are quite common in Europe. Consider the email address mailtest@пример.испытание, which is actually perfectly valid (though they can always be transcribed to the old form - mailtest@xn--hxajbheg2az3al.xn--jxalpdlp). This means that it is probably easier to define what characters are not valid for a domain name. See ICANNs.

In addition, the TLDs are also not strictly part of the set you have defined, see IANAs list of valid TLDs. For example, example@example.travel is a valid email address.

In short, to validate email addresses, consider going with an established third party library, unless you are dealing with a limited special case.

Now for your original question, I would recommend a preprocess stage where you split on reasonable delimiters (',' and ';'), trim whitespace (at least if dealing with user input) and validate each entry.

Krumelur
  • 27,311
  • 6
  • 71
  • 108
0

Something I've written in my days. Basic email validation is taken from practical implementation of RFC 2822

^([a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])(;)?)+$

matches emails with ; separator

I you want more separators, swap (;)? with [;,|]? within the [] brackets.

Jeremy Hodge
  • 480
  • 2
  • 10
Shuffler
  • 163
  • 2
  • 10
0

Below is my solution and it worked as expected for me:

      var emailReg = new RegExp(/^([A-Z0-9.%+-]+@@[A-Z0-9.-]+.[A-Z]{2,6})*([,;][\s]*([A-Z0-9.%+-]+@@[A-Z0-9.-]+.[A-Z]{2,6}))*$/i);
  var emailText = $('#email').val();

  if (!emailReg.test(emailText)) {
      alert('Wrong Email Address\Addresses format! Please reEnter correct format');
        return false;
    }
}
Qasim Bataineh
  • 589
  • 5
  • 3
  • The question was about the actual regular expression rather than an JavaScript implementation. You could improve your answer by putting emphasis on the regex you used. – dakab Dec 22 '15 at 19:38
0

Here is a simple Program which does this for you without using the Regular Expression.Well Actually it does use a regular expression but we don't have to worry about it how it looks .php does this for us .

public function test_reg()

{

   $email_list = '';

        $array = explode(";",$email_list);

        foreach ($array as $value)
         {
            $value;

            if (!filter_var($value, FILTER_VALIDATE_EMAIL) === false)
             {
                 $msg =  "Email List Contains  valid email addresses.";
              } 
            else
             {
                 $msg ="Your Email list contains an invalid email at. &nbsp&nbsp &nbsp".$value;
                 break;
             }  
         }

                echo $msg;



}

You have to separate your emails by a semi colon.

0

This is a very old question, but I figured I'd share my C# code.

I decided to parse by the semicolon then check each email individually:

string toAddress = "testemail@gmail.com;test2@testing.com;";
Regex rgx = new Regex(
    @"^[_a-z0-9-]+(\.[_a-z0-9-]+)*(\+[a-z0-9-]+)?@[a-z0-9-]+(\.[a-z0-9-]+)*$");

List<string> emailArray = new List<string>();

if(toAddress != null && toAddress != "")
{
    if (toAddress.IndexOf(";") != -1)
    {
        emailArray = toAddress.Replace(" ","").Split(';').ToList();
    }
    else
    {
        emailArray.Add(toAddress);
    }

    foreach (string email in emailArray)
    {
        if (rgx.IsMatch(email ?? ""))
        {
            SendEmail(email, subject, body);
        }
    }
}
Uwe Keim
  • 36,867
  • 50
  • 163
  • 268
Jacob Morris
  • 470
  • 1
  • 4
  • 14