jstedfast/MailKit · error · ArgumentException
The socket is not connected.
Error message
The socket is not connected.
What it means
SmtpClient.ValidateArguments(Socket, string, int) rejects a socket argument that is not in a connected state. When you pass a pre-established socket to Connect(Socket, host, port), MailKit checks socket.Connected and throws ArgumentException before any SMTP traffic occurs. It exists to catch callers who hand over a closed, never-connected, or half-closed socket.
Solutions
- Connect the socket yourself (socket.Connect(host, port)) before passing it to SmtpClient.Connect, and check socket.Connected first
- Create a fresh socket for each SmtpClient session instead of reusing stale ones
- If pooling sockets, validate the connection with a probe (socket.Poll / connected check) before reuse
- Simplify: let MailKit manage the connection by calling Connect(host, port) directly instead of supplying your own socket
Example fix
// before
var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
client.Connect(socket, "smtp.example.com", 465); // throws: socket never connected
// after
var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
socket.Connect("smtp.example.com", 465);
if (socket.Connected)
client.Connect(socket, "smtp.example.com", 465); Defensive patterns
Strategy: validation
Validate before calling
if (socket == null) throw new ArgumentNullException(nameof(socket));
if (!socket.Connected)
throw new InvalidOperationException("Pass a socket that is already connected (call socket.Connect first).");
client.Connect(socket, host, port); Type guard
bool IsUsableSocket(Socket s) => s != null && s.Connected;
Try / catch
try { client.Connect(socket, host, port); }
catch (ArgumentException ex) when (ex.ParamName == "socket") {
// rebuild a fresh connected socket and retry
} Prevention
- Always call socket.Connect before handing the socket to SmtpClient
- Never reuse sockets across SmtpClient sessions; create a new one per connection
- Check socket.Connected (or Poll for readability/error) before reuse
- Prefer Connect(host, port) and let MailKit own the socket
When it happens
Trigger: Calling SmtpClient.Connect(Socket socket, string host, int port) (or the overload with SecureSocketOptions) with a socket that was never connected, whose connection was already closed, or whose remote end dropped (Connected becomes false after a disconnect).
Common situations: Reusing a socket from a previous failed session; creating a new Socket and forgetting to call Connect on it before handing it to MailKit; a long-lived app whose pooled socket timed out or was reset by a firewall; passing a socket from a cancelled/disposed connection.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- The host name cannot be empty.
- Annotation entry paths must not end with '/'.
- Annotation entry paths must not end with '.'.
- Invalid part-specifier.
- array
AI-assisted analysis of jstedfast/MailKit@9d3859a785 (2026-09-15).
Data as JSON: /api/errors/fd0588d29f55f40b.
Report an issue: GitHub.
Appendix: source
Thrown at MailKit/Net/Smtp/SmtpClient.cs:1538
stream = ssl;
} else {
secure = false;
}
PostConnect (stream, host, port, options, starttls, cancellationToken);
} catch (Exception ex) {
operation.SetError (ex);
throw;
}
}
void ValidateArguments (Socket socket, string host, int port)
{
if (socket == null)
throw new ArgumentNullException (nameof (socket));
if (!socket.Connected)
throw new ArgumentException ("The socket is not connected.", nameof (socket));
ValidateArguments (host, port);
}
/// <summary>
/// Establish a connection to the specified SMTP or SMTP/S server using the provided socket.
/// </summary>
/// <remarks>
/// <para>Establishes a connection to the specified SMTP or SMTP/S server using the provided socket.</para>
/// <para>If the <paramref name="options"/> has a value of
/// <see cref="SecureSocketOptions.Auto"/>, then the <paramref name="port"/> is used
/// to determine the default security options. If the <paramref name="port"/> has a value
/// of <c>465</c>, then the default options used will be
/// <see cref="SecureSocketOptions.SslOnConnect"/>. All other values will use
/// <see cref="SecureSocketOptions.StartTlsWhenAvailable"/>.</para>
/// <para>Once a connection is established, properties such as
/// <see cref="AuthenticationMechanisms"/> and <see cref="Capabilities"/> will be
/// populated.</para>View on GitHub (pinned to 9d3859a785)