20
\$\begingroup\$

I have a function where I validate emails via a regex. I was wondering if this is the best regex to use or if there's a better way of doing it.

Also is there a difference between this method and just setting the type="email" in the HTML form?

<form name="form" action="process_registration.jsp" onSubmit="return validateEmail()" method="POST">
        <script>
        function validateEmail(){
            var email = document.forms["form"]["Email"].value;
            var regex = /^([0-9a-zA-Z]([-_\\.]*[0-9a-zA-Z]+)*)@([0-9a-zA-Z]([-_\\.]*[0-9a-zA-Z]+)*)[\\.]([a-zA-Z]{2,9})$/;

            if(!regex.test(email)){
                alert("Enter a valid email");
                return false;
                }
        }       
\$\endgroup\$
  • 6
    \$\begingroup\$ See this StackOverflow post for more insight on using Regex to validate e-mail addresses: Using a regular expression to validate an email address - There is no way to practically validate e-mail addresses by regex alone, just send an e-mail, and see if it works. \$\endgroup\$ – rolfl Oct 9 '14 at 19:15
  • \$\begingroup\$ If you're interested in learning about frontend validations, there's this very nice project on Github called Parsley. In this file they came up with a (very large) email validation regex that may be worth a look for you. \$\endgroup\$ – Marcus Vinícius Monteiro Jun 2 '15 at 14:21
17
\$\begingroup\$

I disagree with rolfl's assertion that, "There is no practical way to validate an e-mail address by regex alone."

He is correct—as illustrated by the somewhat infamous SO answer he linked to—that it's impractical to validate any RFC-5322-compliant email addresses because, to quote the HTML5 spec:

RFC-5322 … defines a syntax for e-mail addresses that is simultaneously too strict (before the '@' character), too vague (after the '@' character), and too lax (allowing comments, whitespace characters, and quoted strings in manners unfamiliar to most users) to be of practical use here.

...not to mention that there are now literally thousands of TLDs.

But it's absolutely practical to come up with a very good compromise, which is exactly what the writers of the HTML5 spec did. To that end, the spec provides this PCRE:

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

This regular expression will yield false positives (rejections) for technically valid email addresses, including ones with spaces and comments (yes, there is a syntax for putting comments in an email address), but practically all email addresses in use in the real world will pass.

As rolfl suggests, the only perfect way to validate an email address is to send an email to it and see if it's received—not all syntactically valid email addresses actually exist, after all—but that doesn't mean we can't use a pretty good validation to give the user useful feedback in the client, and for that we can look to the very smart people who did the work for us when they wrote the HTML5 spec.

As to your second question:

Also is there a difference between this method and just setting the type="email" in the HTML form?

Sure. Using type="email" makes the browser do the validation for you. That's obvious, I know, but it has a number of implications, some good and some not-necessarily-good. Among them:

  1. The browser might not do it. It might not support automatic validations, or the user might have disabled it. This limitation could be overcome with a polyfill, however.
  2. In browsers that support it, it just works, and you don't have to write any code, which is pretty nice.
  3. Currently there's no widely-supported way to customize the way browsers show HTML5 validation errors, so you can't control how it'll look to the user.

I'm sure there are others, but you get the idea.

My personal recommendation is that unless you have a good reason not to, use type="email" along with a polyfill (if you have users with older browsers). Very smart people wrote the HTML5 spec, and very smart people wrote the browsers that implement it. Unless you know something that they don't, use the solutions they've already built.

\$\endgroup\$
  • 6
    \$\begingroup\$ As someone who is regularly prevented from signing up on websites by having his perfectly valid email address rejected, I strongly disagree with your assertion that false negatives are acceptable. \$\endgroup\$ – Jörg W Mittag Oct 9 '14 at 20:41
  • 2
    \$\begingroup\$ @JörgWMittag Does your email address fail the regex given by the HTML5 spec? \$\endgroup\$ – Jordan Oct 9 '14 at 20:42
  • \$\begingroup\$ My unittests mention, using your regex : FAIL src/js/utils/__tests__/ValidationFunctions-test.js (0.186s) ● The Emailvalidator "isValidEMail" › it should fail when it has no dot ● The Emailvalidator "isValidEMail" › it should fail when top domain level has only one char ● The Emailvalidator "isValidEMail" › it should fail when the local part starts or ends with a dot ● The Emailvalidator "isValidEMail" › it should fail when it has two or more consecutive dots in the local part, Of course one char topdomain is not a syntax error (just pragmatic) but the other ones are. \$\endgroup\$ – Peter Aug 1 '15 at 13:31
  • \$\begingroup\$ Why does this fail for @gmail.com? It allows for "xxxx@gmail" without the .com \$\endgroup\$ – Anriëtte Myburgh May 10 '16 at 17:02
  • \$\begingroup\$ @AnriëtteMyburgh This regex works correctly for those cases. For example, here it is working in PHP: ideone.com/LEDUci and Ruby: ideone.com/lF7Ool Note that xxxx@gmail is a valid address per RFC-5322. As to why it's not working for you, that's impossible to say since you haven't told us how you're using it. If you're having problems I suggest posting a question on Stack Overflow. \$\endgroup\$ – Jordan May 10 '16 at 17:36
3
\$\begingroup\$

Confirming @Jordan, the Javascript regex provided here is practical, but needs to escape the forward slash / specified between the enclosures /..... / in order to work:

Original:

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

With escape:

/^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/
\$\endgroup\$
  • \$\begingroup\$ Have you ever tried DeBounce Email Verification? I suggest taking a look at this. Maybe helpful. \$\endgroup\$ – Iman Hejazi Mar 4 at 16:48

protected by Simon Forsberg Dec 7 '16 at 13:53

Thank you for your interest in this question. Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).

Would you like to answer one of these unanswered questions instead?

Not the answer you're looking for? Browse other questions tagged or ask your own question.