The SmtpClient Class states that instance members are not thread safe. This can be seen if concurrent calls are made to Send or SendAsync. Both methods will throw a InvalidOperationException on the second call if the first has not yet completed.
The method SendMailAsync, introduced in .NET 4.5, does not list InvalidOperationException as a thrown exception. Do the new .NET 4.5 methods implement some sort of queuing? Reflector isn't able to shed any light on the implementation details of this class, so I assume this has been implemented in native methods.
Can multiple threads call the SendMessageAsync method on a shared instance of the SMTP client safely?
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. Write an EmailSender class and register as a singleton with your IOC container.
The SmtpClient type is obsolete on some platforms and not recommended on others; for more information, see the Remarks section.
An SMTP Client allows sending of e-mail notifications using a SMTP server. Simple Mail Transfer Protocol (SMTP) is a widely used protocol for the delivery of e-mails between TCP/IP systems and users. The SMTP Client can send e-mails to various recipients.
I'm not sure why using Reflector didn't work for you. If I decompile it, I see the following code:
[HostProtection(SecurityAction.LinkDemand, ExternalThreading=true)]
public Task SendMailAsync(MailMessage message)
{
TaskCompletionSource<object> tcs = new TaskCompletionSource<object>();
SendCompletedEventHandler handler = null;
handler = delegate (object sender, AsyncCompletedEventArgs e) {
this.HandleCompletion(tcs, e, handler);
};
this.SendCompleted += handler;
try
{
this.SendAsync(message, tcs);
}
catch
{
this.SendCompleted -= handler;
throw;
}
return tcs.Task;
}
As you can see, it's a simple TAP wrapper for SendAsync()
. And if SendAsync()
throws an exception, SendMailAsync()
just rethrows it.
So, the conclusion is that SendMailAsync()
is not thread-safe and that its exceptions are underdocumented.
As a note (since I don't have enough points to comment), the traditional way to write an asynchronous operation was to use the Asynchronous Programming Model (APM), but today we typically use the Task-based Asynchronous Pattern (TAP) with its async/await keywords. And although it's not unusual to see TAP wrappers around APM methods, it's also possible to see APM wrappers around TAP methods.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With