Send Bulk (Mass) Email in C# and VB.NET

Sending mass numbers of emails (bulk email) to a group of addresses is typically done for advertising or marketing purposes (e.g., subscription notifications, broadcast advertising, marketing campaigns, etc.).

The following example shows how you can send large quantities of emails using C# or VB.NET code. The emails are sent asynchronously so that the application isn't blocked or halted and with multiple threads to improve performance.

Screenshot of mass email sending
Sending builk email in C# and VB.NET
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using GemBox.Email;
using GemBox.Email.Smtp;

class Program
{
    const string Host = "<HOST>";
    const string Username = "<USERNAME>";
    const string Password = "<PASSWORD>";
    const string Sender = "<ADDRESS>";

    static int SentEmailCounter = 0;

    static void Main()
    {
        // If using Professional version, put your serial key below.
        ComponentInfo.SetLicense("FREE-LIMITED-KEY");

        var mailingList = new List<string>()
        {
            "first.receiver@example.com",
            "second.receiver@example.com",
            "third.receiver@example.com",
            "..."
        };

        int chunkSize = 80;

        // Split "mailingList" to multiple lists of "chunkSize" size.
        var mailingChunks = SplitMany(mailingList, chunkSize);

        // Process each "mailingChunks" chunk as a separate Task.
        IEnumerable<Task> sendMailingChunks = mailingChunks.Select(
            mailingChunk => Task.Run(() => SendEmails(mailingChunk)));

        // Create a Task that will complete when emails were sent to all the "mailingList".
        Task sendBuilkEmails = Task.WhenAll(sendMailingChunks);

        // Displaying the progress of bulk email sending.
        while (!sendBuilkEmails.IsCompleted)
        {
            Console.WriteLine($"{SentEmailCounter,5} emails have been sent!");
            Task.Delay(1000).Wait();
        }
    }

    static void SendEmails(IEnumerable<string> recipients)
    {
        using (var smtp = new SmtpClient(Host))
        {
            smtp.Connect();
            smtp.Authenticate(Username, Password);

            foreach (var recipient in recipients)
            {
                MailMessage message = new MailMessage(Sender, recipient)
                {
                    Subject = "New Blog Post",
                    BodyText = "Dear reader,\n" +
                        "We have released a new blog post.\n" +
                        "You can find it on: https://www.gemboxsoftware.com/company/blog"
                };

                smtp.SendMessage(message);
                Interlocked.Increment(ref SentEmailCounter);
            }
        }
    }

    static List<List<string>> SplitMany(List<string> source, int size)
    {
        var sourceChunks = new List<List<string>>();

        for (int i = 0, i < source.Count; i += size)
            sourceChunks.Add(source.GetRange(i, Math.Min(size, source.Count - i)));

        return sourceChunks;
    }
}
Imports System
Imports System.Collections.Generic
Imports System.Linq
Imports System.Threading
Imports System.Threading.Tasks
Imports GemBox.Email
Imports GemBox.Email.Smtp

Module Program

    Const Host As String = "<HOST>"
    Const Username As String = "<USERNAME>"
    Const Password As String = "<PASSWORD>"
    Const Sender As String = "<ADDRESS>"

    Dim SentEmailCounter As Integer = 0

    Sub Main()

        ' If using Professional version, put your serial key below.
        ComponentInfo.SetLicense("FREE-LIMITED-KEY")

        Dim mailingList As New List(Of String)() From
        {
            "first.receiver@example.com",
            "second.receiver@example.com",
            "third.receiver@example.com",
            "..."
        }

        Dim chunkSize As Integer = 80

        ' Split "mailingList" to multiple lists of "chunkSize" size.
        Dim mailingChunks = SplitMany(mailingList, chunkSize)

        ' Process each "mailingChunks" chunk as a separate Task.
        Dim sendMailingChunks As IEnumerable(Of Task) = mailingChunks.Select(
            Function(mailingChunk) Task.Run(Sub() SendEmails(mailingChunk)))

        ' Create a Task that will complete when emails were sent to all the "mailingList".
        Dim sendBuilkEmails As Task = Task.WhenAll(sendMailingChunks)

        ' Displaying the progress of bulk email sending.
        While Not sendBuilkEmails.IsCompleted
            Console.WriteLine($"{SentEmailCounter} emails have been sent!")
            Task.Delay(1000).Wait()
        End While
    End Sub

    Sub SendEmails(ByVal recipients As IEnumerable(Of String))

        Using smtp As New SmtpClient(Host)
            smtp.Connect()
            smtp.Authenticate(Username, Password)

            For Each recipient In recipients
                Dim message As New MailMessage(Sender, recipient) With
                {
                    .Subject = "New Blog Post",
                    .BodyText = "Dear reader," & vbLf &
                        "We have released a new blog post." & vbLf &
                        "You can find it on: https://www.gemboxsoftware.com/company/blog"
                }

                smtp.SendMessage(message)
                Interlocked.Increment(SentEmailCounter)
            Next
        End Using

    End Sub

    Function SplitMany(ByVal source As List(Of String), ByVal size As Integer) As List(Of List(Of String))

        Dim sourceChunks As New List(Of List(Of String))()

        For i As Integer = 0 To source.Count - 1 Step size
            sourceChunks.Add(source.GetRange(i, Math.Min(size, source.Count - i)))
        Next

        Return sourceChunks

    End Function

End Module

Task based asynchronous programming can enable you to execute a non-blocking parallel or multi-threaded processing of your mailing list.

A single SmtpClient object can't send multiple messages simultaneously; instead, it sends emails one by one over the socket being used. To achieve parallel sending, we need multiple SmtpClient objects and multiple sockets.

It's not advisable to create a new SmtpClient object for each recipient because connecting with and authenticating on an email server will increase the latency. This is why in the above example the large mailing list is split into a number of smaller ones of the specified size. A new SmtpClient object is created and used to send bulk email to recipients from each of those smaller mailing lists.

For sending, you can use an SMTP server from a bulk email service or free email provider. Note that to successfully send mass emails with a free email provider (without having a portion of your messages undelivered, blocked, or moved to a Spam folder), you'll need to follow the provider's Bulk Email Sender Guidelines:

To personalize the messages for each recipient, you can use GemBox.Email's mail merge feature and create multiple personalized mail messages based on a single message template and data source.

Check next example or download examples from GitHub.