jstedfast/MailKit · error · ProxyProtocolException

Failed to connect to

Error message

Failed to connect to {0}:{1}: {2}

What it means

After sending the SOCKS4 CONNECT request, Socks4Client reads the 8-byte reply and requires byte[1] == 0x5A (RequestGranted). Any other reply code throws ProxyProtocolException('Failed to connect to host:port: <reason>') where the reason names the SOCKS4 failure (request rejected/ident failed, target unreachable, etc.).

Solutions

  1. Check the failure reason embedded in the exception message (GetFailureReason output) for the exact SOCKS4 reply code.
  2. Verify the proxy allows CONNECT to the target host:port and add the ACL entry if not.
  3. Supply the correct SOCKS4 userid in the Connect call if the proxy validates ident.
  4. Confirm the endpoint really is a SOCKS4 proxy; use Socks5Client/HttpProxyClient if it is SOCKS5/HTTP.
  5. Test manually: `curl --socks4 proxy:1080 http://target:port` to reproduce outside the app.

Example fix

// before
var proxy = new Socks4Client("proxy.corp", 1080);
proxy.Connect(targetEp); // rejected: ACL blocks port 995
// after
// fix on proxy side: allow CONNECT to target:995, or use an allowed proxy
var proxy = new Socks4Client("proxy-alt.corp", 1080);
proxy.Connect(targetEp, "socksUserId");
Defensive patterns

Strategy: try-catch

Validate before calling

// pre-flight the proxy path outside the app:
// curl --socks4 proxy:1080 https://target:port -I

Try / catch

try {
    return proxy.Connect(targetEp, cancellationToken);
} catch (ProxyProtocolException ex) when (ex.Message.Contains("Failed to connect to")) {
    // message carries the SOCKS4 reply reason: check ACLs/userid/proxy type
    throw new InvalidOperationException("SOCKS4 proxy refused CONNECT", ex);
}

Prevention

When it happens

Trigger: The SOCKS4 proxy refuses the CONNECT: target host/port blocked, SOCKS user-id rejected (ident check failed), proxy cannot reach the target, or wrong proxy port/protocol so the reply bytes are garbage.

Common situations: Proxy ACLs disallowing mail ports; missing or mismatched SOCKS userid when the proxy enforces ident; pointing the client at a SOCKS5-only or HTTP proxy; target host firewall dropping from the proxy's network.

Understand the failure class

Background: ECONNREFUSED and "connection refused" / "could not connect to server" errors: what they mean and how to fix them — this error's family across 44 libraries.

Related errors


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

Appendix: source

Thrown at MailKit/Net/Proxy/Socks4Client.cs:268

			try {
				var buffer = GetConnectCommand (domain, addr, port);

				Send (socket, buffer, 0, buffer.Length, cancellationToken);

				// +-----+-----+----------+----------+
				// | VER | REP | BND.PORT | BND.ADDR |
				// +-----+-----+----------+----------+
				// |  1  |  1  |    2     |    4     |
				// +-----+-----+----------+----------+
				int nread, n = 0;

				do {
					if ((nread = Receive (socket, buffer, 0 + n, 8 - n, cancellationToken)) > 0)
						n += nread;
				} while (n < 8);

				if (buffer[1] != (byte) Socks4Reply.RequestGranted)
					throw new ProxyProtocolException (string.Format (CultureInfo.InvariantCulture, "Failed to connect to {0}:{1}: {2}", host, port, GetFailureReason (buffer[1])));

				// TODO: do we care about BND.ADDR and BND.PORT?

				return new NetworkStream (socket, true);
			} catch {
				if (socket.Connected)
					socket.Disconnect (false);

				socket.Dispose ();
				throw;
			}
		}

		/// <summary>
		/// Asynchronously connect to the target host.
		/// </summary>
		/// <remarks>
		/// Asynchronously connects to the target host and port through the proxy server.

View on GitHub (pinned to 9d3859a785)