1

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. nora@example.com
B. nora@example.com, fred@example.com
C. <nora@example.com>, fred@example.com
D. <nora@example.com>, <fred@example.com>
E. fred@example.com, <nora@example.com>

Email Address Formats
1. xyz@example.com
2. <xyz@example.com>
3. "xyz"<xyz@example.com>

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.

Community
  • 1
  • 1
elemjay19
  • 1,126
  • 3
  • 25
  • 51
  • btw , whats wrong with xyz@example.com? – Eswar Rajesh Pinapala Jun 20 '12 at 00: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. – jfriend00 Jun 20 '12 at 00:47
  • @EswarRajeshPinapala not sure what you mean by "what's wrong with" it. – elemjay19 Jun 20 '12 at 01:00
  • @jfriend00 It's gotta be done that way for this project. Not anything I can do about it. – elemjay19 Jun 20 '12 at 01:01
  • @norabora : Were you trying to find the email addresses that use generic patterns like xyz and invalid domains like example.com? – Eswar Rajesh Pinapala Jun 20 '12 at 01:02
  • @EswarRajeshPinapala Aaaah, no. Sorry, didn't realize it could be misunderstood. Those are just the forms of the possible email inputs in the textarea I'm using. The username could be anything and the domain could be anything, so I didn't provide specific ones, but rather generic options. I want to be able to put in my email address, for example, by inputing norabora@stackoverflow.com, ``, or "Norabora"``. Does that make more sense? – elemjay19 Jun 20 '12 at 01:08
  • 1
    Why does it have to be done with regex? Is this homework? – jfriend00 Jun 20 '12 at 01:12
  • aah, now i see what you are saying. So all 1,2, and 3 should be returned as valid by your regex, is it? – Eswar Rajesh Pinapala Jun 20 '12 at 01:13
  • @jfriend00 no it's not homework, but if I were to use a tool from Google, I'd probably have to run that up the chain to make sure it's ok. Since regex can do it easily enough, it's not a big deal. There are other checks after submit that can handle whatever regex can't. – elemjay19 Jun 20 '12 at 06:01
  • @EswarRajeshPinapala yes, exactly. – elemjay19 Jun 20 '12 at 06:02
  • @norabora - I just meant to go find some prewritten javascript made for parsing RFC822 email addresses. A regex can't actually parse all legal addresses. Not sure why you'd have to run that up a pole if it comes appropriately licensed. If you only want something simple that only handles some parts of the email address spec, then a regex might do. – jfriend00 Jun 20 '12 at 06:04
  • @jfriend00 RFC822? I don't know what that is. If you have a suggestion, I'm open to it! – elemjay19 Jun 20 '12 at 06:21
  • 1
    It seems this question has already been asked and discussed here: [Validate email address in Javascript?](http://stackoverflow.com/questions/46155/validate-email-address-in-javascript) and from one of those answers is this reference that discusses the details of using a regex: http://www.regular-expressions.info/email.html – jfriend00 Jun 20 '12 at 06:42
  • @jfriend00 with all my searching for regex, that didn't even come up. Thanks! – elemjay19 Jun 20 '12 at 06:44
  • RFC822 is one of the original standards that describes the email address format. It's been superceded by enhancements like [RFC2822](http://tools.ietf.org/html/rfc2822#section-3.4.1). – jfriend00 Jun 20 '12 at 06:47

4 Answers4

2

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);
        }
    }               
}
elemjay19
  • 1,126
  • 3
  • 25
  • 51
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.

Roger BM
  • 35
  • 5
1

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

var emailList = "abc@example.com,<lmn@example.com>,'xyz' <xyz@example.com>,invalidExample.com,Nope@example.com>,'Still93e-=48%5922=2 Good' <xyz@example.com>";
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

DACrosby
  • 11,116
  • 3
  • 39
  • 51
  • Your regex didn't do the checks I wanted, but I like the bracket checks you did. – elemjay19 Jun 20 '12 at 17:53
  • 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. – DACrosby Jun 20 '12 at 20:11
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"<xyz@example.com>'));

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

Eswar Rajesh Pinapala
  • 4,841
  • 4
  • 32
  • 40
  • 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. – elemjay19 Jun 20 '12 at 01:05