EmailAddressValidatorVerify Method (IDataReader, String)
Validates e-mail addresses supplied by the data reader.

Namespace: MailBee.AddressCheck
Assembly: MailBee.NET (in MailBee.NET.dll) Version: 12.5.0 build 687 for .NET 4.5
Syntax
public void Verify(
	IDataReader emails,
	string columnName
)

Parameters

emails
Type: System.DataIDataReader
The data reader, in columnName column containing the e-mail addresses to check for syntax and, optionally, for existence.
columnName
Type: SystemString
The name of column in the given data reader, containing the e-mail addresses.
Exceptions
ExceptionCondition
MailBeeInvalidArgumentExceptionemails or columnName is a null reference (Nothing in Visual Basic), columnName is an empty string, or DnsServers collection is empty.
MailBeeUserAbortExceptionThe user code has aborted the component with Abort method.
Remarks

To analyze the results, subscribe to Verified event. To implement blacklist or whitelist, subscribe to Verifying event.

For more info and tutorials, refer to Getting started with Address Validator guide or examine AddressValidatorDemo sample project in MailBee.NET Samples folder.

Examples

This sample takes e-mail addresses from 'emails' table contained in an MS SQL Server database, and verifies them. The table must have numeric 'id' and string (such as nvarchar) 'email' fields.

Multi-threading is in use, and the sample works in the way that it's compatible with forward-only database cursors. Despite of many concurrent threads, the code accesses each data row only once in the sequential order. Once a row has been read, the component remembers the data from it in a temporary storage for later use. Thus, it's safe to advance the data reader and lose the context of the current record as its data are already cached. The component then exposes the cached data to the application code through event handlers. The sample uses this data to implement blacklisting and whitelisting and to report 'id' values of all records being processed, to the console. Read DataReader topic for more info on accessing data reader directly or cached data, in event handlers.

The sample does not save the results of verification in the database. See AddressValidatorDemo sample project if you need this, or browse other code snippets in Getting started with Address Validator guide.

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

class Program
{
    const string SqlDataSource = @"(local)\SQLEXPRESS";
    const string SqlDatabase = "afterlogic";
    const string SqlTable = "emails";
    const string EmailColumn = "email";
    const string IdColumn = "id";

    // Set to false to see another method of reading data from data row in event handlers.
    // Also, when false, it would be much easier to understand the console output as lines
    // from different threads won't mix. Still, 'id' field should help you understand to
    // which email address certain output line corresponds, even in multi-threaded mode.
    const bool EnableMultiThreading = true;

    static SqlConnection _sqlConnection;
    static SqlDataReader _dataReader;
    static SqlCommand _cmd;

    // Gets the data from SQL database. You must have a table such as the one made by
    // AddressValidatorDemo sample project, available in "MailBee.NET Objects\Samples\WinForms"
    // folder of "My Documents" (you can find this folder by clicking "Browse WinForms Samples"
    // button in "MailBee.NET Start Menu").
    // 
    // The "emails" table needs to have at least "id" field (numeric) and "email" field
    // (nvarchar or other string type), and some rows in it.
    private static void OpenDataReader()
    {
        SqlConnectionStringBuilder connStringBuilder = new SqlConnectionStringBuilder();
        connStringBuilder.DataSource = SqlDataSource;
        connStringBuilder.InitialCatalog = SqlDatabase;

        // Change this to use SQL Server authentication.
        connStringBuilder.IntegratedSecurity = true;

        // In AddressValidatorDemo, we need MultipleActiveResultSets because we're reading and
        // writing data in the same SQL connection. But in this sample we don't write anything
        // to the SQL server. Thus, we don't need MultipleActiveResultSets functionality.

        // Should you need to write to the database, create separate SqlConnection for that
        // or uncomment the next line.

        // connStringBuilder.MultipleActiveResultSets = true;

        _sqlConnection = new SqlConnection(connStringBuilder.ConnectionString);
        _sqlConnection.Open();
        _cmd = _sqlConnection.CreateCommand();
        _cmd.CommandText = "SELECT * FROM " + SqlTable;
        _dataReader = _cmd.ExecuteReader();
    }

    private static void FreeDataReader()
    {
        if (_dataReader != null)
        {
            _dataReader.Close();
            _dataReader = null;
        }
        if (_cmd != null)
        {
            _cmd.Dispose();
            _cmd = null;
        }
        if (_sqlConnection != null)
        {
            _sqlConnection.Close();
            _sqlConnection = null;
        }
    }

    // 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. This is true for both blacklist and whitelist, in either
    // case we don't need to process the e-mail address deeper if it's already on any of these lists.
    private static void valid_Verifying(object sender, VerifyingEventArgs e)
    {
        try
        {
            // See valid_Verified for explanations.
            int id = (int)e.DataReaderRowValues[0];

            string idStr = id.ToString();

            Console.WriteLine(string.Format("{0}: {1} is being checked against blacklist.",
                idStr, e.Email));

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

            if (e.Email.EndsWith("@server.com"))
            {
                // Exclude it from address checking by other methods, and forget it.
                e.VerifyIt = false;
                Console.WriteLine(string.Format("{0}: {1} does not checking as it's on blacklist.",
                    idStr, e.Email));
            }

            if (e.VerifyIt)
            {
                Console.WriteLine(string.Format("{0}: {1} survived blacklist check and not on whitelist.",
                    idStr, e.Email));
            }
            else
            {
                Console.WriteLine(string.Format("{0}: {1} skipped from further verification.",
                    idStr, 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());
        }

        if (!EnableMultiThreading)
        {
            // See valid_Verified for explanations.
            Console.WriteLine();
        }
    }

    // All those e-mail addresses which passed 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
        {
            int id;

            if (EnableMultiThreading)
            {
                // Demonstrate taking 'id' field. Unlike DataTable, IDataReader does not always permit
                // access to a data row for more than once (which happens when MailBee reads data from it).
                // Luckily, MailBee saves the data row it has read, for later use. That's how you can use it.
                id = (int)e.DataReaderRowValues[0];

                // Or, if we didn't know that 'id' is column #0, we could find it by name:
                id = (int)e.DataReaderRowValues[Array.IndexOf(e.DataReaderColumnNames, "id")];
            }
            else
            {
                // Who said that it's not possible to read from any IDataReader any number of times? Actually,
                // SqlDataReader allows us to read a current row as many times as we want. The only issue is
                // that when the app is multi-threaded, another thread may already advance the reader to the
                // next position and we won't have right data here. But when there is only one thread using
                // the data reader, it's not a problem to read directly from it.
                // 
                // Note that it's always safe to use reading from DataReaderRowValues. Just in case if for
                // some reason your app is single-threaded and for a very special reason you need to access
                // IDataReader directly, you now know how to do it.
                id = (int)_dataReader.GetValue(0);

                // Or by name.
                id = (int)_dataReader.GetValue(_dataReader.GetOrdinal("id"));
            }

            string idStr = id.ToString();

            // That's where we display the determined validation level at which the process failed, or OK.
            Console.WriteLine(string.Format("{0}: email={1}, result={2}",
                idStr, e.Email, e.Result.ToString()));

            if (e.Reason != null)
            {
                Console.WriteLine(string.Format("{0}: Reason is: {1}", idStr, e.Reason.Message));
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.ToString());
        }

        if (!EnableMultiThreading)
        {
            // Adding empty lines for clarity at the end of an event handler (to visually separate
            // processing of individual e-mail addresses) makes sense only in single-threaded mode.
            // When multi-threading is on, output from different thread mixes and makes inserting
            // empty lines useless.
            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);

        if (EnableMultiThreading)
        {
            valid.MaxThreadCount = -1;
        }

        try
        {
            OpenDataReader();

            // Run the verification in multi-threaded or single-threaded mode
            // (adjust EnableMultiThreading const to change the mode).
            valid.Verify(_dataReader, EmailColumn);
        }
        finally
        {
            FreeDataReader();
        }
    }
}
See Also