Advanced email address validation in .NET

Brouillon

À venir

0 comment

Applications often ask users to enter an email address, for instance to create an account. Of course, the application must check the value is a valid email address. In this post, we’ll see how to validate the email address and avoid some typing mistakes.

Check the value is an email address

First, we must check the user input is an email address. This means the value must match the grammar described in the RFC 5322 (which replaces RFC 2822 and RFC 822). There are 2 mains ways of validating email address: using a regex or a parser.

There are many regex on the web. Some are very complex (like this one), some are basics, and many are wrongs (reject valid values). I prefer using the regex provided by the W3C to validate <input type="email">:

var regex = new Regex(@"^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$", RegexOptions.Compiled);
return regex.IsMatch(email);

If you need a better parser, you can rely on the one provided by the .NET Framework. Indeed, you can parse an email address using the MailAddress class, which internally use MailAddressParser. Unfortunately, it doesn’t provide a TryParse method, so you must catch the exception.

try
{
    var mailAddress = new MailAddress(email);
    return true;
}
catch (FormatException)
{
    return false;
}

Check the domain has an email server

At this stage, you know the email address is valid, but this doesn’t mean you’ll be able to send an email at this address. In fact, if the user types "john@softluent.com" instead of "john@softfluent.com" (note the missing "f" in the domain), you may send an email to a domain that doesn’t exist.

You can avoid this kind of typing errors by checking the provided domain exists and has an email server. Indeed, when you send an email to a recipient, you must first ask the IP address of the email server of the recipient. This information is provided by the DNS server, and more specifically the MX or A entry. For instance, the DNS of "softfluent.com" has one MX record:

softfluent.com.         10776   IN      A       213.246.37.242
softfluent.com.         10178   IN      MX      0 softfluent-com.mail.protection.outlook.com.

To query the DNS server in .NET, you can use the NuGet package DnsClient (GitHub) which support .NET and .NET Core.

Task<bool> IsValidAsync(string email)
{
    try
    {
        var mailAddress = new MailAddress(email);
        var host = mailAddress.Host;
        return CheckDnsEntriesAsync(host);
    }
    catch (FormatException)
    {
        return Task.FromResult(false);
    }
}

async Task<bool> CheckDnsEntriesAsync(string domain)
{
    try
    {
        var lookup = new LookupClient();
        lookup.Timeout = TimeSpan.FromSeconds(5);
        var result = await lookup.QueryAsync(domain, QueryType.Any).ConfigureAwait(false);

        var records = result.Answers.Where(record => record.RecordType == DnsClient.Protocol.ResourceRecordType.A || 
                                                     record.RecordType == DnsClient.Protocol.ResourceRecordType.AAAA || 
                                                     record.RecordType == DnsClient.Protocol.ResourceRecordType.MX);
        return records.Any();
    }
    catch (DnsResponseException)
    {
        return false;
    }
}

Note: The MX record is not mandatory when the value of the A and MX records is the same. However, it's very common to have an MX record, so maybe you can remove the A and AAAA check.

Conclusion

You can quickly validate an email address by using a regex or a parser. If you want to go further, you can also query the DNS server of the recipient domain to ensure the domain exists and can receive emails. This allows to detect some typing mistakes in the domain part. However, this doesn’t guarantee the email address exists. Indeed, the only way to ensure an email address exists is by sending an email.

Gérald Barré