2

I need a regular expression that will accept well-formed emails in several formats (see below) that will be input in a comma-separated list. I have the basic email address validation regex,

^[\w\d._%+-]+@(?:[\w\d-]+\.)+(\w{2,})(,|$) 

which can handle test cases A and B, but not the others. I also tried

^(\<)?[\w\d._%+-]+@(?:[\w\d-]+\.)+(\w{2,})(\>)?(,|$)

which was able to handle A, B, and C, but only validated the first email address in each of test cases D and E. I haven't even gotten to testing a regex for format 3.

tl;dr Need a regex that will validate email addresses 1, 2, and 3.

Good website to test your regular expressions: Online Javascript Regex Tester

Data

Test Cases
A. [email protected]
B. [email protected], [email protected]
C. <[email protected]>, [email protected]
D. <[email protected]>, <[email protected]>
E. [email protected], <[email protected]>

Email Address Formats
1. [email protected]
2. <[email protected]>
3. "xyz"<[email protected]>

EDIT

I flagged this as a possible duplicate of:

Validate email address in JavaScript?

which, in turn, seems to be a duplicate of:

Using a regular expression to validate an email address

both of which contain much discussion on the validity of regex as email validation. However, the top-voted regexes provided don't seem to do quite what I want so I don't consider this answered yet.

15
  • btw , whats wrong with [email protected]? Commented Jun 20, 2012 at 0:47
  • regex is not the best tool to fully parse/validate all legal email addresses. Google will offer you many examples of other ways to do this. Commented Jun 20, 2012 at 0:47
  • @EswarRajeshPinapala not sure what you mean by "what's wrong with" it. Commented Jun 20, 2012 at 1:00
  • 1
    Why does it have to be done with regex? Is this homework? Commented Jun 20, 2012 at 1:12
  • 1
    It seems this question has already been asked and discussed here: Validate email address in Javascript? and from one of those answers is this reference that discusses the details of using a regex: regular-expressions.info/email.html Commented Jun 20, 2012 at 6:42

4 Answers 4

3

None of the links or answers provided was the best answer for this question. Here's what solved it:

/*
* regex checks: must start with the beginning of a word or a left caret
* must end with either the end of a word or a right caret
* can handle example.example.com as possible domain
* email username can have + - _ and .
* not case sensitive
*/
var EMAIL_REGEX = /(\<|^)[\w\d._%+-]+@(?:[\w\d-]+\.)+(\w{2,})(\>|$)/i;  
var emails = emailList.trim().split(',');  
var validEmails = [];  
var invalidEmails = [];  

for (var i = 0; i < emails.length; i++) {  
    var current = emails[i].trim();
    if(current !== "") {
        //if something matching the regex can be found in the string
        if(current.search(EMAIL_REGEX) !== -1) {
            //check if it has either a front or back bracket
            if(current.indexOf("<") > -1 || current.indexOf(">") > -1) {
                //if it has both, find the email address in the string
                if(current.indexOf("<") > -1 && current.indexOf(">") > -1) {
                    current = current.substr(current.indexOf("<")+1, current.indexOf(">")-current.indexOf("<") -1);
                } 
            } 
        }
        if(EMAIL_REGEX.test(current)) {
            validEmails.push(current);
        } else {
            invalidEmails.push(current);
        }
    }               
}
Sign up to request clarification or add additional context in comments.

Comments

2

This validateEmail function will check for the basic syntax of an email address ([email protected]). The included ifs will check for the alternate formatting (<[email protected]>, 'xyz' <[email protected]>) and only validate the actual email portion. Items with only < or > are deemed invalid for poor formatting ([email protected]>), same with any emails lacking the basic structure required (invalidExample.com).

var emailList = "[email protected],<[email protected]>,'xyz' <[email protected]>,invalidExample.com,[email protected]>,'Still93e-=48%5922=2 Good' <[email protected]>";
var emails = emailList.split(",");

//Loop through the array of emails
for (var i = 0; i < emails.length; i++) {
    var isValid = 1;
    var cur = emails[i];

    // If it has a < or a >,
    if( cur.indexOf("<") > -1 || cur.indexOf(">") > -1 ){
        // Set it invalid
        isValid = 0;
        // But if it has both < and >
        if( cur.indexOf("<") > -1 && cur.indexOf(">") > -1 ){
            //Set it valid and set the cur email to the content between < and >
            isValid = 1;
            cur = cur.substr(cur.indexOf("<")+1, ( cur.indexOf(">") - cur.indexOf("<") - 1 ));
        }
    }
    //Run the validate function
    if ( !validateEmail(cur) )
        isValid = 0;

    // Output your results. valid = 1, not valid = 0
    alert("Orig: "+emails[i] +"\nStripped: "+cur+"\nIs Valid: "+isValid);

}

function validateEmail(curEmail){
    var emailValid = /.*\@.*\..*$/g;
    return (curEmail.test(emailValid));
}

jsFiddle

2 Comments

Your regex didn't do the checks I wanted, but I like the bracket checks you did.
That's the nice part about this, you can change out the regex to whatever email verification you want. The the non-email parts don't seem to need to be validated, so any solid email validating regex will work.
1

It would be simpler to first split the comma-separated list into an array, and validate each member of the array individually. That would make the regex easier to write (and read and maintain), and also give you the ability to provide specific feedback to the user who entered the list ("the 3rd email address is invalid").

So assuming you did that with a split

var bits = csv.split(',');

Iterate through the bits array

for (var i = 0; i < bits.length; ++i) {
  if (!validateEmail(bits[i])) {
    alert("Email #" + (i+1) + " is bogus");
  }
}

Then for the regex, something like this will capture 2 and 3

(\"[a-z0-9\s]+\"\s+)?\<[\w\d._%+-]+@(?:[\w\d-]+\.)+(\w{2,})\>

And you can use the simpler one to capture simple email addresses without the < or the name in quotes in front of it.

A single regex will not necessarily run any faster than two if tests, especially if you short-circuit the or by putting the more likely one first. It's also harder to read and maintain. Lastly it's extra tricky because you need a lookahead: the final > is only ok if the string ahead of the email address includes a < right before the first character of the email.

So my $0.02 = not worth it. Just do two regexes.

2 Comments

You might be right about needing to do more than one. However, the one you provided also allows things like "xyz" to pass, and I don't want that.
Also, totally fine with splitting it first.
0

Will something like this help?

I have tested 2. and 3., and it detects both the patterns.

var isEmail_re       = /^\s*[\w\-\+_]+(\.[\w\-\+_]+)*\@[\w\-\+_]+\.[\w\-\+_]+(\.[\w\-\+_]+)*\s*$/;

function isEmail (s) {
   return String(s).search (isEmail_re) != -1;
}

alert(isEmail ('"xyz"<[email protected]>'));

http://jsfiddle.net/epinapala/BfKrR/

1 Comment

This doesn't seem to address any of the examples I provided. At least, not from testing it using the link I provided in my OP.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.