jstedfast/MailKit · error · InvalidOperationException
The SmtpClient is already authenticated.
Error message
The SmtpClient is already authenticated.
What it means
SmtpClient.Authenticate throws InvalidOperationException when IsAuthenticated is already true. SMTP allows only one successful AUTH per connection, so MailKit rejects a second Authenticate call on the same connection rather than re-authenticating.
Solutions
- Guard with if (!client.IsAuthenticated) client.Authenticate(...).
- To switch credentials, call Disconnect and Connect again before re-authenticating, or create a new SmtpClient.
- Restructure loops so a new connection (and authentication) is made per account.
Example fix
// before
client.Connect(host, 587, SecureSocketOptions.StartTls);
client.Authenticate("a", "pw1");
client.Authenticate("b", "pw2"); // InvalidOperationException
// after
client.Authenticate("a", "pw1");
client.Disconnect(true);
client.Connect(host, 587, SecureSocketOptions.StartTls);
client.Authenticate("b", "pw2"); Defensive patterns
Strategy: validation
Validate before calling
if (!client.IsAuthenticated)
client.Authenticate(user, pass); Try / catch
try {
client.Authenticate(user, pass);
} catch (InvalidOperationException) {
// already authenticated on this connection; proceed
} Prevention
- Track authentication state in your app instead of re-calling Authenticate.
- Disconnect + reconnect when credentials change.
- Avoid retry wrappers that re-run Authenticate on a live session.
When it happens
Trigger: Calling Authenticate twice on the same connected SmtpClient instance, e.g. authenticating once then calling Authenticate again with different credentials without reconnecting.
Common situations: Looping over multiple accounts but reusing one SmtpClient without reconnecting; retry logic that calls Authenticate again after a later failure (e.g. Send) on the still-authenticated connection; credential-rotation code assuming re-auth is allowed.
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.
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- The HeaderSet is read-only.
- Value cannot be null. (Parameter 'message')
- Value cannot be null. (Parameter 'response')
- Cannot rename this folder.
- Cannot delete this folder.
AI-assisted analysis of jstedfast/MailKit@9d3859a785 (2026-09-15).
Data as JSON: /api/errors/7c31af7c744369bf.
Report an issue: GitHub.
Appendix: source
Thrown at MailKit/Net/Smtp/SmtpClient.cs:1002
if (response.StatusCode != SmtpStatusCode.Ok)
throw new SmtpCommandException (SmtpErrorCode.UnexpectedStatusCode, response.StatusCode, response.Response);
} else {
UpdateCapabilities (response);
}
}
void ValidateArguments (SaslMechanism mechanism)
{
if (mechanism == null)
throw new ArgumentNullException (nameof (mechanism));
CheckDisposed ();
if (!IsConnected)
throw new ServiceNotConnectedException ("The SmtpClient must be connected before you can authenticate.");
if (IsAuthenticated)
throw new InvalidOperationException ("The SmtpClient is already authenticated.");
if ((capabilities & SmtpCapabilities.Authentication) == 0)
throw new NotSupportedException ("The SMTP server does not support authentication.");
mechanism.ChannelBindingContext = Stream.Stream as IChannelBindingContext;
mechanism.Uri = new Uri ($"smtp://{uri.Host}");
}
/// <summary>
/// Authenticate using the specified SASL mechanism.
/// </summary>
/// <remarks>
/// <para>Authenticates using the specified SASL mechanism.</para>
/// <para>For a list of available SASL authentication mechanisms supported by the server,
/// check the <see cref="AuthenticationMechanisms"/> property after the service has been
/// connected.</para>
/// </remarks>
/// <param name="mechanism">The SASL mechanism.</param>View on GitHub (pinned to 9d3859a785)