jstedfast/MailKit · error · NotSupportedException

The SMTP server does not support the STARTTLS extension.

Error message

The SMTP server does not support the STARTTLS extension.

What it means

During PostConnectAsync, when SecureSocketOptions.StartTls was requested, MailKit checks the EHLO capability list for SmtpCapabilities.StartTLS. If the server did not advertise STARTTLS, it throws NotSupportedException, refusing to proceed on an unencrypted channel because the caller explicitly demanded TLS upgrade.

Solutions

  1. Use SecureSocketOptions.StartTls on port 587; use SecureSocketOptions.SslOnConnect for port 465.
  2. Or use SecureSocketOptions.Auto to let MailKit pick the right strategy.
  3. Verify the server supports STARTTLS via the EHLO capability list (client.Capabilities).
  4. Enable STARTTLS support on the SMTP server if you control it.

Example fix

// before
await client.ConnectAsync("smtp.example.com", 465, SecureSocketOptions.StartTls);
// after
await client.ConnectAsync("smtp.example.com", 465, SecureSocketOptions.SslOnConnect); // 465 is implicit TLS
// (or port 587 + SecureSocketOptions.StartTls)
Defensive patterns

Strategy: validation

Validate before calling

// choose options based on port before calling ConnectAsync
SecureSocketOptions options = port == 465
    ? SecureSocketOptions.SslOnConnect
    : SecureSocketOptions.StartTls;
// or simply:
options = SecureSocketOptions.Auto;

Type guard

bool SupportsStartTls(SmtpClient c) => c.IsConnected && c.Capabilities.HasFlag(SmtpCapabilities.StartTLS);

Try / catch

try {
    await client.ConnectAsync(host, port, SecureSocketOptions.StartTls);
} catch (NotSupportedException ex) when (ex.Message.Contains("STARTTLS")) {
    // fall back to implicit TLS or Auto
    await client.ConnectAsync(host, 465, SecureSocketOptions.SslOnConnect);
}

Prevention

When it happens

Trigger: Calling ConnectAsync with options=SecureSocketOptions.StartTls against a server that (a) does not support STARTTLS, or (b) already runs implicit TLS on that port (e.g. port 465) so it never advertises STARTTLS.

Common situations: Using StartTls on port 465 (implicit TLS) instead of 587 (plaintext+STARTTLS); old/locked-down relays without TLS support.

Related errors


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

Appendix: source

Thrown at MailKit/Net/Smtp/AsyncSmtpClient.cs:456

				stream.Dispose ();
				secure = false;
				throw;
			}

			Stream = new SmtpStream (stream, ProtocolLogger);

			try {
				// read the greeting
				var response = await Stream.ReadResponseAsync (cancellationToken).ConfigureAwait (false);

				if (response.StatusCode != SmtpStatusCode.ServiceReady)
					throw new SmtpCommandException (SmtpErrorCode.UnexpectedStatusCode, response.StatusCode, response.Response);

				// Send EHLO and get a list of supported extensions
				await EhloAsync (true, cancellationToken).ConfigureAwait (false);

				if (options == SecureSocketOptions.StartTls && (capabilities & SmtpCapabilities.StartTLS) == 0)
					throw new NotSupportedException ("The SMTP server does not support the STARTTLS extension.");

				if (starttls && (capabilities & SmtpCapabilities.StartTLS) != 0) {
					response = await Stream.SendCommandAsync ("STARTTLS\r\n", cancellationToken).ConfigureAwait (false);
					if (response.StatusCode != SmtpStatusCode.ServiceReady)
						throw new SmtpCommandException (SmtpErrorCode.UnexpectedStatusCode, response.StatusCode, response.Response);

					try {
						var tls = new ExtendedSslStream (stream, false, ValidateRemoteCertificate);
						Stream.SetStream (tls);

						await SslHandshakeAsync (tls, host, cancellationToken).ConfigureAwait (false);
					} catch (Exception ex) {
						throw SslHandshakeException.Create (ref sslValidationInfo, ex, true, "SMTP", host, port, 465, 25, 587);
					}

					secure = true;

					// Send EHLO again and get the new list of supported extensions

View on GitHub (pinned to 9d3859a785)