jstedfast/MailKit · error · ServiceNotConnectedException

The Pop3Client must be connected before you can…

Error message

The Pop3Client must be connected before you can authenticate.

What it means

Pop3Client.CheckCanAuthenticate validates preconditions for authentication and throws ServiceNotConnectedException when engine.IsConnected is false, with this message. Authentication is a protocol exchange over an open connection, so it requires a live TCP/TLS session first. This guard fires before any AUTH bytes are sent.

Solutions

  1. Call Connect (and upgrade with StartTls if needed) before calling Authenticate.
  2. Check client.IsConnected immediately before Authenticate; reconnect if false.
  3. On connection failures or dropped sessions, recreate or reconnect the Pop3Client before retrying authentication.
  4. Ensure the previous Connect call's exceptions are not being swallowed, leaving the client unconnected.

Example fix

// before
var client = new Pop3Client();
client.Authenticate("user", "pass"); // throws ServiceNotConnectedException
// after
var client = new Pop3Client();
client.Connect("pop.example.com", 995, SecureSocketOptions.SslOnConnect);
client.Authenticate("user", "pass", cancellationToken);
Defensive patterns

Strategy: try-catch

Validate before calling

if (!client.IsConnected)
    client.Connect(host, port, SecureSocketOptions.SslOnConnect);

Try / catch

try {
    client.Authenticate(user, pass, cancellationToken);
} catch (ServiceNotConnectedException) {
    client.Connect(host, port, SecureSocketOptions.SslOnConnect);
    client.Authenticate(user, pass, cancellationToken);
}

Prevention

When it happens

Trigger: Calling Authenticate (or an overload going through CheckCanAuthenticate/saslUri) on a Pop3Client that was never connected, after Disconnect, or after the connection was dropped/disposed — i.e. engine.IsConnected is false at authenticate time.

Common situations: Calling Authenticate before Connect; an earlier Connect failed or threw and the code continued; the server dropped the connection (idle timeout, server restart) and the app tries to re-authenticate without reconnecting; reusing a disposed Pop3Client instance.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


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

Appendix: source

Thrown at MailKit/Net/Pop3/Pop3Client.cs:776

				try {
					// Note: We defer throwing exceptions on command failure so that our caller can continue trying other authentication mechanisms.
					await Engine.RunAsync (false, cancellationToken).ConfigureAwait (false);
				} finally {
					client.detector.IsAuthenticating = false;
				}

				return pc;
			}
		}

		Uri CheckCanAuthenticate (SaslMechanism mechanism, CancellationToken cancellationToken)
		{
			if (mechanism == null)
				throw new ArgumentNullException (nameof (mechanism));

			if (!engine.IsConnected)
				throw new ServiceNotConnectedException ("The Pop3Client must be connected before you can authenticate.");

			if (IsAuthenticated)
				throw new InvalidOperationException ("The Pop3Client is already authenticated.");

			CheckDisposed ();

			cancellationToken.ThrowIfCancellationRequested ();

			return new Uri ("pop://" + engine.Uri.Host);
		}

		SaslAuthContext GetSaslAuthContext (SaslMechanism mechanism, Uri saslUri)
		{
			mechanism.ChannelBindingContext = engine.Stream!.Stream as IChannelBindingContext;
			mechanism.Uri = saslUri;

			return new SaslAuthContext (this, mechanism);
		}

View on GitHub (pinned to 9d3859a785)