13

I'm creating Windows Service that sends batches of emails every 5 minutes.

I want to send batches of 10-100 emails every 5 minutes. This is extreme edge case. Batches are sent every 5 minutes and normally consist of up to 10 emails.

I'm using SmtpClient from System.Net.Mail namespace.

What is proper lifetime of SmtpClient object? Should I create one every time batch is send? Or should I create one on Service start and never dispose of it?

Amna
  • 603
  • 7
  • 30
Hooch
  • 28,817
  • 29
  • 102
  • 161

3 Answers3

12

You should always utilise using

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

In most cases you should always dispose of anything that implements IDisposable as soon as you are finished with it, however you should always check the Docs to be sure. The SmtpClient class in .NET 4.0 implements IDisposable so be sure to use it!

To quote MSDN:

The SmtpClient class has no Finalize method, so an application must call Dispose to explicitly free up resources.

If you find yourself doing async related tasks then you can make a new instance for each email to prevent blocking yourself.You can use the following.

var smtpClient = new SmtpClient();
smtpClient.SendCompleted += (s, e) => {
                           client.Dispose();
                           message.Dispose();
                        };
client.SendAsync(message, null);

At Request - Best option for Bulk Send Emails

As noted above you can reuse the same client. If you keep it all on the same thread I recommend you just use one client

MSDN States:

The SmtpClient class implementation pools SMTP connections so that it can avoid the overhead of re-establishing a connection for every message to the same server. An application may re-use the same SmtpClient object to send many different emails to the same SMTP server and to many different SMTP servers.

However it goes on to say:

...As a result, there is no way to determine when an application is finished using the SmtpClient object and it should be cleaned up.

So assuming you dispose of your Client when complete it is fine.


There is discussion of a number of SMTP related topics linked below as I recently found myself asking the same question

More from Stackoverflow:

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

How to dispose objects having asynchronous methods called?

Related Reading:

MSDN SmtpClient

Implementing Finalize and Dispose to clean up managed resources

JEV
  • 2,494
  • 4
  • 33
  • 47
  • 1
    I don't really agree with part "as soon as you have the chance." and what is that "as soon" in my application? Also creating SmtpClient takes time as it needs to establish secure connection. – Hooch Jun 02 '15 at 08:42
  • That was a leftover from my crazy edits. There is nothing stopping you utilising one client, especially if you are in total control of the flow of emails, however you may find youself getting exceptions where it can't send emails because its still waiting on a response. It's not too expensive to create if you limit the amount. If you are settled on the idea of using one client perhaps using a BlockingCollection and a Semaphore can achieve this – JEV Jun 02 '15 at 08:45
  • 1
    I think I'll create on client per batch. It looks more logiacal then one per email and once per application. – Hooch Jun 02 '15 at 09:07
  • I'll accept your answer if you add small note that describes best practice for SmtpClient when sending batch of messages. Thank you. – Hooch Jun 02 '15 at 09:09
  • Hi @Hooch is it being handled in the main thread, or are you creating more to do this? – JEV Jun 02 '15 at 09:12
  • I was thinking about creating one thread per batch. But I don't know if sending every message in batch as "async" would be good idea. I know it will work. I just don't have experience and don't know the proper way. – Hooch Jun 02 '15 at 09:15
  • @Hooch I updated my answer .Go with just one thread for now. I have provided the async code above if you wish to use it later on – JEV Jun 02 '15 at 09:18
  • 1
    "You should always dispose of anything that implements IDisposable as soon as you are finished with it." That is not always true, take HttpClient for example that _should not_ be routinely disposed but rather persisted. – Alex Oct 22 '21 at 17:40
  • I think HttpClient is a bit of a unique case, and is different even now in netcore. However I will edit answer to be a bit more explicit – JEV Oct 25 '21 at 09:16
5

As of .NET 4.0 the SmtpClient pools connections so you might keep on it for a while. It's probably best to dispose it after you finished sending a batch.

From MSDN: https://msdn.microsoft.com/en/us/library/system.net.mail.smtpclient(v=VS.100).aspx

The SmtpClient class implementation pools SMTP connections so that it can avoid the overhead of re-establishing a connection for every message to the same server. An application may re-use the same SmtpClient object to send many different emails to the same SMTP server and to many different SMTP servers. As a result, there is no way to determine when an application is finished using the SmtpClient object and it should be cleaned up.

rlee
  • 293
  • 1
  • 8
0

First of all it is a very good practice to use any object whenever needed untill and unless you needs its utility throughout the app.

Secondly you should create SmtpClient's object every time you need it and to properly dispose it, for that use the using tags as described above by Glitch100.

 using (var smtpClient = new SmtpClient())
 {
     smtpClient.SendMail(message);
 }
Murtaza Munshi
  • 1,065
  • 4
  • 13
  • 40