jstedfast/MailKit · error · TimeoutException

Operation timed out after

Error message

Operation timed out after {readTimeout} milliseconds

What it means

MailKit's NetworkStream.ReadAsync wraps the socket receive in a cancellation-linked timeout; when the read doesn't complete within readTimeout, the OperationCanceledException is converted to a TimeoutException with the readTimeout in the message, and the stream disconnects first. It's the generic 'server took too long to send data' timeout.

Solutions

  1. Increase the client's Timeout property (e.g. client.Timeout = 120000) to a value large enough for the slowest server response.
  2. Catch TimeoutException and retry the operation with a fresh connection, since MailKit disconnects the stream on timeout.
  3. Investigate server-side latency (queue size, greylisting on SMTP, bandwidth) if timeouts persist at reasonable values.

Example fix

// before
var client = new ImapClient();
client.Connect("imap.example.com", 993, true);

// after
var client = new ImapClient();
client.Timeout = 120_000; // 2 minutes
client.Connect("imap.example.com", 993, true);
Defensive patterns

Strategy: try-catch

Try / catch

try { await op(); }
catch (TimeoutException) {
    // stream already disconnected; reconnect and retry with a larger Timeout
    client.Timeout = 120_000;
    await ReconnectAsync();
    await op();
}

Prevention

When it happens

Trigger: Any read on a NetworkStream-based connection (e.g. AcceptProxyConnection reading the proxy protocol header, IMAP/POP3/SMTP response reads) that exceeds the client's Timeout property; server hangs or stops responding mid-command.

Common situations: Slow or overloaded mail servers; very large responses over slow links where readTimeout is too small; firewalls silently dropping packets; debugging proxies that hold connections open.

Understand the failure class

Background: Request timed out: what client-side request timeouts mean across libraries (Request timed out, TIMED_OUT, APITimeoutError) — this error's family across 39 libraries.

Related errors


AI-assisted analysis of jstedfast/MailKit@9d3859a785 (2026-09-15). Data as JSON: /api/errors/33cd6a6e3f0de702. Report an issue: GitHub.

Appendix: source

Thrown at MailKit/Net/NetworkStream.cs:193

			// Capture the ReadTimeout so even if we get an exception and disconnect the socket, we still have it.
			int readTimeout = ReadTimeout;

			using (var timeout = new CancellationTokenSource (readTimeout)) {
				using (var linked = CancellationTokenSource.CreateLinkedTokenSource (cancellationToken, timeout.Token)) {
					using (var registration = linked.Token.Register (() => tcs.TrySetCanceled (), false)) {
						recv!.SetBuffer (buffer, offset, count);
						recv.UserToken = tcs;

						if (!Socket.ReceiveAsync (recv))
							AsyncOperationCompleted (null, recv);

						try {
							await tcs.Task.ConfigureAwait (false);
							return recv.BytesTransferred;
						} catch (OperationCanceledException ex) {
							Disconnect ();
							if (timeout.IsCancellationRequested)
								throw new TimeoutException ($"Operation timed out after {readTimeout} milliseconds", ex);
							throw;
						} catch (Exception ex) {
							Disconnect ();
							if (ex is SocketException)
								throw new IOException (ex.Message, ex);
							throw;
						}
					}
				}
			}
		}

		public override void Write (byte[] buffer, int offset, int count)
		{
			try {
				Socket.Send (buffer, offset, count, SocketFlags.None);
			} catch (SocketException ex) {
				throw new IOException (ex.Message, ex);

View on GitHub (pinned to 9d3859a785)