Mail Merge with DataTable in C# and VB.NET
Mail merge means creating multiple personalized email messages based on a single message template and a data source. The template message contains fixed text, which will be the same in every output message, and variables, which represent placeholders that values from a data source will replace.
You can execute a mail merge by using the MailMerge.Merge
method. Once started, the template message is cloned for every DataRow
in the DataTable
data source, but with the variables replaced by values from the current row.
With the following example, you will learn how to perform a mail merge to generate multiple personalized emails, using DataTable
as a data source.

using System.Collections.Generic;
using System.Data;
using GemBox.Email;
class Program
{
static void Main()
{
// If using the Professional version, put your serial key below.
ComponentInfo.SetLicense("FREE-LIMITED-KEY");
// Create template message.
MailMessage template = new MailMessage("sender@example.com");
template.Subject = "%FirstName%, check our new offer!";
template.BodyHtml =
@"<div>
Dear <strong>%Title% %LastName%</strong><br/><br/>
Check out our new offer on this <a href=""%link%"">link</a>.<br/>
<span style=""color:red;font-size:90%"">Visit us today and get additional %discount%% discount!</span><br/><br/>
Sincerely Yours,<br/>
Special Store<br/><br/>
<span style=""color:gray;font-size:80%"">This email was sent to <a href=""mailto:%To%"">%To%</a>.</span>
</div>";
// Create data source.
DataTable data = new DataTable();
data.Columns.Add("To", typeof(string));
data.Columns.Add("Title", typeof(string));
data.Columns.Add("FirstName", typeof(string));
data.Columns.Add("LastName", typeof(string));
data.Columns.Add("Discount", typeof(int));
data.Columns.Add("Link", typeof(string));
// Fill data source with some data.
data.Rows.Add("jonh@example.com", "Mr.", "John", "Doe", 10, "https://example.com/check.html?name=John");
data.Rows.Add("jane@example.com", "Mrs.", "Jane", "Doe", 20, "https://example.com/check.html?name=Jane");
data.Rows.Add("joe@example.com", "Mr.", "Joe", "Unknown", 15, "https://example.com/check.html?name=Joe");
// Perform mail merge operation.
IList<MailMessage> messages = MailMerge.Merge(template, data);
// Save mail messages.
for (int i = 0; i < messages.Count; i++)
messages[i].Save($"Message_{i}.eml");
}
}
Imports System.Collections.Generic
Imports System.Data
Imports GemBox.Email
Module Program
Sub Main()
' If using the Professional version, put your serial key below.
ComponentInfo.SetLicense("FREE-LIMITED-KEY")
' Create template message.
Dim template As New MailMessage("sender@example.com")
template.Subject = "%FirstName%, check our new offer!"
template.BodyHtml =
"<div>
Dear <strong>%Title% %LastName%</strong><br/><br/>
Check out our new offer on this <a href=""%link%"">link</a>.<br/>
<span style=""color:red;font-size:90%"">Visit us today and get additional %discount%% discount!</span><br/><br/>
Sincerely Yours,<br/>
Special Store<br/><br/>
<span style=""color:gray;font-size:80%"">This email was sent to <a href=""mailto:%To%"">%To%</a>.</span>
</div>"
' Create data source.
Dim data As New DataTable()
data.Columns.Add("To", GetType(String))
data.Columns.Add("Title", GetType(String))
data.Columns.Add("FirstName", GetType(String))
data.Columns.Add("LastName", GetType(String))
data.Columns.Add("Discount", GetType(String))
data.Columns.Add("Link", GetType(String))
' Fill data source with some data.
data.Rows.Add("jonh@example.com", "Mr.", "John", "Doe", 10, "https://example.com/check.html?name=John")
data.Rows.Add("jane@example.com", "Mrs.", "Jane", "Doe", 20, "https://example.com/check.html?name=Jane")
data.Rows.Add("joe@example.com", "Mr.", "Joe", "Unknown", 15, "https://example.com/check.html?name=Joe")
' Perform mail merge operation.
Dim messages As IList(Of MailMessage) = MailMerge.Merge(template, data)
' Save mail messages.
For i As Integer = 0 To messages.Count - 1
messages(i).Save($"Message_{i}.eml")
Next
End Sub
End Module
It’s also possible to use the MailMessage
object as a template message, where MailMessage.Subject
, MailMessage.BodyText
, MailMessage.BodyHtml
, and body of any MailMessage.MimeEntity.Headers
can contain fixed text and variables.
Variables are defined as %<ValueName>%. The value name can contain letters or digits, without any whitespace, and must start and end with the '%'
character.
%To%
, %Cc%
, %Bcc%
and %ReplyTo%
are predefined value names you can use to set the corresponding properties in the output message. All predefined names are optional except %To%
since it represents the recipient's email address.