SmtpSendMailMerge Method (String, EmailAddressCollection, DataTable)
Creates a series of e-mails based on an e-mail message template and a data table 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
public bool SendMailMerge(
	string senderEmailPattern,
	EmailAddressCollection recipientsPattern,
	DataTable mergeTable


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.
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.
Type: System.DataDataTable
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.
MailBeeExceptionAn error occurred and ThrowExceptions is true.

Use this method to prepare the mail merge task (job) and immediately process it. SendMailMerge(String, EmailAddressCollection, DataTable) method simply calls AddJob(String, String, EmailAddressCollection, DataTable) and then SendJobs.

Note Note
Mail merge over database is not supported in .NET Core and UWP editions yet. This method in not available these.

If JobsPending queue already contained some jobs to the moment of SendMailMerge(String, EmailAddressCollection, DataTable) call, these jobs will be processed too.

To sign each outgoing e-mail with DomainKeys/DKIM signature, subscribe to SendingMessage event and call e.MailMessage.DomainKeysSign in the event handler (assuming e is SmtpSendingMessageEventArgs parameter of the event handler).

By default, SendMailMerge(String, EmailAddressCollection, DataTable) method won't stop if any e-mail message in the mail merge series failed to be sent. Thus, the method always succeeds. The developer can use MessageSent and MessageNotSent events to keep track of successful and failed e-mails while SendMailMerge(String, EmailAddressCollection, DataTable) method is in progress, or examine JobsSuccessful and JobsFailed collections after SendMailMerge(String, EmailAddressCollection, DataTable) completes.

However, it's possible to make SendMailMerge(String, EmailAddressCollection, DataTable) method fail if any of the e-mails in the series fail to be sent. To achieve this, set StopJobsOnError to true prior to calling SendMailMerge(String, EmailAddressCollection, DataTable).

If any e-mails within the mail merge job failed to be sent, the developer can use RetryFailedJobs method to put all failed send-mail jobs back from JobsFailed into JobsPending and then call SendJobs to try sending them out again. Note that RetryFailedJobs will work for this overload which uses DataTable as input but won't work for SendMailMerge(string, EmailAddressCollection, IDataReader) version.

Re-sending failed e-mails can be repeated multiple times, and it's allowed to use different sending methods each time. For instance, the developer can change SMTP relay server, try direct sending via DNS MX lookup, or even save e-mails as files for later delivery using SubmitJobsToPickupFolder(String, Boolean) method.

In the case if the application shuts down after performing mail merge (so there is no way to call RetryFailedJobs next time when the application starts since all the data has been lost), the application should save information regarding failed e-mails in a persistent storage such as database. For mail merge, there is no need to save the entire e-mails because the only thing which differs e-mails from each other is an index of a row in the data table which was used to create an e-mail from the template. Thus, it's enough to save data row indices only and then load them next time (provided that the template and the data table will be the same). See AddJob(String, String, EmailAddressCollection, DataTable, Object, Boolean, Boolean) topic for the code sample.

This console sample sends out a newsletter. Events are used to keep track of the mailing. E-mails are sent from "Return-Path" address different from "From:" address. This makes it easier to process bounced messages because each bounced message (produced for mail merge messages which could not be delivered) is sent to "Return-Path" address rather than "From:" address. Thus, each bounced message will have ID of the failed mail merge row in its "From:" field (and this "From:" will be taken from "Return-Path" of the originating e-mails).
using System;
using System.Data;
using System.Data.OleDb;
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.MergeTable.Rows[e.MergeRowIndex]["Email"] + " 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.MergeTable.Rows[e.MergeRowIndex]["Email"] + " 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.MergeTable.Rows[e.MergeRowIndex]["Email"] + " 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;

        // 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("", "jdoe", "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 <>";
        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 = @"Provider=Microsoft.Jet.OLEDB.4.0; Data Source=C:\Temp\newsletter.mdb;";

        DataTable table = new DataTable();

        // Connect to the database and populate mail merge job to-do list with
        // the data from "mailing_list" table.
        using (OleDbConnection conn = new OleDbConnection(connParams))
            // Open the connection and get the data.
            OleDbCommand command = new OleDbCommand("SELECT * FROM mailing_list", conn);
            OleDbDataAdapter adapter = new OleDbDataAdapter();
            adapter.SelectCommand = command;

        // 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>" (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_*", possible bounces
        // will arrive to this mailbox and have "From:" like "",
        // "", etc and the application can then poll this
        // wildcard mailbox to unsubscribe records #1 and #4908 from database.
        mailer.SendMailMerge("", null, table);
See Also