Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What are best practices for using SmtpClient, SendAsync and Dispose under .NET 4.0

People also ask

How do I dispose of SmtpClient objects?

The SmtpClient class has no Finalize method. So an application must call Dispose to explicitly free up resources. The Dispose method iterates through all established connections to the SMTP server specified in the Host property and sends a QUIT message followed by gracefully ending the TCP connection.

Is SmtpClient obsolete?

The SmtpClient class is obsolete in Xamarin. However: It is included in the . NET Standard 2.0 and later versions and therefore must be part of any .

Is SmtpClient thread safe?

The SmtpClient Class states that instance members are not thread safe. This can be seen if concurrent calls are made to Send or SendAsync.


The original question was asked for .NET 4, but if it helps as of .NET 4.5 SmtpClient implements async awaitable method SendMailAsync.

As a result, to send email asynchronously is as the following:

public async Task SendEmail(string toEmailAddress, string emailSubject, string emailMessage)
{
    using (var message = new MailMessage())
    {
        message.To.Add(toEmailAddress);

        message.Subject = emailSubject;
        message.Body = emailMessage;

        using (var smtpClient = new SmtpClient())
        {
            await smtpClient.SendMailAsync(message);
        }
    }
}

It's better to avoid using SendAsync method.


Note: .NET 4.5 SmtpClient implements async awaitable method SendMailAsync. For lower versions, use SendAsync as described below.


You should always dispose of IDisposable instances at the earliest possibility. In the case of async calls, this is on the callback after the message is sent.

var message = new MailMessage("from", "to", "subject", "body"))
var client = new SmtpClient("host");
client.SendCompleted += (s, e) => {
                           client.Dispose();
                           message.Dispose();
                        };
client.SendAsync(message, null);

It's a bit annoying the SendAsync doesn't accept a callback.


In general, IDisposable objects should be disposed as soon as possible; implementing IDisposable on an object is intended to communicate the fact that the class in question holds expensive resources that should be deterministically released. However, if creating those resources is expensive and you need to construct a lot of these objects, it may be better (performance wise) to keep one instance in memory and reuse it. There's only one way to know if that makes any difference: profile it!

Re: disposing and Async: you can't use using obviously. Instead you typically dispose the object in the SendCompleted event:

var smtpClient = new SmtpClient();
smtpClient.SendCompleted += (s, e) => smtpClient.Dispose();
smtpClient.SendAsync(...);

Ok, old question I know. But I stumbled upon this myself when I was in need of implementing something similar. I just wanted to share some code.

I'm iterating over several SmtpClients to send several mail asynchronously. My solution is similar to TheCodeKing, but I'm disposing the callback object instead. I'm also passing MailMessage as userToken to get it in the SendCompleted event so I can call dispose on that as well. Like this:

foreach (Customer customer in Customers)
{
    SmtpClient smtpClient = new SmtpClient(); //SmtpClient configuration out of this scope
    MailMessage message = new MailMessage(); //MailMessage configuration out of this scope

    smtpClient.SendCompleted += (s, e) =>
    {
        SmtpClient callbackClient = s as SmtpClient;
        MailMessage callbackMailMessage = e.UserState as MailMessage;
        callbackClient.Dispose();
        callbackMailMessage.Dispose();
    };

    smtpClient.SendAsync(message, message);
}