Search code examples
mailkitmimekit

MailKit version 2.15.0 disconnection issue


I am using MailKit version 2.15.0. When trying to disconnect the client using DisconnectAsync, I am getting the below error

ClientDisconnect method()==> Exception Message:  The ReadAsync method cannot be called when another read operation is pending., Exception String: System.NotSupportedException:  The ReadAsync method cannot be called when another read operation is pending.
         at System.Net.Security.SslStream.ReadAsyncInternal[TIOAdapter](TIOAdapter adapter, Memory`1 buffer)
         at MailKit.Net.Pop3.Pop3Stream.ReadAheadAsync(Boolean doAsync, CancellationToken cancellationToken)
         at MailKit.Net.Pop3.Pop3Stream.ReadLineAsync(Stream ostream, Boolean doAsync, CancellationToken cancellationToken)
         at MailKit.Net.Pop3.Pop3Engine.ReadLineAsync(Boolean doAsync, CancellationToken cancellationToken)
         at MailKit.Net.Pop3.Pop3Engine.ReadResponseAsync(Pop3Command pc, Boolean doAsync)
         at MailKit.Net.Pop3.Pop3Engine.IterateAsync(Boolean doAsync)
         at MailKit.Net.Pop3.Pop3Client.SendCommandAsync(Boolean doAsync, CancellationToken token, String command)
         at MailKit.Net.Pop3.Pop3Client.DisconnectAsync(Boolean quit, Boolean doAsync, CancellationToken cancellationToken)

Below is the code I am using to Disconnect the Client

private async Task DisconnectClient(Hashtable markAsRead, EmailServer emailServer)
{
    pollingInProgress = false;
    await emailServer.ClientDisconnect(markAsRead);
    markAsRead.Clear();
}
   internal void MarkAsRead(Hashtable markAsRead)
        {
            emailBinding.emailSource().MarkRead(markAsRead);
        }

        internal async Task ClientDisconnect(Hashtable markAsRead)
        {
            try
            {
                if (!emailBinding.emailSource().IsConnected)
                {
                    await emailBinding.Connect();
                }

                FlushClient(markAsRead);

                await emailBinding.Disconnect();
            }
            catch (Exception e)
            {
                AttachWorkerLogs(string.Format("ClientDisconnect method()==> Exception Message: {0}, Exception String: {1}", e.Message, e.ToString()));
                throw;
            }
        }

        private void FlushClient(Hashtable markAsRead)
        {
            MarkAsRead(markAsRead);
        }

Finally calling the disconnect method like this:

public async Task Disconnect()
        {
            try
            {
                if (client.IsConnected)
                {
                    await client.DisconnectAsync(true);
                }
            }
            catch (Exception e)
            {
                AttachLogger(string.Format("Disconnect method()==> Exception Message: {0}, Exception String: {1}", e.Message, e.ToString()));
                throw;
            }

        }

I am unable to figure out what exactly is the issue.


Solution

  • The exception message makes it pretty clear that you are trying to read from the SslStream from multiple threads at the same time.

    Since MailKit is not multi-threaded, it means that you are effectively trying to perform 2 or more operations on the same Pop3Client from multiple threads at the same time.

    In other words, the problem is not that you are calling Disconnect, the problem is that you are calling Disconnect when your code is also trying to download messages or something from the server.