14
\$\begingroup\$

I need to validate whether my regex is correct for below scenario. Suggestion's if the regex is correct:

Wiki Link Local_part

The local-part of the email address may use any of these ASCII characters.[4] RFC 6531 permits Unicode characters beyond the ASCII range:

  1. Uppercase and lowercase English letters (a–z, A–Z) (ASCII: 65–90, 97–122)
  2. Digits 0 to 9 (ASCII: 48–57)
  3. These special characters: ! # $ % & ' * + - / = ? ^ _ { | } ~ (limited support)
  4. Character . (dot, period, full stop) (ASCII: 46) provided that it is not the first or last character, and provided also that it does not appear two or more times consecutively (e.g. John..Doe@example.com is not allowed).
  5. Special characters are allowed with restrictions. They are:
  6. Comments are allowed with parentheses at either end of the local part; e.g. "john.smith(comment)@example.com" and "(comment)john.smith@example.com" are both equivalent to "john.smith@example.com".
  7. International characters above U+007F are permitted by RFC 6531, though mail systems may restrict which characters to use when assigning local parts.

The Regex:

^[a-z0-9][-a-z0-9.!#$%&'*+-=?^_`{|}~\/]+@([-a-z0-9]+\.)+[a-z]{2,5}$

Demo Here

\$\endgroup\$
10
  • 2
    \$\begingroup\$ What language are we talking about? Most languages have libraries for validating emails, and also, regex implementation differs between languages. \$\endgroup\$ Jun 23, 2014 at 11:41
  • \$\begingroup\$ Oops sorry to mention. .net \$\endgroup\$ Jun 23, 2014 at 11:42
  • \$\begingroup\$ .net is not a language, it's a framework. \$\endgroup\$ Jun 23, 2014 at 11:43
  • 2
    \$\begingroup\$ Can you provide some C# code where you perform this check? \$\endgroup\$ Jun 23, 2014 at 11:45
  • 5
    \$\begingroup\$ I'd consider regex to be a domain-specific language. Specifying ".NET Framework Regular Expressions" makes it sufficiently concrete to be on-topic. \$\endgroup\$ Jun 23, 2014 at 11:53

7 Answers 7

35
\$\begingroup\$

I remember having read somewhere (possibly in another Code Review answer) that for an e-mail address, the simplest and most effective validation you can do is to make sure it contains an @. Making it more restrictive than that can often be a risk of invalidating some valid e-mails. You'd be surprised at some examples of valid e-mail addresses.

As an additional example, see the "almost RFC 822 compatible regex" in this answer.

Keep it simple, and don't mark some e-mail addresses that are actually valid as invalid.

email.contains("@")

If you want to be more restrictive than this, use an existing and trusted library for the validation, don't try to make another regex.

For further reading:

\$\endgroup\$
8
  • \$\begingroup\$ Thanks @simon for the list of email addresses. \$\endgroup\$ Jun 23, 2014 at 12:16
  • 4
    \$\begingroup\$ "Some people, when confronted with a problem, think 'I know, I'll use regular expressions.' Now they have two problems."——Jamie Zawinski on regular expressions; paraphrasing the Unix Haters Handbook on sed, paraphrasing David Tilbrook on awk. regex.info/blog/2006-09-15/247 :) \$\endgroup\$ Jun 23, 2014 at 17:20
  • 1
    \$\begingroup\$ The main point being that even if the address is syntactically correct, you have no idea whether it exists. If you need verification, send a verification link to the address. \$\endgroup\$
    – Ingo Bürk
    Jun 23, 2014 at 19:38
  • 1
    \$\begingroup\$ @IngoBürk: That's true, but validation and verification are different things. There's no point verifying invalid data. \$\endgroup\$
    – Magus
    Jun 24, 2014 at 15:19
  • 1
    \$\begingroup\$ If you want to be more restrictive than this, use an existing and trusted library for the validation - In my experience, even library validators are broken. Since then, email.contains("@") is the only thing I'd ever do. \$\endgroup\$
    – Jo So
    Aug 17, 2014 at 2:40
20
\$\begingroup\$

As @Simon pointed out, your regular expression might consider some valid addresses as invalid.

Per this source which I've found somewhere on this Stack Overflow page, this would be RFC5322-compliant:

(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*
  |  "(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]
      |  \\[\x01-\x09\x0b\x0c\x0e-\x7f])*")
@ (?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?
  |  \[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}
       (?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:
          (?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]
          |  \\[\x01-\x09\x0b\x0c\x0e-\x7f])+)
     \])

Validating emails with a regular expression is ...more complicated than one would think, eh?

I agree with @Simon here, it's probably best to keep it simple, and go with a simple string.Contains() instead of a regular expression. If it's not a matter of life and death, ...don't try to be a regex ninja!

XKCD#208

\$\endgroup\$
1
  • 4
    \$\begingroup\$ Pretty much anything with an xkcd comic gets an up vote. \$\endgroup\$
    – RubberDuck
    Jun 23, 2014 at 13:14
13
\$\begingroup\$

It was suggested that I move this to an answer instead of a comment:

Since you're using .NET, why not just use System.Net.Mail.MailAddress? It already performs validation in its constructor - it will throw a FormatException if the address is invalid.

This is particularly useful if you intend on using the address to actually send email, since you'll likely be using Systen.Net.Mail.MailAddress for it anyways.

This does not get you the regex, but I think a better solution is to avoid regex in this case for the reasons stated in the comments and other answers.

\$\endgroup\$
3
  • \$\begingroup\$ Why, why, why, WHY haven't I thought if this!?!! Here, have an upvote! ;) \$\endgroup\$ Jun 23, 2014 at 23:56
  • 2
    \$\begingroup\$ +1 I've used this technique multiple times. If it's good enough for the .NET Framework, it's good enough for me. The really long catch-all-edge-cases regex formats are daunting. And they're never quite perfect. \$\endgroup\$
    – user24822
    Jun 24, 2014 at 19:39
  • \$\begingroup\$ This feels like you're using try/catch for control flow since you're forced to catch an exception in the invalid case while trying to validate. \$\endgroup\$
    – Erik
    Nov 18, 2015 at 19:09
3
\$\begingroup\$

I follow the HTML5 spec for validation of email here. (Note that it's not RFC 5322 compatible)

The regex for it is:

/^[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])?)*$/

which is simple enough for my needs.

\$\endgroup\$
4
  • 2
    \$\begingroup\$ The important question IMO is not whether or not the regex is simple, it's whether or not it is correct. I believe this regex will incorrectly mark several unusual but valid addresses as invalid. \$\endgroup\$ Jun 23, 2014 at 15:28
  • \$\begingroup\$ True, some will fail, but it has the advantage that the same validation that happens on the browser is also used on the server side. Also I suspect that soon all the "valid" emails that don't pass the check above (ie HTML5 validation) will be changed to be compatible with it. \$\endgroup\$ Jun 23, 2014 at 16:08
  • \$\begingroup\$ @SimonAndréForsberg: Do you have some examples of valid ones not accepted by this regex? \$\endgroup\$
    – Gabe
    Jun 24, 2014 at 0:20
  • 1
    \$\begingroup\$ @SimonAndréForsberg: I.am.a.valid"email address!"@email.host. The spec is uh, quite flexible. \$\endgroup\$
    – Phoshi
    Jun 24, 2014 at 15:18
1
\$\begingroup\$

If you're willing to take a dependency on System.ComponentModel.DataAnnotations then you can use the EmailAddressAttribute to do all the heavy lifting for you. I tend to use it as an extension method as follows:

private static readonly EmailAddressAttribute EmailValidator = new EmailAddressAttribute();

public static bool IsValidEmail(this string email)
{
    // You can also add validation against length if you want
    return !string.IsNullOrWhiteSpace(email) && EmailValidator.IsValid(email); 
}
\$\endgroup\$
1
\$\begingroup\$

Email validation regex:

^[a-z0-9][-a-z0-9._]+@([-a-z0-9]+\.)+[a-z]{2,5}$

Or

^[a-z0-9][-a-z0-9._]+@([-a-z0-9]+[.])+[a-z]{2,5}$

Test it out in this Demonstration

\$\endgroup\$
0
\$\begingroup\$
const re_host = '(([a-z0-9-]+\.)+[a-z]+|([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])){3})';
const re_localpart = '[a-z0-9!#\$%&\'*\+-/=\?\^_`{|}\~\.]+';

Take these two constants, and concatenate them like this re_localpart + '@' + re_host and you have a regular expression to validate an email address. Note that this is a PHP regex.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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