0
votes

I use MailKit for sending email by timer. I keep smtpClient in ConcurrentDictionary. Sometimes, I get error when try to connect async: The ReadAsync method cannot be called when another read operation is pending.

public async Task SendMessageAsync(string consumerKey, SmtpServer server, EmailMessage message)
{            
   SmtpClient client = new SmtpClient();
   if (!_clients.TryAdd(consumerKey, client))
   {
       client = _clients[consumerKey];
   }

   if (!client.IsConnected) await ConnectSmtpClient(server, client);
...
}
private async Task ConnectSmtpClient(SmtpServer server, SmtpClient client)
{
   try
   {
       await client.ConnectAsync(server.Address, server.Port, server.UseSSL);
       await client.AuthenticateAsync(new SaslMechanismLogin(server.Credentials));
   }
    catch (Exception e)
   {
        Console.WriteLine(e);
        throw;
   }
 }

    at System.Net.Security.SslStream.[ReadAsyncInternal]d__214`1.MoveNext()
    at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
    at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult()
    at MailKit.Net.Smtp.SmtpStream.[ReadAheadAsync]d__39.MoveNext()
    at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
    at MailKit.Net.Smtp.SmtpStream.[ReadResponseAsync]d__46.MoveNext()
    at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
    at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult()
    at MailKit.Net.Smtp.SmtpClient.[SendCommandAsync]d__63.MoveNext()
    at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
    at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult()
    at MailKit.Net.Smtp.SmtpClient.[SendEhloAsync]d__65.MoveNext()
    at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
    at MailKit.Net.Smtp.SmtpClient.[EhloAsync]d__66.MoveNext()
    at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
    at MailKit.Net.Smtp.SmtpClient.[ConnectAsync]d__74.MoveNext()
    at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)

1

1 Answers

1
votes

You are probably getting into a situation where multiple threads are accessing the same SmtpClient object.

Since MailKit's SmtpClient is not thread-safe, things will break if you attempt to send mail (or connect/authenticate) from multiple threads.