SmtpSendMailMerge Method (String, EmailAddressCollection, IDataReader)
Creates a series of e-mails based on an e-mail message template and a data reader and sends these e-mails out.

Namespace: MailBee.SmtpMail
Assembly: MailBee.NET (in MailBee.NET.dll) Version: 12.4 build 677 for .NET 4.5
Syntax
public bool SendMailMerge(
	string senderEmailPattern,
	EmailAddressCollection recipientsPattern,
	IDataReader mergeDataReader
)

Parameters

senderEmailPattern
Type: SystemString
The e-mail address template of the sender. If it's a null reference (Nothing in Visual Basic), the e-mail address template will be taken from From property.
recipientsPattern
Type: MailBee.MimeEmailAddressCollection
The pattern of the message recipients. If it's a null reference (Nothing in Visual Basic), the recipients list is combined from To, Cc, and Bcc lists.
mergeDataReader
Type: System.DataIDataReader
The data source for mail merge.

Return Value

Type: Boolean
true if the entire mail merge has been processed; false if the operation was stopped due to an error.
Exceptions
ExceptionCondition
MailBeeExceptionAn error occurred and ThrowExceptions is true.
Remarks

This method is a version of SendMailMerge(string, EmailAddressCollection, DataTable) overload which accepts IDataReader rather than DataTable as input. This may be handy for dealing with large recordsets which would not fit in memory in case of DataTable.

However, such readers like SqlDataReader can represent forward-only cursors which cannot be accessed on arbitrary basis. This imposes some limitations on using this overload, for instance, you cannot use RetryFailedJobs to process the data reader another time because the reader does not remember the rows which have already been read before and needs to be re-created for that.

Multi-threaded usage of forward-only data readers is also limited but MailBee has some means to overcome this. The code sample in this topic shows how to access data from a data reader in event handlers in case if many threads are reading from the reader and the app cannot rely on the current row position.

Note Note
Mail merge over database is not supported in .NET Core and UWP editions yet. This method is not available there.
Examples
This console sample is a version of the same sample in SendMailMerge(string, EmailAddressCollection, DataTable) overload but uses SqlDataReader (and MS SQL Server database) as input.
using System;
using System.Data;
using System.Data.SqlClient;
using MailBee;
using MailBee.Mime;
using MailBee.SmtpMail;

class Sample
{
    // Reports readiness to start sending an e-mail.
    static void mailer_SendingMessage(object sender, SmtpSendingMessageEventArgs e)
    {
        // Display e-mail address of the e-mail to be sent.
        Console.WriteLine(e.MergeDataReaderRowValues[1].ToString() + " IS BEING SENT");
    }

    // Reports successful attempt of sending mail merge e-mail.
    static void mailer_MessageSent(object sender, SmtpMessageSentEventArgs e)
    {
        // Display e-mail address of the successful e-mail.
        Console.WriteLine(e.MergeDataReaderRowValues[1].ToString() + " SUCCEEDED");
    }

    // Reports failed attempt of sending mail merge e-mail.
    static void mailer_MessageNotSent(object sender, SmtpMessageNotSentEventArgs e)
    {
        // Display e-mail address of the failed e-mail.
        Console.WriteLine(e.MergeDataReaderRowValues[1].ToString() + " FAILED");
    }

    static void Main(string[] args)
    {
        Smtp mailer = new Smtp();

        // Logging into a file is useful for troubleshooting.
        mailer.Log.Filename = @"C:\Temp\log.txt";
        mailer.Log.Enabled = true;
        mailer.Log.Format = LogFormatOptions.AddContextInfo;
        mailer.Log.Clear();

        // Uncomment the line below to use unlimited number of worker threads (up to 60)
        // and increase performance. Note that not all SMTP servers support this.

        // mailer.MaxThreadCount = -1;

        // Subscribe to events to track send bulk mail progress.
        mailer.SendingMessage += new SmtpSendingMessageEventHandler(mailer_SendingMessage);
        mailer.MessageSent += new SmtpMessageSentEventHandler(mailer_MessageSent);
        mailer.MessageNotSent += new SmtpMessageNotSentEventHandler(mailer_MessageNotSent);

        // Setup SMTP server parameters.
        mailer.SmtpServers.Add("mail.domain.com", "jdoe@domain.com", "secret");

        // Uncomment next line if ESMTP CHUNKING causes problems with your server (usually, with MS Exchange).
        // mailer.SmtpServers[0].SmtpOptions = ExtendedSmtpOptions.NoChunking;

        // Setup e-mail message header template for mail merge.
        mailer.Message.From.AsString = "John Doe <john.doe@domain.com>";
        mailer.Message.To.AsString = "##Email##";
        mailer.Message.Subject = "Our Jan/2007 newsletter";

        // Setup HTML body template.
        mailer.Message.BodyHtmlText = "<html>##Body##</html>";

        // Specify database connection string (it may be different in your case).
        string connParams = @"server=(local)\SQLEXPRESS;Initial Catalog=afterlogic;Integrated Security=True";

        using (SqlConnection conn = new SqlConnection(connParams))
        {
            conn.Open();
            using (SqlCommand command = conn.CreateCommand())
            {
                // The 'mailing_list' table or query must have these fields:
                // #0: ID (int)
                // #1: Email (nvarchar)
                // #2: Name (nvarchar)
                // #3: Body (nvarchar)
                // Table row example: 175, "jdoe@domain.com", "John", "Some text".
                command.CommandText = "SELECT * FROM mailing_list";

                // Populate mail merge job to-do list with from the specified table.
                using (SqlDataReader reader = command.ExecuteReader())
                {

                    // Create and run a job which is the following task for MailBee: perform mail merge
                    // over the specified data table and then send out each resulting e-mail to
                    // the recipients which appear in the resulting messages.
                    // "bounce_Jan2007_<ID>@domain.com" (where <ID> is mailing_list.ID)
                    // address will be used as Return-Path (i.e. sender e-mail address).
                    // If there is a wildcard mailbox "bounce_Jan2007_*@domain.com", possible bounces
                    // will arrive to this mailbox and have "From:" like "bounce_Jan2007_1@domain.com",
                    // "bounce_Jan2007_4908@domain.com", etc and the application can then poll this
                    // wildcard mailbox to unsubscribe records #1 and #4908 from database.
                    mailer.SendMailMerge("bounce_Jan2007_##ID##@domain.com", null, reader);
                }
            }
        }
    }
}
See Also