0

In a web application, we create an email provider, which in turn creates an SMTP client: my question is whether we should create an SMTP client per request or create only one client and have it service all requests?

Which is the best way to use an SMTP client? We are only sending (not receiving) email.

4
  • That depends entirely on your implementation and further requirements. Whatever language you use, creating a new SMTP client per request is going to cause overhead you would not have when reusing the same one. Nov 18, 2016 at 9:50
  • It depends on whether or not you're sending one email or several. Read the Remarks section here: msdn.microsoft.com/en-us/library/… Nov 18, 2016 at 17:38
  • but if we create client one time and reuse it with every request that may cause deadlock in application. if one request use smtp client for sending email and in mean time , other request also try to use it make deadlock, and if we try to use lock statement that means we try to hold the request thread
    – Ankit Rana
    Nov 25, 2016 at 6:56
  • Looks like C# SmtpClient implements a pool of connections so it probably enqueue the requests. It's most probably a bottleneck than a deadlock. If you are afraid of holding requests thread, use asyncSend instead.
    – Laiv
    Dec 13, 2016 at 20:09

2 Answers 2

4

Since the SmtpClient is not fully thread safe and can not send multiple emails at the same time, the only way to build a scalable and performant solution is to make your own pool of SmtpClient instances.

A simple implementation would be along the lines of

  • Write an EmailSender class and register as a singleton with your IOC container. Make it create a Queue of SmtpClients at initialization and keep a private reference to the queue.
  • When the application sends email, lock the queue and take an SmtpClient from the queue if there is one. If the queue is empty then construct a new SmtpClient instead.
  • The synchronous version is easier because you just wrap the send in try/finally and add the SmtpClient to the queue in the finally part.
  • The async version is slightly more complicated but also possible.
  • Be careful to reset the SmtpClient back into a valid starting state before adding to the queue. Take special care when the send fails.
  • Optionally dispose of SmtpClients rather than adding them to the queue count exceeds a configurable threshold.

A more complicated version also exists where you send lots of very similar emails. In this case you can have multiple pools that initialize SmtpClients for each type of email your application sends.

1
  • 2
    This is a really well thought out answer.
    – HouseCat
    Feb 25, 2019 at 22:23
1

Microsoft does not guarantee that the instance methods of SmtpClient are thread safe. Use SmtpClient.SendMailAsync to allow same thread to do other tasks while sending mails. You also cannot send other mails while SmtpClient is sending a message if you check remarks for SmtpClient.Send:

You cannot call this method if there is a message being sent asynchronously.

Your safest bet is to initialize a new SmtpClient every time. I've been doing this for thousands of emails being sent asynchronously on a cheap 1 core, 1gb ram server.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.