EmailAddressValidator Class
Provides means for bulk verification of e-mail addresses.
Inheritance Hierarchy
SystemObject
  MailBee.AddressCheckEmailAddressValidator

Namespace: MailBee.AddressCheck
Assembly: MailBee.NET (in MailBee.NET.dll) Version: 12.4 build 677 for .NET 4.5
Syntax
public class EmailAddressValidator : IComponent, 
	IDisposable

The EmailAddressValidator type exposes the following members.

Constructors
  NameDescription
Public methodEmailAddressValidator
Creates an instance of EmailAddressValidator class.
Public methodEmailAddressValidator(String)
Creates and unlocks an instance of EmailAddressValidator class.
Top
Methods
  NameDescription
Public methodAbort
Forces MailBee to cancel all pending operations and close all opened connections as soon as possible.
Public methodCode exampleArrayToDataTable
Converts a string array into DataTable containing a single column named "email".
Public methodCode exampleBeginVerify Obsolete.
Begins an asynchronous request for verifying a bulk of e-mails addresses.
Public methodDispose
Closes opened network connections (if any) and releases any used system resources.
Protected methodDispose(Boolean)
When overridden in a derived class, must release unmananged and optionally managed resources used by the component.
Public methodEndVerify
Ends the pending asynchronous request for verification of e-mail addresses.
Public methodEquals
Determines whether the specified object is equal to the current object.
(Inherited from Object.)
Protected methodFinalize
Allows an object to try to free resources and perform other cleanup operations before it is reclaimed by garbage collection.
(Inherited from Object.)
Public methodGetHashCode
Serves as the default hash function.
(Inherited from Object.)
Public methodGetType
Gets the Type of the current instance.
(Inherited from Object.)
Protected methodMemberwiseClone
Creates a shallow copy of the current Object.
(Inherited from Object.)
Protected methodOnDataReceived
Used by MailBee to raise DataReceived event.
Protected methodOnDataSent
Used by MailBee to raise DataSent event.
Protected methodOnErrorOccurred
Used by MailBee to raise ErrorOccurred event.
Protected methodOnLogNewEntry
Used by MailBee to raise LogNewEntry event.
Protected methodOnVerified
Used by MailBee to raise Verified event.
Protected methodOnVerifying
Used by MailBee to raise Verifying event.
Public methodResetState
Resets the internal state of the component.
Public methodToString
Returns a string that represents the current object.
(Inherited from Object.)
Public methodCode exampleVerify(String)
Validates a single e-mail address for correct syntax and, optionally, checks it for existence.
Public methodCode exampleVerify(String)
Validates e-mail addresses in the string array given.
Public methodCode exampleVerify(DataTable, String)
Validates e-mail addresses in the data table given.
Public methodCode exampleVerify(IDataReader, String)
Validates e-mail addresses supplied by the data reader.
Public methodVerifyAsync(String)
async/await version of Verify(String).
Public methodVerifyAsync(String)
Public methodVerifyAsync(DataTable, String)
async/await version of Verify(DataTable, String).
Public methodVerifyAsync(IDataReader, String)
async/await version of Verify(IDataReader, String).
Top
Properties
  NameDescription
Public propertyDnsServers
Gets the DnsServerCollection object containing the list of DNS servers to be used for DNS MX lookup.
Public propertyHelloDomain
Gets or sets the domain string to use as an argument of HELO or EHLO commands when making test connections to SMTP MX servers.
Public propertyIsAborted
Indicates whether Abort method has been called for the component.
Public propertyIsBusy
Indicates whether the component is performing a lengthy operation.
Public propertyLocalEndPoint
Gets or sets the local end point which will be used when connecting to SMTP MX servers.
Public propertyCode exampleLog
Gets the object used for logging MailBee activities into a file or memory buffer.
Public propertyMailFrom
Gets or sets the string to be used as sender when making test connections to SMTP MX servers.
Public propertyMaxThreadCount
Gets or sets the maximum number of threads MailBee may create during bulk verification of e-mail addresses' operations.
Public propertyPipelining
Gets or sets whether to use commands pipelining if it's supported by the SMTP MX server.
Public propertyRaiseEvents
Gets or sets whether the component will raise any events.
Public propertyRegexPattern
Gets or sets the regular expression to check syntax of e-mail addresses.
Public propertySite
Gets or sets the object to be used as a site for the component.
Public propertySmtpTimeout
Gets or sets the amount of time (in milliseconds) the component will wait for a response from the SMTP MX server.
Public propertySynchronizingObject
Gets or sets the object used to marshal the calls of the event handlers.
Public propertyTrialDaysLeft
Gets the number of days left to the date of the trial license key expiration.
Public propertyValidationLevel
Gets or sets the level of deepness of e-mail address verification.
Public propertyVersion
Gets the version of the MailBee assembly.
Top
Events
  NameDescription
Public eventCode exampleDataReceived
Occurs when data is received from the network.
Public eventCode exampleDataSent
Occurs when data is sent to the network.
Public eventDisposed
Occurs after the component was disposed.
Public eventErrorOccurred
Occurs when MailBeeException is thrown internally.
Public eventCode exampleLogNewEntry
Occurs when an entry is written into the log file (or into the memory buffer if EmailAddressValidator.Log.MemoryLog is true).
Public eventCode exampleVerified
Occurs once an e-mail addresses in a bulk series has been verified.
Public eventCode exampleVerifying
Occurs when an e-mail address in a bulk series is about to be verified.
Top
Remarks

This class can validate single addresses and their lists (string array and DataTable are accepted). If your data source is different, you can also create and populate DataTable manually, using ArrayToDataTable(String) method.

There are several levels of verification: syntax check with a regular expression, DNS MX lookup of the domain part of the address, test connection to the SMTP MX server responsible for delivering e-mail to the given domain, and test send attempt (which means not only the connection is made but also the sender and the recipient are submitted to the server). Even in "send attempt" mode, the component does not actually send any e-mails, it stops at the point where the server accepted the given e-mail address as the valid recipient's address. How deep the verification will be is controlled with ValidationLevel property.

You can implement black and white listing of any e-mail addresses or domains in your collection by subscribing to Verifying event. It lets you skip any e-mails from verification, based on your criteria.

By default, the component works in single-thread mode. If you need to verify multiple addresses, you can greatly improve performance by setting MaxThreadCount property. Up to 60 threads are supported.

Note Note
Due to anti-spam filters on many servers, direct validation of e-mail addresses via making test connections and send attempts is not always 100% accurate (there can be both false positives and false negatives). See AddressValidationLevel topic for more details on how to deal with this.

For more info and tutorials, refer to Getting started with Address Validator guide.

Note Note
Database-related functionality is not available in .NET Core and UWP (only single e-mail addresses can be validated there).
Examples

This advanced sample reads and parses the list of e-mail addresses from C:\Temp\input.txt file (creating file it it's missing), performs blacklist check to remove all addresses ending with "@blacklisted.com", and verifies other addresses. Addresses with bad syntax are removed immediately, those which failed due to network errors are given second and third chance. Each run of the app performs a new check on the same list. In the end, no addresses will remain in the list as all the addresses there are fake (you can add real addresses so that the list wouldn't get empty).

For simpler (but less accurate and flexible) examples, refer to Verify(String) or Verified topics.

For clarity of its functioning, this sample does not use multi-threading (MaxThreadCount remains the default value, 1). In production, multi-threading is highly recommended for performance sake.

using System;
using System.IO;
using System.Data;
using MailBee;
using MailBee.AddressCheck;

class Program
{
    const string EmailColumn = "email";
    const string FailureCountColumn = "failures";
    private static StreamWriter sw = null;

    // Builds the data table from the file contents.
    // For brevity, we don't check if the data has correct format.
    private static DataTable GetDataTable(string[] lines)
    {
        DataTable workTable = new DataTable();
        workTable.Columns.Add(EmailColumn, typeof(string));
        workTable.Columns.Add(FailureCountColumn, typeof(int));

        foreach (string line in lines)
        {
            string[] parts = line.Split(',');
            DataRow row = workTable.NewRow();
            row[EmailColumn] = parts[0];
            row[FailureCountColumn] = int.Parse(parts[1]);
            workTable.Rows.Add(row);
        }

        return workTable;
    }

    // This method will be executed for each e-mail address in the bulk,
    // whenever it gets verified. Those addresses for which we set VerifyIt
    // to 'false' will be skipped from further verification and Verified
    // event won't occur for them.
    private static void valid_Verifying(object sender, VerifyingEventArgs e)
    {
        try
        {
            Console.WriteLine(string.Format("{0} is being checked against blacklist.", e.Email));

            if (e.Email.EndsWith("@blacklisted.com"))
            {
                // Exclude it from address checking by other methods, and forget it.
                e.VerifyIt = false;
                Console.WriteLine(string.Format("{0} removed due to blacklist hit.", e.Email));
            }

            if (e.VerifyIt)
            {
                Console.WriteLine(string.Format("{0} survived blacklist check.", e.Email));
            }
            else
            {
                Console.WriteLine(string.Format("Discarded: {0}", e.Email));
            }
        }
        catch (Exception ex)
        {
            // At least for debug purposes, it makes sense to catch all exceptions in
            // event handlers as uncaught exceptions here don't cause the app to crash.
            // Without this try/catch, it could be quite hard to understand what went wrong
            // as you'd see no indication of a problem, the event handler would silently
            // die in the middle but the app itself would continue.
            Console.WriteLine(ex.ToString());
        }

        Console.WriteLine();
    }

    // All those e-mail addresses which survived Verifying event handler then get validated,
    // and the validation results (which can be both successful or negative) will be delivered
    // to the application through Verified event handler.
    private static void valid_Verified(object sender, VerifiedEventArgs e)
    {
        try
        {
            // Keep the address on the list?
            bool keepIt;

            Console.WriteLine(string.Format("{0}={1}", e.Email, e.Result.ToString()));
            if (e.Reason != null)
            {
                Console.WriteLine("Reason: " + e.Reason.Message);
            }
            int failureCount = (int)e.Row[FailureCountColumn];
            switch (e.Result)
            {
                case AddressValidationLevel.OK:
                    // Address is fine, reset the failure counter if needed.
                    if (failureCount != 0)
                    {
                        failureCount = 0;
                    }
                    keepIt = true;
                    break;
                case AddressValidationLevel.RegexCheck:
                    // Bad syntax, won't keep this address in the list.
                    keepIt = false;
                    break;
                default:
                    failureCount++;
                    if (failureCount > 3)
                    {
                        // Too many failed attempts. Forget this address.
                        keepIt = false;
                    }
                    else
                    {
                        // Give the address another chance.
                        keepIt = true;
                    }
                    break;
            }

            if (keepIt)
            {
                sw.WriteLine(string.Format("{0},{1}", e.Email, failureCount.ToString()));
                Console.WriteLine(string.Format("Written to the file: {0},{1}",
                    e.Email, failureCount.ToString()));
            }
            else
            {
                Console.WriteLine(string.Format("Discarded: {0}", e.Email));
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.ToString());
        }

        Console.WriteLine();
    }

    static void Main(string[] args)
    {
        EmailAddressValidator valid = new EmailAddressValidator("MN110-0123456789ABCDEF-0123");

        // To perform DNS MX lookup queries, we need some DNS servers for that.
        valid.DnsServers.Autodetect();

        // Logging into a file is not required for the component to work
        // but helpful for debugging and understanding things under the hood.
        valid.Log.Enabled = true;
        valid.Log.Filename = @"C:\Temp\log.txt";
        valid.Log.Clear();

        // Subscribe to events.
        valid.Verifying += new VerifyingEventHandler(valid_Verifying);
        valid.Verified += new VerifiedEventHandler(valid_Verified);

        string inputFile = @"C:\Temp\input.txt";
        string outputFile = @"C:\Temp\output.txt";

        // Create a file with some e-mail addresses to check if it's not already there.
        if (!File.Exists(inputFile))
        {
            // Number is a count of failed attempts to check an address. If it exceeds 3, we'll
            // remove the address from the list. Addresses with invalid syntax will be removed
            // immediately.
            File.WriteAllText(inputFile,
@"john.doe@domain.com,0
user@blacklisted.com,0
alice@company.com,0
somebody@non-exisent.domain,0
bob@incorrect-syntax,0
sarah@example.com,0");
        }

        string[] lines = File.ReadAllLines(inputFile);

        if (lines.Length == 0)
        {
            Console.WriteLine("No addresses left in the list! Delete input.txt and try again.");
        }

        using (sw = new StreamWriter(outputFile))
        {
            // Run the verification in single-threaded mode (for clarity of console output).
            valid.Verify(GetDataTable(lines), EmailColumn);
        }

        // Once the verification finished, replace the input file with the recently generated.
        // This way, we'll refine our list each time the app is run. After several runs, only
        // good addresses will remain.
        File.Delete(inputFile);
        File.Move(outputFile, inputFile);
    }
}
See Also