Email validation in Actionscript 3

Email is surprisingly hard to validate. Looking at how flex does it, one wonders if it couldn't be easier (and better).

I've been playing with flex lately and I though the best way to get the hang of it was to use it in small pieces. One of the most obvious places for using the flex framework seemed form validation. Since it is enterprise ready, validation must be top notch. And then I stumbled upon the monstrous 500+ lines of code mx.validators.EmailValidator class. Sure, it's doing a lot more than checking if a String is a valid email address. It will tell you if there is too litle at signs, too many at signs, and many other possible combination of invalid email addresses.

Wow! This is such a case of over engineering! If someone is typing a email addresses on a form, they probably know what it looks like. I've never seen such detailed error messages, and honestly, that's a good thing. Using the EmailValidator from flex will weight 6kb of sources. If it's that complex it sure will do a great job at validating emails, you'd think. But shockingly, the email validation is a great hack: no regex just a bunch of string searches such as:

1
2
var ampPos:int = emailStr.indexOf("@");
if (ampPos == -1)
And so forth. Ouch! Regexes can be daunting and intimidating, but sometimes avoiding a regex will cause a lot more trouble that it will save you. This is an invalid email address, according to the flex validator: "arthur+". Not only plus signs are legal at the address part, but they're very useful. If your mail server is configured correctly (and unfortunately many aren't) and you have an email account such as "", then you can use many variations of "arthur+" and still get those delivered to you. This is great for checking if a company has passed your personal information to others, or generating automated rules for filtering or forwarding. Gmail allows that, and I use it all the time.

Getting email validation right is tough. Zeh couldn't get his email to be accepted in so many places he had to change it. The spec allows many variations such as: arthur'@' and other bizarre cases. You don't have to allow them all, but you should definitely allow for the most common ones. Flex, being a framework for client side programming, should really do a better job at validating emails.

In the end you have a heavy, tightly coupled framework that deals with really edge cases (such as warning a user that his email has too many at signs!) but not taking enough care to validate emails correctly.

I've hacked an EmailValidator class that is much more light weight and hopefully gets most emails right. You can download it here. Sample usage below:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
/* https://stimuli.com.br/, Arthur Debert
*/
package br.com.stimuli.mona.validators{
    /*// usage
    * import br.com.stimuli.mona.validators.EmailValidator;
    * 
    * // will return a boolean
    * EmailValidator.isValidEmail("");
    * 
    * // if you'd rather validate an catch an error you can use:
    * EmailValidator.validate("");
    * 
    * // You can also specify which class you;d rather throw an error in case the email isn't valid:
    * EmailValidator.validate("bad@", MyErrorClass);
    * 
    * // You can also specify the message to be passed to the error class
    * EmailValidator.validate("bad@", Error, "Bad email!");
    * 
    * // If you have an input where people can type a few email addresses you can validate a whole list
    * // This will separate and trim each word of text:
    * EmailValidator.isValidEmailList(", ");
    * 
    * // If you specify an arbitrary separator to test. This will return true:
    * EmailValidator.isValidEmailList(";  ", ";");
    * // But using the default (",") separator, this will return false:
    * EmailValidator.isValidEmailList(";  ",);
    */
    public class EmailValidator{

        public function EmailValidator() {
            throw new Error("The EmailValidator class is not intended to be instantiated.");
        }
        
        // permissive, will allow quite a few non matching email addresses
        public static const EMAIL_REGEX : RegExp = /^[A-Z0-9._%+-]+@(?:[A-Z0-9-]+\.)+[A-Z]{2,4}$/i;

        /** Checks if the given string is a valid email address.
        *   email The email address as a String
        *   True if the given string is a valid email address, false otherwise.
        */
        public static function isValidEmail(email : String) : Boolean{
            return Boolean(email.match(EMAIL_REGEX));
        }
        
        /* Splits a string with the separator character, strips white characters and checks if all of them are valid
        */
        public static function isValidEmailList(emailList : String, separator : String = ",") : Boolean{
            var addresses : Array = emailList.split(separator);
            for each (var email : String in addresses){
                if (!isValidEmail(email.replace(/\s/, "")))return false;
            }
            return true;
        }
        
        public static function validate(email : String, errorClass : Class = null, errorMessage : String = "Invalid e-mail address.") : void{
            if (isValidEmail(email) )return;
            errorClass = errorClass || Error;
            throw new errorClass(errorMessage)
        }
    }
}

If you catch valid emails that this regex is complaining about, please let me know. you can also get the full scoop on the nitty gritty of email validation here.

getting a third opinion

1.
Marian M.Bida says at

Just run itno this problem, this is my first day in as3 world, thank you.

2.
jkjk;l says at

jk;jkl

3.
Chris Ellem says at

Great AS3 example of how to loop over a string...very useful piece of code...great work Arthur...and thanks for sharing.

4.
noponies says at

Nice work.

5.
jack as3 says at

Thanks very much but... why that execute the method and don't send a boolean ?: trace(EmailValidator.isValidEmail(""));

I would affect the error message to a textfield and display it in (without create a class just for it) but your fonction only return intern chek ... for example :

if (EmailValidator.isValidEmail(textFieldEmail.text)==false){ textFieldError = "my message"; }

don't work :/ thanks

6.
Rajiv Ranjan Kumar says at

Hi Dear,

Thank you for this solution.

Rjiv Ranjan Kumar

7.
Felipe Ziliotti says at

Greaaaatttt job!

Tk's for shareeee Arthur!!

:)

8.
Michael Parisi says at

Awesome. Thankz

9.
says at

That's greate, Email validation is a small task, but here they are using so many lines of code.

Thanks, Uday

10.
John says at

Needed this solution quicky and it works perfectly! Thanks for saving my sanity. :)

11.
Timo Virtanen says at

Thanks. Works like a charm :)

12.
wyktor says at

Thanks for great job:) works perfectly

13.
Faurskov says at

Super.... =)

14.
cvbn says at

Hello, its cool!

15.
lukegill says at

I've blogged about a much easier way to validate emails in AS3. Including source .fla

Check it out : http://www.lukegill.com/blog/as3-email-validation/

16.
Dan says at

great body of work you have here Arthur!

I notice that your email validator rejects emails with 's in them. e.g. jack.o'. Since there are many Irish surnames (and in other langs I presume) written like that, I would think that would be valid?

17.
İhsan says at

Wow, This is the best pattern I've met on the web. Lukegill, the pattern is important. This works also great:

function isValidEmail(email:String):Boolean { var emailExpression:RegExp = /^[A-Z0-9._%+-]+@(?:[A-Z0-9-]+.)+[A-Z]{2,4}$/i; // this is the pattern here return emailExpression.test(email); }

Now lukegill, your pattern accepts nonsense like . The pattern here only accepts dots seperated with valid characters instead:

18.
Dan says at

Hi, back again. How about accented characteds, cedila and other "funny" european chars? I don't know what's really valid though. Here's a little string of the ones that I think cover Spanish, Catalan, French, Italian and probably some others. ·áéíóúñàèìòùñçüïÁÉÍÓÚÀÈÌÙÒÑÇÜÏ Perhaps it'd be better to write the regexp so it excludes unwanted chars rather than only include permitted ones?

19.
Arthur Debert says at

Hi Dan.

Yeah, you do bring good points. I am not sure though, on most server configuration for non-ascii chars in the local domain part, but I suspect it's still pretty uncommon.

Will think this more throughly, though.

Best regards

20.
Chrome says at

or you can take this tiny function instead:

function isValidEmail(email:String):Boolean { var emailExpression:RegExp = /^[a-z][w.-]+[w.-]+.[w.-]*[a-z][a-z]$/i; return emailExpression.test(email); } trace(isValidEmail(''));//true trace(isValidEmail('all'));//false

21.
senthil says at

Thanks a lot!!

22.
Adrian Parr says at

: When I run your code I get the following in the output window ...

false false

Rather than ...

true false

23.
ravi says at

many thanks man.

24.
J. Taniguchi says at

Hi there,

great job but unfortunately the download link it's broken....

Cheers!

25.
Dariusz says at

I have tested the pattern and found a bug. It allows the more then 4 letters for top level domain.

I have found another /^[A-Z0-9._%+-]+@(?:[A-Z0-9-]+.)+[A-Z]{2,6}$/i

The difference is the slash before dot. This pattern also allows .museum top level domain. Source is http://www.regular-expressions.info/email.html

Best Regards

26.
Simon Dion says at

Nice thanks !

27.
Pouyan Savoli says at

DariusZ I just used your new code but it allows me so email without a .com for example

28.
Tyler Reid says at

This looks like a fabulous resource. However, the download link is broken.

Have the last word





posted by
Arthur Debert

on

Tagged with:

28 comments so far.
Say something

Other months availabe in 2007

The complete blog archive

The latest entries

Subscribe to comments on this entry: rss feed

Cloud me:

Feeds: Entries rss feed Linksrss feed Worksrss feed

A Django joint. hosted on Slicehost