So, I have this JavaScript function:
ME.Utils = {
RxEmail: new RegExp(/^(("[\w-\s]+")|([\w-]+(?:\.[\w-]+)*)|("[\w-\s]+")([\w-]+(?:\.[\w-]+)*))(@((?:[\w-]+\.)*\w[\w-]{0,66})\.([a-z]{2,6}(?:\.[a-z]{2})?)$)|(@\[?((25[0-5]\.|2[0-4][0-9]\.|1[0-9]{2}\.|[0-9]{1,2}\.))((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[0-9]{1,2})\.){2}(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[0-9]{1,2})\]?$)/i),
ValidateEmail: function(email) {
return ME.Utils.RxEmail.test(email);
},
GetEmailAddresses: function(text) {
return text.match(ME.Utils.RxEmail);
},
HasEmail: function(text) {
return ME.Utils.GetEmailAddresses != null;
}
};
ValidateEmail
works very well. However, HasEmail
and GetEmailAddresses
is not working properly.
GetEmailAdresses
always returns null
, except for when the string only contains an email address. In this case, GetEmailAdresses
returns an array not only containing the email address, but the email address ([email protected]), just the id (test) plus some unidentified etc. etc...
Can you help me figure out what's wrong in my expression?
So, I have this JavaScript function:
ME.Utils = {
RxEmail: new RegExp(/^(("[\w-\s]+")|([\w-]+(?:\.[\w-]+)*)|("[\w-\s]+")([\w-]+(?:\.[\w-]+)*))(@((?:[\w-]+\.)*\w[\w-]{0,66})\.([a-z]{2,6}(?:\.[a-z]{2})?)$)|(@\[?((25[0-5]\.|2[0-4][0-9]\.|1[0-9]{2}\.|[0-9]{1,2}\.))((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[0-9]{1,2})\.){2}(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[0-9]{1,2})\]?$)/i),
ValidateEmail: function(email) {
return ME.Utils.RxEmail.test(email);
},
GetEmailAddresses: function(text) {
return text.match(ME.Utils.RxEmail);
},
HasEmail: function(text) {
return ME.Utils.GetEmailAddresses != null;
}
};
ValidateEmail
works very well. However, HasEmail
and GetEmailAddresses
is not working properly.
GetEmailAdresses
always returns null
, except for when the string only contains an email address. In this case, GetEmailAdresses
returns an array not only containing the email address, but the email address ([email protected]), just the id (test) plus some unidentified etc. etc...
Can you help me figure out what's wrong in my expression?
Share Improve this question asked May 6, 2010 at 8:06 MickelMickel 6,6865 gold badges44 silver badges60 bronze badges 7- 1 Oh look. Someone is trying to test email addresses with a regular expression. When was the last time I saw one that succeeded? Not today, it rejects email addresses with + characters in them. – Quentin Commented May 6, 2010 at 8:13
- 7 Please stop mocking me. help me, or say nothing at all... – Mickel Commented May 6, 2010 at 8:16
- 1 @odeo, its not that simple. see ex-parrot./~pdw/Mail-RFC822-Address.html and stackoverflow./questions/201323/… and even that monster requires that some stripping is done first – Sam Holder Commented May 6, 2010 at 8:43
- 1 Questions about parsing email addresses with regex cropup here on a regular basis, and they usually have false negatives on mon address styles. I'm not mocking you, I'm expressing frustration at people failing to learn from history and making the same mistakes over and over again. Regular expressions are not suited to parsing email addresses in any depth but people insist on trying and failing again and again. Yahoo! is a huge pany who's business is built about the web, and they can't get it right: twitter./edent/status/11687784947 - but so many smaller fish think they can. – Quentin Commented May 6, 2010 at 8:51
- 1 @h2g2java: Try every few days: stackoverflow./search?q=email%20[regex]&tab=newest – Quentin Commented May 6, 2010 at 8:52
4 Answers
Reset to default 4There are a few problems.
Your regex is anchored at the start and end of the string. You should remove the
^
and$
characters from it.If you want to return only the email addresses, use non-capturing groups.
In
HasEmail()
, you're not callingGetEmailAddresses()
. You're actually checking if the value of that property is defined.
All in all, a fixed version might look like:
ME.Utils = {
RxEmail: /(?:(?:"[\w-\s]+")|(?:[\w-]+(?:\.[\w-]+)*)|(?:"[\w-\s]+")(?:[\w-]+(?:\.[\w-]+)*))(?:@(?:(?:[\w-]+\.)*\w[\w-]{0,66})\.(?:[a-z]{2,6}(?:?:\.[a-z]{2})?))|(?:@\[?(?:(?:25[0-5]\.|2[0-4][0-9]\.|1[0-9]{2}\.|[0-9]{1,2}\.))(?:(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[0-9]{1,2})\.){2}(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[0-9]{1,2})\]?)/gi,
ValidateEmail: function(email) {
// We can't do a simple test() since we're using an unanchored regex now.
var match = ME.Utils.RxEmail.match(email);
return match.length == 1 && match[0] == email;
},
GetEmailAddresses: function(text) {
return text.match(ME.Utils.RxEmail);
},
HasEmail: function(text) {
return ME.Utils.GetEmailAddresses(text) != null;
}
};
your regexp specifically matches an entire string
RxEmail: new RegExp(/^ ... $)/i),
the ^ and $ match the start and end of the input respectively. try removing those characters and see how you get on?
if (emailMatch = ME.Utils.GetEmailAddresses(myEmail))
// do stuff with emailMatch[1]
The reason you're getting multiple entries in the array when presenting it with an email address is that you have capture groups in your expression. In Javascript, the result of match is an array where index 0 is the total string matched, and then there are (optionally) additional indexes for each capture group. You can make your groups non-capturing by changing them from (...)
to (?:...)
.
As for why you're not getting the results you expect when using GetEmailAddresses
with a string containing an email address, try this instead:
GetEmailAddresses: function(text) {
var rv = [];
var match;
while (match = ME.Utils.RxEmail.exec(text)) {
rv.push(match[0]);
}
return rv.length == 0 ? null : rv;
},
See this question and answer, I can't say I know why String#match
isn't quite the same as the RegExp#exec
loop above, but it isn't.
Edit And you'll need to fix the issue that oedo pointed out as well; the RegExp needs to be allowed to match substrings.