Async/await methods of Smtp class allow your application to send e-mails in the background using lightweight I/O worker threads.
Actually, MailBee.NET library also has two sets of async methods:
- MethodNameAsync
- truly async methods, supported in .NET 4.5 and higher. They are fast, scalable and easy to use with async/await
pattern. This tutorial focuses on async/await
approach.
- BeginMethodName/EndMethodName
pairs - they create CPU-bound worker threads. They are not as efficient and now considered deprecated. Use them only if you're bound to an older version of .NET Framework (prior to v4.5). You can find examples of these methods in MailBee.NET library class reference (such as Smtp.BeginSend) and in .NET 2.0+ versions of sample projects (see below).
Note that there is a difference between multi-threaded mode (see Smtp.MaxThreadCount property) and async methods. For instance, multi-threading can be used by a regular synchronous method as long as an async method can send e-mails in a single worker thread (without multi-threading).
An async method just allows your application to proceed immediately with other tasks not waiting for completion of the operation started. However, you cannot start another async operation on the same instance of Smtp class until the previous operation has finished. If you planned to use async operations to send multiple e-mails simultaneously, use jobs instead (see Send bulk e-mail through two SMTP relay servers for increased throughput topic for details).
Besides the samples below, there is a complete WinForms sample project SMTP Demo 2 which sends an e-mail asynchronously and carefully handles exceptions. It's installed with the product among other sample projects in "My Documents\MailBee.NET Objects\Samples\WinForms" folder. The project is available in both C# and VB versions, for .NET 2.0+ (BeginSend
-based) and .NET 4.5+ (SendAsync
-based).
Another useful sample project there is AddressValidator Demo. Although it's for another MailBee.NET's component EmailAddressValidator, the idea of using async methods and handling exceptions is all the same for all MailBee.NET components.
This is a simple console sample of sending an e-mail in async way:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using MailBee.SmtpMail; class Program { private static async Task DoAsyncWork() { Smtp mailer = new Smtp(); // Use SMTP relay with authentication. mailer.SmtpServers.Add("mail.here.com", "joe", "secret"); // Set other fields of the e-mail. mailer.Message.From.AsString = "Joe D. <joe@here.com>"; mailer.Message.To.AsString = "jane@example.com"; mailer.Message.Subject = "Message subject"; mailer.Message.BodyHtmlText = "<html>Message text</html>"; // Send asynchronously. await mailer.SendAsync(); Console.WriteLine("The e-mail was sent to: " + mailer.GetAcceptedRecipients().ToString()); } static void Main(string[] args) { DoAsyncWork().Wait(); Console.WriteLine("Press any key to exit"); Console.ReadKey(); } }
Imports System.Collections.Generic Imports System.Linq Imports System.Text Imports System.Threading.Tasks Imports MailBee.SmtpMail Module Module1 Private Async Function DoAsyncWork() As Task Dim mailer As New Smtp() ' Use SMTP relay with authentication. mailer.SmtpServers.Add("mail.here.com", "joe", "secret") ' Set other fields of the e-mail. mailer.Message.From.AsString = "Joe D. <joe@here.com>" mailer.Message.To.AsString = "jane@example.com" mailer.Message.Subject = "Message subject" mailer.Message.BodyHtmlText = "<html>Message text</html>" ' Send asynchronously. Await mailer.SendAsync() Console.WriteLine("The e-mail was sent to: " & mailer.GetAcceptedRecipients().ToString()) End Function Sub Main(args As String()) DoAsyncWork().Wait() Console.WriteLine("Press any key to exit") Console.ReadKey() End Sub End Module
We assume MailBee.NET SMTP license key is already set in app.config or Windows registry. See Import namespaces and set license key topic for details.
You can find more complex WinForms sample suitable for use in a desktop application at Smtp.BeginSend method documentation.
Also, as mentioned above, the complete WinForms sample project SMTP Demo 2 which uses Smtp.BeginSend method is installed with the product.
To send more than one e-mail or perform mail merge, use Smtp.BeginSendJobs method. The sample below is an async version of a similar code from Send series of e-mails based on template and database topic:
using System; using System.Data; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using MailBee; using MailBee.Mime; using MailBee.SmtpMail; class Program { // Create DataTable with some data. In real-world apps, // you'll get the data from external sources like SQL query. private static DataTable GetData() { DataTable workTable = new DataTable("customers"); DataColumn workCol = workTable.Columns.Add("id", typeof(int)); workCol.AllowDBNull = false; workCol.Unique = true; workTable.Columns.Add("name", typeof(string)); workTable.Columns.Add("email", typeof(string)); workTable.Columns.Add("doc_id", typeof(int)); workTable.Columns.Add("doc_name", typeof(string)); // Add two rows to the data source. This way, // the mail merge procedure will generate two e-mails. DataRow row = workTable.NewRow(); row["id"] = 1; row["name"] = "John Doe"; row["email"] = "john.doe@company.com"; row["doc_id"] = 637; row["doc_name"] = "annual report.xls"; workTable.Rows.Add(row); row = workTable.NewRow(); row["id"] = 2; row["name"] = "Bob Brown"; row["email"] = "bob.brown@example.com"; row["doc_id"] = 2358; row["doc_name"] = "agreement draft.pdf"; workTable.Rows.Add(row); return workTable; } private static async Task DoAsyncWork() { Smtp mailer = new Smtp(); // Use SMTP relay server with authentication. mailer.SmtpServers.Add("mail.here.com", "jane.doe", "secret"); // Set static From and Subject. mailer.Message.From.AsString = "Jane Doe <jane.doe@here.com>"; mailer.Message.Subject = "Information"; // Set templates for To, body, and attachment. mailer.Message.To.AsString = "##name## <##email##>"; mailer.Message.BodyPlainText = "Attachment for ##name##"; mailer.Message.Merge.AddAttachmentPattern(@"C:\Docs\##doc_name##"); // Enqueue mail merge job. mailer.AddJob("async mail merge sample", null, null, GetData()); await mailer.SendJobsAsync(); Console.WriteLine("The newsletter was sent to: " + mailer.JobsSuccessful.Count.ToString() + " addresses"); Console.WriteLine("The newsletter wasn't sent to: " + mailer.JobsFailed.Count.ToString() + " addresses"); } static void Main(string[] args) { DoAsyncWork().Wait(); Console.WriteLine("Press any key to exit"); Console.ReadKey(); } }
Imports System.Collections.Generic Imports System.Data Imports System.Linq Imports System.Text Imports System.Threading.Tasks Imports MailBee.SmtpMail Module Module1 ' Create DataTable with some data. In real-world apps, ' you'll get the data from external sources like SQL query. Private Function GetData() As DataTable Dim workTable As New DataTable("customers") Dim workCol As DataColumn = _ workTable.Columns.Add("id", GetType(Integer)) workCol.AllowDBNull = False workCol.Unique = True workTable.Columns.Add("name", GetType(String)) workTable.Columns.Add("email", GetType(String)) workTable.Columns.Add("doc_id", GetType(Integer)) workTable.Columns.Add("doc_name", GetType(String)) ' Add two rows to the data source. This way, ' the mail merge procedure will generate two e-mails. Dim row As DataRow = workTable.NewRow() row("id") = 1 row("name") = "John Doe" row("email") = "john.doe@company.com" row("doc_id") = 637 row("doc_name") = "annual report.xls" workTable.Rows.Add(row) row = workTable.NewRow() row("id") = 2 row("name") = "Bob Brown" row("email") = "bob.brown@example.com" row("doc_id") = 2358 row("doc_name") = "agreement draft.pdf" workTable.Rows.Add(row) Return workTable End Function Private Async Function DoAsyncWork() As Task Dim mailer As New Smtp() ' Use SMTP relay server with authentication. mailer.SmtpServers.Add("mail.here.com", "jane.doe", "secret") ' Set static From and Subject. mailer.Message.From.AsString = "Jane Doe <jane.doe@here.com>" mailer.Message.Subject = "Information" ' Set templates for To, body, and attachment. mailer.Message.To.AsString = "##name## <##email##>" mailer.Message.BodyPlainText = "Attachment for ##name##" mailer.Message.Merge.AddAttachmentPattern("C:\Docs\##doc_name##") ' Enqueue mail merge job. mailer.AddJob("async mail merge sample", Nothing, Nothing, GetData()) ' Start mail merge asynchronously. Await mailer.SendJobsAsync() Console.WriteLine("The newsletter was sent to: " & _ mailer.JobsSuccessful.Count.ToString() & " addresses") Console.WriteLine("The newsletter wasn't sent to: " & _ mailer.JobsFailed.Count.ToString() & " addresses") End Function Sub Main(args As String()) DoAsyncWork().Wait() Console.WriteLine("Press any key to exit") Console.ReadKey() End Sub End Module
With async methods, you can also use events and all other features which are available for synchronous methods. However, be sure that the main thread of the application (message loop thread) is not blocked. Otherwise, events won't get a chance to get processed and the application will hang.
Async methods available for all synchronous methods (i.e. Smtp.ConnectAsync for Smtp.Connect, Smtp.ExecuteCustomCommandAsync for Smtp.ExecuteCustomCommand, and so on). Their usage is very similar to synchronous methods.
Copyright © 2006-2024 AfterLogic Corporation. All rights reserved.