636

What is the most elegant code to validate that a string is a valid email address?

6

46 Answers 46

1047

What about this?

bool IsValidEmail(string email)
{
    var trimmedEmail = email.Trim();

    if (trimmedEmail.EndsWith(".")) {
        return false; // suggested by @TK-421
    }
    try {
        var addr = new System.Net.Mail.MailAddress(email);
        return addr.Address == trimmedEmail;
    }
    catch {
        return false;
    }
}

Per Stuart's comment, this compares the final address with the original string instead of always returning true. MailAddress tries to parse a string with spaces into "Display Name" and "Address" portions, so the original version was returning false positives.


To clarify, the question is asking whether a particular string is a valid representation of an e-mail address, not whether an e-mail address is a valid destination to send a message. For that, the only real way is to send a message to confirm.

Note that e-mail addresses are more forgiving than you might first assume. These are all perfectly valid forms:

  • cog@wheel
  • "cogwheel the orange"@example.com
  • 123@$.xyz

For most use cases, a false "invalid" is much worse for your users and future proofing than a false "valid". Here's an article that used to be the accepted answer to this question (that answer has since been deleted). It has a lot more detail and some other ideas of how to solve the problem.

Providing sanity checks is still a good idea for user experience. Assuming the e-mail address is valid, you could look for known top-level domains, check the domain for an MX record, check for spelling errors from common domain names (gmail.cmo), etc. Then present a warning giving the user a chance to say "yes, my mail server really does allow 🌮🍳🎁 as an email address."


As for using exception handling for business logic, I agree that is a thing to be avoided. But this is one of those cases where the convenience and clarity may outweigh the dogma.

Besides, if you do anything else with the e-mail address, it's probably going to involve turning it to a MailAddress. Even if you don't use this exact function, you will probably want to use the same pattern. You can also check for specific kinds of failure by catching different exceptions: null, empty, or invalid format.


--- Further reading ---

Documentation for System.Net.Mail.MailAddress

Explanation of what makes up a valid email address

Sign up to request clarification or add additional context in comments.

51 Comments

Actually, that's not incorrect. a@a is a valid e-mail address. See haacked.com/archive/2007/08/21/… In fact, this method does return incorrect results if you use an address with quotes.
+1: This is the best answer if you're using the System.Net.Mail classes to send mail, which you probably are if you're using .NET. We made the decision to use this type of validation simply because there is no point in us accepting email addresses - even valid ones - that we cannot send mail to.
I don't recommend. It returns true: IsValidEmail("this is not valid@email$com");
A lot of the problems seem to be because MailAddress tries to parse the DisplayName out too, so "single [email protected]" parses to DisplayName "single" and Address "[email protected]". A fix for this is to: return (addr.Address == email);
I like this; I don't get the compulsion to be more restrictive than the actual spec. False negatives are way worse than false positives ("what do you mean my e-mail is invalid?")
|
328

This is an old question, but all the answers I've found on SO, including more recent ones, are answered similarly to this one. However, in .Net 4.5 / MVC 4 you can add email address validation to a form by adding the [EmailAddress] annotation from System.ComponentModel.DataAnnotations, so I was wondering why I couldn't just use the built-in functionality from .Net in general.

This seems to work, and seems to me to be fairly elegant:

using System.ComponentModel.DataAnnotations;

class ValidateSomeEmails
{
    static void Main(string[] args)
    {
        var email = new EmailAddressAttribute();
        email.IsValid("[email protected]");         //true
        email.IsValid("[email protected]");       //true
        email.IsValid("[email protected]");     //true
        email.IsValid("[email protected]");      //true
        
        email.IsValid("fdsa");                          //false
        email.IsValid("fdsa@");                         //false
        email.IsValid("fdsa@fdsa");                     //false
        email.IsValid("fdsa@fdsa.");                    //false

        //one-liner
        if (new EmailAddressAttribute().IsValid("[email protected]")) 
            return true;
    }
}

23 Comments

Cool, although it's disappointing that MS can't make this agree with their own documentation. This rejects [email protected]
Note that EmailAddressAttribute is less permissive than System.Net.Mail.MailAddress - for instance, MailAddress accepts an address for a TLD. Just something to keep in mind if you need to be as permissive as possible.
@hofnarwillie: it is in the main body, but the comments elaborate. If your goal is to not anger your users then your validation shouldn't be any more restrictive than the spec. The only way to truly verify whether an e-mail is valid is to send a test message.
Please note that foo.IsValid(null); returns true.
As pointed out by @Hoffs the current implementation it's very different. Now only checks for the "@" character! Really scarily a text like "[email protected]' or 1=1" now is considered valid. I think a very visible disclaimer for NetCore implementations needs to be added...
|
86

I use this single liner method which does the work for me-

using System.ComponentModel.DataAnnotations;
public bool IsValidEmail(string source)
{
    return new EmailAddressAttribute().IsValid(source);
}

Per the comments, this will "fail" if the source (the email address) is null.

public static bool IsValidEmailAddress(this string address) => address != null && new EmailAddressAttribute().IsValid(address);

9 Comments

This doesn't work for me; I get, "'Data Annotations' does not exist...are you missing an assembly reference?" Which reference do I need to add?
This will return true if source is null. See msdn.microsoft.com/en-us/library/hh192424 "true if the specified value is valid or null; otherwise, false."
A better version: public static Boolean IsValidMailAddress(this String pThis) => pThis == null ? false : new EmailAddressAttribute().IsValid(pThis);
Or even better: public static bool IsValidEmailAddress(this string address) => address != null && new EmailAddressAttribute().IsValid(address);
I don't think this extension method should silently return false for null strings. That's why I propose the (even better better)++ version: public static bool IsValidEmailAddress(this string address) => new EmailAddressAttribute().IsValid(address ?? throw new ArgumentNullException());. I'll now go and found the Reformed Church of the Even Better Better Versionists.
|
52

.net 4.5 added System.ComponentModel.DataAnnotations.EmailAddressAttribute

You can browse the EmailAddressAttribute's source, this is the Regex it uses internally:

const string pattern = @"^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$";

6 Comments

Unfortunately the EmaillAddressAttribute allows Ñ which is not a valid character for email
@BZ Yes it is. Why do you think it isn't?
@Chad Grant: This is a C# version. Can you please provide a VB.Net one. Because that will escape characers like \\ to \ or you can provide a string verbatim one.
This works, but don't forget RegexOptions.IgnoreCase because this pattern does not allow capital letters explicitly!
Note that Regex is very deliberate: "This attribute provides server-side email validation equivalent to jquery validate, and therefore shares the same regular expression".
|
48

I took Phil's answer from #1 and created this class. Call it like this: bool isValid = Validator.EmailIsValid(emailString);

Here is the class:

using System.Text.RegularExpressions;

public static class Validator
{

    static Regex ValidEmailRegex = CreateValidEmailRegex();

    /// <summary>
    /// Taken from http://haacked.com/archive/2007/08/21/i-knew-how-to-validate-an-email-address-until-i.aspx
    /// </summary>
    /// <returns></returns>
    private static Regex CreateValidEmailRegex()
    {
        string validEmailPattern = @"^(?!\.)(""([^""\r\\]|\\[""\r\\])*""|"
            + @"([-a-z0-9!#$%&'*+/=?^_`{|}~]|(?<!\.)\.)*)(?<!\.)"
            + @"@[a-z0-9][\w\.-]*[a-z0-9]\.[a-z][a-z\.]*[a-z]$";

        return new Regex(validEmailPattern, RegexOptions.IgnoreCase);
    }

    internal static bool EmailIsValid(string emailAddress)
    {
        bool isValid = ValidEmailRegex.IsMatch(emailAddress);

        return isValid;
    }
}

4 Comments

Just a small one, but I would use: return (!string.IsNullOrEmpty(emailAddress)) && ValidEmailRegex.IsMatch(emailAddress);
This is just horror :)
this will not validate emails with 1 character domain. i.e: [email protected]
@Владимiръ did you run the code? Last time someone said it didn't work, I fired up a coding environment and it did validate properly. I haven't used C# in about 8 years and I'm genuinely curious if you know it doesn't work or if you are reading the code and saying it doesn't work.
37

Personally, I would say that you should just make sure there is an @ symbol in there, with possibly a . character. There's many regexes you could use of varying correctness, but I think most of these leave out valid email addresses, or let invalid ones through. If people want to put in a fake email address, they will put in a fake one. If you need to verify that the email address is legit, and that the person is in control of that email address, then you will need to send them an email with a special coded link so they can verify that it indeed is a real address.

10 Comments

I personally think you should do a bit more validation than that. Someone's bound to try Bobby Table's email address or worse.
What's wrong with bobby table's email address if you're using prepared statements. We're talking about valid email addresses, not other things that have nothing to do with what constitues a valid email address, like how to properly do SQL queries so that you don't get SQL injection problems.
I guess you don't know what someone will put in there but a malicious person knows that the value may eventually be fed into your mail system. I'd just prefer to go defense in depth and be a bit stricter.
That's for the mail system to worry about. I wouldn't go around rejecting perfectly valid email addresses just because it could be a security issue with some other system. If all your email server needs is a malformed email address to cause security problems, you should probably switch to another server.
Defence in depth only works if each level of your security onion is not rotten. One rotten layer means you spoil the whole onion. Rejecting "[email protected]" because you want to defend against vulnerabilities in Sun's µ-law encoding doesn't make sense, does it? Don't laugh, it's happened to me. The reason I am here commenting is that Medicare Australia doesn't allow ".au" addresses, only ".com". Also read Mark Swanson, "How not to validate email, ", mdswanson.com/blog/2013/10/14/…
|
34

Short and accurate code

string Email = txtEmail.Text;
if (Email.IsValidEmail())
{
   //use code here 
}

public static bool IsValidEmail(this string email)
{
  string pattern = @"^(?!\.)(""([^""\r\\]|\\[""\r\\])*""|" + @"([-a-z0-9!#$%&'*+/=?^_`{|}~]|(?<!\.)\.)*)(?<!\.)" + @"@[a-z0-9][\w\.-]*[a-z0-9]\.[a-z][a-z\.]*[a-z]$";    
  var regex = new Regex(pattern, RegexOptions.IgnoreCase);    
  return regex.IsMatch(email);
}

5 Comments

I had to change public static bool IsValidEmail(this string email) to public static bool IsValidEmail(string email) to avoid THIS: stackoverflow.com/questions/10412233/…
@Goner Doug, this functionlity will work like this.(bool flag = EmailAddress.IsValidEmail())
the "THIS" needed to be removed to avoid causing compiler issues when added to my form.
@Goner Doug, Its functionlity will work like this. string email = "[email protected]"; if (email.IsValidEmail()){ return false; }else { return true;}
this before the parameter string email makes the method an extension method that you can call like so : "some-email@provider".IsValidEmail() or like the example in the question: Email.IsValidEmail();. However, an extension method can only be placed in a static class.
19

The most elegant way is to use .Net's built in methods.

These methods:

  • Are tried and tested. These methods are used in my own professional projects.

  • Use regular expressions internally, which are reliable and fast.

  • Made by Microsoft for C#. There's no need to reinvent the wheel.

  • Return a bool result. True means the email is valid.

For users of .Net 4.5 and greater

Add this Reference to your project:

System.ComponentModel.DataAnnotations

Now you can use the following code:

(new EmailAddressAttribute().IsValid("[email protected]"));

Example of use

Here are some methods to declare:

protected List<string> GetRecipients() // Gets recipients from TextBox named `TxtRecipients`
{
    List<string> MethodResult = null;

    try
    {
        List<string> Recipients = TxtRecipients.Text.Replace(",",";").Replace(" ", "").Split(';').ToList();

        List<string> RecipientsCleaned = new List<string>();

        foreach (string Recipient in RecipientsCleaned)
        {
            if (!String.IsNullOrWhiteSpace(Recipient))
            {
                RecipientsNoBlanks.Add(Recipient);

            }

        }

        MethodResult = RecipientsNoBlanks;

    }
    catch//(Exception ex)
    {
        //ex.HandleException();
    }

    return MethodResult;

}


public static bool IsValidEmailAddresses(List<string> recipients)
{
    List<string> InvalidAddresses = GetInvalidEmailAddresses(recipients);

    return InvalidAddresses != null && InvalidAddresses.Count == 0;

}

public static List<string> GetInvalidEmailAddresses(List<string> recipients)
{
    List<string> MethodResult = null;

    try
    {
        List<string> InvalidEmailAddresses = new List<string>();

        foreach (string Recipient in recipients)
        {
            if (!(new EmailAddressAttribute().IsValid(Recipient)) && !InvalidEmailAddresses.Contains(Recipient))
            {
                InvalidEmailAddresses.Add(Recipient);

            }

        }

        MethodResult = InvalidEmailAddresses;

    }
    catch//(Exception ex)
    {
        //ex.HandleException();

    }

    return MethodResult;

}

...and code demonstrating them in action:

List<string> Recipients = GetRecipients();

bool IsValidEmailAddresses = IsValidEmailAddresses(Recipients);

if (IsValidEmailAddresses)
{
    //Emails are valid. Your code here

}
else
{
    StringBuilder sb = new StringBuilder();

    sb.Append("The following addresses are invalid:");

    List<string> InvalidEmails = GetInvalidEmailAddresses(Recipients);

    foreach (string InvalidEmail in InvalidEmails)
    {
        sb.Append("\n" + InvalidEmail);

    }

    MessageBox.Show(sb.ToString());

}

In addition, this example:

  • Extends beyond the spec since a single string is used to contain 0, one or many email addresses sperated by a semi-colon ;.
  • Clearly demonstrates how to use the IsValid method of the EmailAddressAttribute object.

Alternative, for users of a version of .Net less than 4.5

For situations where .Net 4.5 is not available, I use the following solution:

Specifically, I use:

public static bool IsValidEmailAddress(string emailAddress)
{
    bool MethodResult = false;

    try
    {
        MailAddress m = new MailAddress(emailAddress);

        MethodResult = m.Address == emailAddress;

    }
    catch //(Exception ex)
    {
        //ex.HandleException();

    }

    return MethodResult;

}

public static List<string> GetInvalidEmailAddresses(List<string> recipients)
{
    List<string> MethodResult = null;

    try
    {
        List<string> InvalidEmailAddresses = new List<string>();

        foreach (string Recipient in recipients)
        {
            if (!IsValidEmail(Recipient) && !InvalidEmailAddresses.Contains(Recipient))
            {
                InvalidEmailAddresses.Add(Recipient);

            }

        }

        MethodResult = InvalidEmailAddresses;

    }
    catch //(Exception ex)
    {
        //ex.HandleException();

    }

    return MethodResult;

}

2 Comments

@ThomasAyoub I haven't seen an EmailAddressAttribute answer, and no answer that uses new MailAddress() with a check on input == .Address so I think its pretty useful. Without reading comments the accepted answer is pretty wrong. new MailAddress("Foobar [email protected]") proves that.
@Jan fwiw, Manik beat Knickerless to the EmailAddressAttribute by just under four months, though this one does catch the null issue.
18

I think the best way is as follow:

    public static bool EmailIsValid(string email)
    {
        string expression = "\\w+([-+.']\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*";

        if (Regex.IsMatch(email, expression))
        {
            if (Regex.Replace(email, expression, string.Empty).Length == 0)
            {
                return true;
            }
        }
        return false;
    }

You can have this static function in a general class.

1 Comment

This answer doesn't accept an address with a TLD in the domain part.
11

To be honest, in production code, the best I do is check for an @ symbol.

I'm never in a place to be completely validating emails. You know how I see if it was really valid? If it got sent. If it didn't, it's bad, if it did, life's good. That's all I need to know.

Comments

7

I find this regex to be a good trade off between checking for something more than just the @ mark, and accepting weird edge cases:

^[^@\s]+@[^@\s]+(\.[^@\s]+)+$

It will at least make you put something around the @ mark, and put at least a normal looking domain.

6 Comments

I came up with the same regex ;) It does allow invalid charachters though
This answer does not accept a TLD in the domain part.
@Simone probably nobody does have email addresses with the TLD in the domain part though in practice: serverfault.com/a/721929/167961 note in the comments it may be prohibited these days
@MatthewLock Could it be an intranet address? Like bob@companyinternal?
@Simone does anyone in real life actually use that scheme?
|
7

I just want to point out, that there has been a recent addition to the .NET documentation regarding email validation, also utilitzing Regex operations. A thorough explanation to their implementation can be found there.

https://learn.microsoft.com/en-us/dotnet/standard/base-types/how-to-verify-that-strings-are-in-valid-email-format

For convenience, here is a list of their test results:

//       Valid: [email protected]
//       Valid: [email protected]
//       Valid: [email protected]
//       Invalid: [email protected]
//       Valid: [email protected]
//       Valid: js#[email protected]
//       Valid: j_9@[129.126.118.1]
//       Invalid: [email protected]
//       Invalid: js*@proseware.com
//       Invalid: [email protected]
//       Valid: [email protected]
//       Valid: [email protected]
//       Valid: "j\"s\""@proseware.com
//       Valid: js@contoso.中国

Comments

6

Here's my answer -- Phil's solution fails for single letter domains like "[email protected]". Believe it or not, that's used =) (goes to centurylink, for instance).

Phil's answer is also going to work only with PCRE standard... so C# will take it, but javascript is going to bomb. It's too complex for javascript. So you can't use Phil's solution for mvc validation attributes.

Here's my regex. It'll work nicely with MVC validation attributes.
- Everything before the @ is simplified, so that at least javascript will work. I'm okay relaxing validation here as long as exchange server doesn't give me a 5.1.3. - Everything after the @ is Phil's solution modified for single letter domains.

public const string EmailPattern =
        @"^\s*[\w\-\+_']+(\.[\w\-\+_']+)*\@[A-Za-z0-9]([\w\.-]*[A-Za-z0-9])?\.[A-Za-z][A-Za-z\.]*[A-Za-z]$";

For people suggesting using system.net.mail MailMessage(), that thing is WAY to flexible. Sure, C# will accept the email, but then exchange server will bomb with 5.1.3 runtime error as soon as you try to send the email.

3 Comments

that seems to be the best most thoughtful / reasonable / realworld answer, thanks Ralph!
this is the best answer so far! I can't believe a bad solution that accepts basket@ball as a valid email address has gained the correct answer as well as all those upvotes. Thanks anyway!
Thanks this is the best solution and should be accepted answer.
6

I summarize all the above answers as of the current year 2021 I wrote for myself this class:

public static class StringExt {
    private const string emailPattern = @"^(?!\.)(""([^""\r\\]|\\[""\r\\])*""|" 
            + @"([-a-z0-9!#$%&'*+/=?^_`{|}~]|(?<!\.)\.)*)(?<!\.)" 
            + @"@[a-z0-9][\w\.-]*[a-z0-9]\.[a-z][a-z\.]*[a-z]$";

    public static bool IsValidMailAddress(this string pThis) 
            => pThis is not null 
            && Regex.IsMatch(pThis, emailPattern, RegexOptions.IgnoreCase);
}

1 Comment

Works for detecting multiple . in a row and , outside of quotes, and seems to follow standards listed here: en.wikipedia.org/wiki/Email_address#Local-part but does not allow for international characters permitted by RFC 6530.
5

Email address validation is not as easy as it might seem. It's actually theoretically impossible to fully validate an email address using just a regular expression.

Check out my blog post about it for a discussion on the subject and a F# implementation using FParsec. [/shameless_plug]

3 Comments

I liked you list of alternative approaches; very interesting.
Interesting article. But seriously who's putting comments, and nested ones at that, in email addresses?
@matthew I don't know why the IETF has even allowed that, but it's possible, so a thorough validation has to take it into account.
4

There are a lot of strong answers here. However, I recommend that we take a step back. @Cogwheel answers the question https://stackoverflow.com/a/1374644/388267. Nevertheless, it could be costly in a bulk validation scenario, if many of the email address being validated are invalid. I suggest that we employ a bit of logic before we enter into his try-catch block. I know that the following code could be written using RegEx but that could be costly for new developers to understand. This is my twopence worth:

    public static bool IsEmail(this string input)
    {
        if (string.IsNullOrWhiteSpace(input)) return false;

        // MUST CONTAIN ONE AND ONLY ONE @
        var atCount = input.Count(c => c == '@');
        if (atCount != 1) return false;

        // MUST CONTAIN PERIOD
        if (!input.Contains(".")) return false;

        // @ MUST OCCUR BEFORE LAST PERIOD
        var indexOfAt = input.IndexOf("@", StringComparison.Ordinal);
        var lastIndexOfPeriod = input.LastIndexOf(".", StringComparison.Ordinal);
        var atBeforeLastPeriod = lastIndexOfPeriod > indexOfAt;
        if (!atBeforeLastPeriod) return false;

        // CODE FROM COGWHEEL'S ANSWER: https://stackoverflow.com/a/1374644/388267 
        try
        {
            var addr = new System.Net.Mail.MailAddress(input);
            return addr.Address == input;
        }
        catch
        {
            return false;
        }
    }

1 Comment

This will reject "Abc@def"@example.com which is a valid email address that contains more than one @ symbol (see this article.
4

As mentioned in many answers, the domain of email addresses is complex. I would strongly discourage the use of a regex in this case. Those who match (most) cases are extremely complex to read and therefor to maintain. Furthermore, the still have difficulties supporting all cases, and are slow.

Microsoft's EmailAddress class helps a bit in that respect, but is not perfect either, I would argue. For an open source project I gave it try some years ago, by using a customized EmailParser.

That is used in [EmailAddress]https://github.com/Qowaiv/Qowaiv/blob/master/src/Qowaiv/EmailAddress.cs).

By using this approach, you're not only to validate email addresses, but also by cleaning out multiple formats of display names, getting rid of the mailto:-prefix, and normalizing domain literals based on IP-addresses, and lowercasing everything (note that the local part officially is case sensitive).

Scenario's your solution should support (and the mentioned one does):

[TestCase(null)]
[TestCase("")]
[TestCase("[email protected]")]
[TestCase("[email protected]")]
[TestCase("ab@sd@dd")]
[TestCase("[email protected]")]
[TestCase("[email protected]")]
[TestCase("[email protected]")]
[TestCase("[email protected]")]
[TestCase("ab@[188.120.150.10")]
[TestCase("[email protected]]")]
[TestCase("ab@[188.120.150.10].com")]
[TestCase("[email protected]")]
[TestCase("[email protected]")]
[TestCase("[email protected]")]
[TestCase("[email protected].")]
[TestCase("ab@b+de.cc")]
[TestCase("[email protected]")]
[TestCase("[email protected],")]
[TestCase("plainaddress")]
[TestCase("plain.address")]
[TestCase("@%^%#$@#$@#.com")]
[TestCase("@domain.com")]
[TestCase("Joe Smith &lt;[email protected]&gt;")]
[TestCase("email.domain.com")]
[TestCase("email@[email protected]")]
[TestCase("[email protected]")]
[TestCase("[email protected]")]
[TestCase("[email protected]")]
[TestCase("[email protected]")]
[TestCase("[email protected]")]
[TestCase("[email protected]")]
[TestCase("[email protected]")]
[TestCase("[email protected].")]
[TestCase("[email protected]")]
[TestCase("[email protected]")]
[TestCase("[email protected]")]
[TestCase("email@[123.123.123.123")]
[TestCase("email@[123.123.123].123")]
[TestCase("[email protected]]")]
[TestCase("[email protected].[123.123]")]
[TestCase("email@{leftbracket.com")]
[TestCase("email@rightbracket}.com")]
[TestCase("email@p|pe.com")]
[TestCase("isis@100%.nl")]
[TestCase("email@dollar$.com")]
[TestCase("email@r&amp;d.com")]
[TestCase("email@#hash.com")]
[TestCase("email@wave~tilde.com")]
[TestCase("email@exclamation!mark.com")]
[TestCase("email@question?mark.com")]
[TestCase("email@obelix*asterisk.com")]
[TestCase("email@grave`accent.com")]
[TestCase("email@colon:colon.com")]
[TestCase("email@caret^xor.com")]
[TestCase("email@=qowaiv.com")]
[TestCase("email@plus+.com")]
[TestCase("[email protected]>")]
[TestCase("email( (nested) )@plus.com")]
[TestCase("email)mirror(@plus.com")]
[TestCase("[email protected] (not closed comment")]
[TestCase("email(with @ in comment)plus.com")]
[TestCase(@"""Joe Smith [email protected]")]
[TestCase(@"""Joe Smith' [email protected]")]
[TestCase(@"""Joe Smith""[email protected]")]
[TestCase("email@mailto:domain.com")]
[TestCase("mailto:mailto:[email protected]")]
[TestCase("Display Name <[email protected]> (after name with display)")]
[TestCase("ReDoSaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa@aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")]
public void IsInvalid(string email)
{
    Assert.IsFalse(EmailAddress.IsValid(email), email);
}

[TestCase("w@com")]
[TestCase("[email protected]")]
[TestCase("[email protected]")]
[TestCase("[email protected]")]
[TestCase("[email protected]")]
[TestCase("[email protected]")]
[TestCase("[email protected]")]
[TestCase("[email protected]")]
[TestCase("[email protected]")]
[TestCase("[email protected]")]
[TestCase("[email protected]")]
[TestCase("ab@[120.254.254.120]")]
[TestCase("local@2001:0db8:85a3:0000:0000:8a2e:0370:7334")]
[TestCase("local@[2001:0db8:85a3:0000:0000:8a2e:0370:7334]")]
[TestCase("[email protected]")]
[TestCase("[email protected]")]
[TestCase("[email protected]")]
[TestCase("[email protected]")]
[TestCase("[email protected]")]
[TestCase("[email protected]")]
[TestCase("[email protected]")]
[TestCase("[email protected]")]
[TestCase("[email protected]")]
[TestCase("[email protected]")]
[TestCase("[email protected]")]
[TestCase("[email protected]")]
[TestCase("email@domain")]
[TestCase("あいうえお@domain.com")]
[TestCase("local@あいうえお.com")]
[TestCase("[email protected]")]
[TestCase("[email protected]")]
[TestCase("[email protected]")]
[TestCase("[email protected]")]
[TestCase("email@[123.123.123.123]")]
[TestCase("[email protected]")]
[TestCase("[email protected]")]
[TestCase("[email protected]")]
[TestCase("[email protected]")]
[TestCase("[email protected]")]
[TestCase("[email protected]")]
[TestCase("[email protected]")]
[TestCase("[email protected]")]
[TestCase("[email protected]")]
[TestCase("[email protected]")]
[TestCase("[email protected]")]
[TestCase("[email protected]")]
[TestCase("[email protected]")]
[TestCase("{local{name{{with{@leftbracket.com")]
[TestCase("}local}name}}with{@rightbracket.com")]
[TestCase("|local||name|with|@pipe.com")]
[TestCase("%local%%name%with%@percentage.com")]
[TestCase("[email protected]")]
[TestCase("&local&&name&with&[email protected]")]
[TestCase("#local##name#with#@hash.com")]
[TestCase("[email protected]")]
[TestCase("[email protected]")]
[TestCase("[email protected]")]
[TestCase("*local**name*with*@asterisk.com")]
[TestCase("`local``name`with`@grave-accent.com")]
[TestCase("^local^^name^with^@xor.com")]
[TestCase("[email protected]")]
[TestCase("[email protected]")]
[TestCase("Joe Smith <[email protected]>")]
[TestCase("[email protected] (joe Smith)")]
[TestCase(@"""Joe Smith"" [email protected]")]
[TestCase(@"""Joe\\tSmith"" [email protected]")]
[TestCase(@"""Joe\""Smith"" [email protected]")]
[TestCase(@"Test |<gaaf <[email protected]>")]
[TestCase("MailTo:[email protected]")]
[TestCase("mailto:[email protected]")]
[TestCase("Joe Smith <mailto:[email protected]>")]
[TestCase("Joe Smith <mailto:email(with comment)@domain.com>")]
[TestCase(@"""With extra < within quotes"" Display Name<[email protected]>")]
[TestCase("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa@aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")]
public void IsValid(string email)
{
    Assert.IsTrue(EmailAddress.IsValid(email), email);
}

Comments

3

If you really and I mean really want to know if an email address is valid...ask the mail exchanger to prove it, no regex needed. I can provide the code if requested.

General steps are as follows: 1. does email address have a domain name part? (index of @ > 0) 2. using a DNS query ask if domain has a mail exchanger 3. open tcp connection to mail exchanger 4. using the smtp protocol, open a message to the server using the email address as the reciever 5. parse the server's response. 6. quit the message if you made it this far, everything is good.

This is as you can imagine, very expensive time wise and relies on smtp, but it does work.

4 Comments

Did you create fakes, stubs and/or mocks for those interfaces?
That won't work. The smtp protocol to verify an email address has LONG been deprecated/not used. It is considered bad practice to enable that on mail servers since spammers use that functionality.
I'll keep your suggestion up to point 2. Way more future-proof than checking for a known domain name pattern.
Nitpicking, but define "has a mail exchanger"? If no MX records exist, SMTP should fall back to the A/AAAA record, as per RFC2821/5321. If an MX record does exist, it still might not indicate a mail exchanger exists (RFC7505). Really, the only way is to send them a mail with a call-to-action link, and wait for them to reply...
3

In case you are using FluentValidation you could write something as simple as this:

public cass User
{
    public string Email { get; set; }
}

public class UserValidator : AbstractValidator<User>
{
    public UserValidator()
    {
        RuleFor(x => x.Email).EmailAddress().WithMessage("The text entered is not a valid email address.");
    }
}

// Validates an user. 
var validationResult = new UserValidator().Validate(new User { Email = "açflkdj" });

// This will return false, since the user email is not valid.
bool userIsValid = validationResult.IsValid;

Comments

3

a little modification to @Cogwheel answer

public static bool IsValidEmail(this string email)
{
  // skip the exception & return early if possible
  if (email.IndexOf("@") <= 0) return false;

  try
  {
    var address = new MailAddress(email);
    return address.Address == email;
  }
  catch
  {
    return false;
  }
}

2 Comments

This doesn't seem to help... Console.WriteLine(MailAddress("asdf@asdf.").Address); outputs "asdf@asdf.", which is not valid.
.net seems to have its own definition of valid. related discussion
2

Generally speaking, a regular expression to validate email addresses is not an easy thing to come up with; at the time of this writing, the syntax of an email address must follow a relatively high number of standards and implementing all of them within a regular expression is practically unfeasible!

I highly suggest you to try our EmailVerify.NET, a mature .NET library which can validate email addresses following all of the current IETF standards (RFC 1123, RFC 2821, RFC 2822, RFC 3696, RFC 4291, RFC 5321 and RFC 5322), tests the related DNS records, checks if the target mailboxes can accept messages and can even tell if a given address is disposable or not.

Disclaimer: I am the lead developer for this component.

4 Comments

Impressive! "Next, it tries to contact the mail exchanger responsible for the given email address and begins a fake SMTP dialog with that server, emulating a real mail server. This way it ensures that the server can handle emails for the address. Many SMTP servers actually give back false positive answers as a protection against spammers: to overcome this issue, EmailVerify for .NET finally attempts to query the target mail exchanger multiple times with different fabricated addresses. "
Thanks, @MatthewLock ;)
Nice, but I only see paid editions. Any plans for a community/OpenSource edition?
@OhadSchneider Yes: we are offering a free version of our email validation technology by way of Verifalia, our SaaS email verification service. Verifalia comes with free and open-source SDKs for the major software development platforms, including .NET.
2

A simple one without using Regex (which I don't like for its poor readability):

bool IsValidEmail(string email)
{
    string emailTrimed = email.Trim();

    if (!string.IsNullOrEmpty(emailTrimed))
    {
        bool hasWhitespace = emailTrimed.Contains(" ");

        int indexOfAtSign = emailTrimed.LastIndexOf('@');

        if (indexOfAtSign > 0 && !hasWhitespace)
        {
            string afterAtSign = emailTrimed.Substring(indexOfAtSign + 1);

            int indexOfDotAfterAtSign = afterAtSign.LastIndexOf('.');

            if (indexOfDotAfterAtSign > 0 && afterAtSign.Substring(indexOfDotAfterAtSign).Length > 1)
                return true;
        }
    }

    return false;
}

Examples:

It is meant to be simple and therefore it doesn't deal with rare cases like emails with bracketed domains that contain spaces (typically allowed), emails with IPv6 addresses, etc.

Comments

2
For the simple email like [email protected], below code is sufficient. 

 public static bool ValidateEmail(string email)
        {
            System.Text.RegularExpressions.Regex emailRegex = new System.Text.RegularExpressions.Regex(@"^([\w\.\-]+)@([\w\-]+)((\.(\w){2,3})+)$");
            System.Text.RegularExpressions.Match emailMatch = emailRegex.Match(email);
            return emailMatch.Success;
        }

1 Comment

It'll fail to validate [email protected] as a valid email address.
2

The most voted answer from @Cogwheel is best answer however i have tried to implement trim() string method so it will trim all user white space from string start to end. Check the code bellow for full example-

bool IsValidEmail(string email)
{
    try
    {
        email = email.Trim();
        var addr = new System.Net.Mail.MailAddress(email);
        return addr.Address == email;
    }
    catch
    {
        return false;
    }
}

2 Comments

The risk of this is that you are validating a different e-mailaddress than the source, leaving you to think you can mail to the (in this case) untrimmed version of the specified e-mailaddress. A better approach would be to make a seperate method SanitizeEmail(string email), using the result of that method to validate and send the email to.
a+b@b comes as valid using this code but that is not a valid email
2

Another Regex Match answer :

   /// <summary>
   /// Validates the email input
   /// </summary>
   internal static bool ValidateEmail(string _emailAddress)
   { 

        string _regexPattern = @"^(([\w-]+\.)+[\w-]+|([a-zA-Z]{1}|[\w-]{2,}))@"
                + @"((([0-1]?[0-9]{1,2}|25[0-5]|2[0-4][0-9])\.([0-1]?[0-9]{1,2}|25[0-5]|2[0-4][0-9])\."
                + @"([0-1]?[0-9]{1,2}|25[0-5]|2[0-4][0-9])\.([0-1]?[0-9]{1,2}|25[0-5]|2[0-4][0-9])){1}|"
                + @"([a-zA-Z]+[\w-]+\.)+[a-zA-Z]{2,4})$";

        return (string.IsNullOrEmpty(_emailAddress) == false && System.Text.RegularExpressions.Regex.IsMatch(_emailAddress, _regexPattern))
            ? true
            : false;
    }

Comments

2

I came here to steal the verification code for the e-mail. Then I saw that the codes in the answers were unnecessarily extended. I believe I wrote the best solution in the shortest way:

public static bool IsEmail(string email)
{
    try
    {
        return new System.Net.Mail.MailAddress(email).Address == email && !email.Trim().EndsWith(".");
    }
    catch
    {
        return false;
    }
}

2 Comments

why do people insist on being lazy and using exceptions for control flow?
did you ask this question yourself? why you are here :)
2

A refactored version of @Cogwheel's answer using .NET 5's MailAddress.TryCreate():

bool IsValidEmail(string email)
{
    var trimmedEmail = email.Trim();

    if (trimmedEmail.EndsWith("."))
    {
        return false; // suggested by @TK-421
    }

    return MailAddress.TryCreate(email, out MailAddress addr)
        && addr.Address == trimmedEmail;
}

Comments

1
private static bool IsValidEmail(string emailAddress)
{
    const string validEmailPattern = @"^(?!\.)(""([^""\r\\]|\\[""\r\\])*""|"
                                     + @"([-a-z0-9!#$%&'*+/=?^_`{|}~]|(?<!\.)\.)*)(?<!\.)"
                                     + @"@[a-z0-9][\w\.-]*[a-z0-9]\.[a-z][a-z\.]*[a-z]$";

    return new Regex(validEmailPattern, RegexOptions.IgnoreCase).IsMatch(emailAddress);
}

Comments

1

Check email string is right format or wrong format by System.Text.RegularExpressions:

    public static bool IsValidEmailId(string InputEmail)
    {
        Regex regex = new Regex(@"^([\w\.\-]+)@([\w\-]+)((\.(\w){2,3})+)$");
        Match match = regex.Match(InputEmail);
        if (match.Success)
            return true;
        else
            return false;
    }

    protected void Email_TextChanged(object sender, EventArgs e)
    {
        String UserEmail = Email.Text;
        if (IsValidEmailId(UserEmail))
        {
            Label4.Text = "This email is correct formate";
        }
        else
        {
            Label4.Text = "This email isn't correct formate";
        }
    }

Comments

1

/Using the Internal Regex used in creating the "new EmailAddressAttribute();" component in .Net4.5 >>> using System.ComponentModel.DataAnnotations; //To Validate an Email Address......Tested and Working.

public bool IsEmail(string email)
{
    if (String.IsNullOrEmpty(email))
    {   return false;  }
    try
    {
        Regex _regex = new Regex("^((([a-z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])" +
                "+(\\.([a-z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])+)*)|((\\x22)" +
                "((((\\x20|\\x09)*(\\x0d\\x0a))?(\\x20|\\x09)+)?(([\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x7f]|\\x21|[\\x23-\\x5b]|[\\x5d-\\x7e]|" +
                "[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(\\\\([\\x01-\\x09\\x0b\\x0c\\x0d-\\x7f]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\u" +
                "FDF0-\\uFFEF]))))*(((\\x20|\\x09)*(\\x0d\\x0a))?(\\x20|\\x09)+)?(\\x22)))@((([a-z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|" +
                "(([a-z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])([a-z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])*([a-z]|\\d|" +
                "[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])))\\.)+(([a-z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(([a-z]|[\\u00A0-\\uD7FF\\uF900" +
                "-\\uFDCF\\uFDF0-\\uFFEF])([a-z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])*([a-z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFF" +
                "EF])))\\.?$", RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture | RegexOptions.Compiled);
        return _regex.IsMatch(email);
    }
    catch (RegexMatchTimeoutException)
    {
        return false;
    }
}

Also, You can use this:

http://msdn.microsoft.com/en-us/library/01escwtf(v=vs.110).aspx

2 Comments

it says true for this email : "[email protected]ö" and it throws error at mandrill api
First, the email is valid w.r.t. [email protected] or [email protected] email has all valid string and criterial except for the last character " ö " and you can easily add a simple condition to validate such character. Second, am not sure about that mandrill api error, you might want to verify your method of usage bcos I have used this validation on some other environment / api's and its been good to me.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.