jstedfast/MailKit · error · ProxyProtocolException
Failed to connect to
Error message
Failed to connect to {0}:{1}: {2} What it means
When the SOCKS5 CONNECT reply's status byte (REP) is not 0x00, ProcessPartialConnectResponse throws ProxyProtocolException formatted with the requested host, port, and a textual reason from GetFailureReason (e.g. general failure, connection not allowed, network unreachable, host unreachable, connection refused, TTL expired, command not supported, address type not supported). The proxy itself reported that the proxied connection failed.
Solutions
- Read the embedded failure reason: for 'connection refused'/'host unreachable' fix the target service or network path, for 'not allowed' fix proxy ACLs
- If the target allowlists clients, add the proxy server's egress IP
- Confirm the target host/port by testing connectivity from the proxy machine itself
- Check the client is using CONNECT (the only command MailKit sends) and the port is what the target expects
Example fix
// before await proxy.ConnectAsync(proxyHost, 1080, "internal-db", 1433); // blocked by proxy ACL // after await proxy.ConnectAsync(proxyHost, 1080, "internal-db.example.com", 1433); // allowed FQDN, or request ACL change
Defensive patterns
Strategy: try-catch
Try / catch
try {
await socks5.ConnectAsync(proxyHost, proxyPort, target, targetPort);
} catch (ProxyProtocolException ex) {
log.Warn("SOCKS5 CONNECT to {0} refused: {1}", target, ex.Message);
// branch on the reason text / retry via alternate egress or alert ops
} Prevention
- Keep proxy ACLs in sync with all destinations the app needs
- Add proxy egress IPs to target allowlists
- Monitor target availability from the proxy network, not just locally
When it happens
Trigger: Socks5Client.Connect/ConnectAsync where the proxy cannot or will not reach the target host:port — target down, proxy egress blocked by policy, unsupported command, or unresolvable target from the proxy's network.
Common situations: Target service down or moved, corporate proxy ACLs blocking the destination, trying an SMTP/IMAP port the proxy forbids, DNS not working on the proxy host, or remote host refuses connections from the proxy's IP (allowlist lacks proxy IP).
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
- Failed to connect to
- Proxy server responded with unknown SOCKS version
- Failed to authenticate with SOCKS5 proxy server.
- Proxy server returned unknown address type.
- Failed to negotiate authentication method with the proxy…
AI-assisted analysis of jstedfast/MailKit@9d3859a785 (2026-09-15).
Data as JSON: /api/errors/a456d8d5d2f3ad04.
Report an issue: GitHub.
Appendix: source
Thrown at MailKit/Net/Proxy/Socks5Client.cs:344
break;
case Socks5AddressType.IPv4:
addr = ip!.GetAddressBytes ();
Buffer.BlockCopy (addr, 0, buffer, n, addr.Length);
n += 4;
break;
}
buffer[n++] = (byte) (port >> 8);
buffer[n++] = (byte) port;
return buffer;
}
int ProcessPartialConnectResponse (string host, int port, byte[] buffer)
{
VerifySocksVersion (buffer[0]);
if (buffer[1] != (byte) Socks5Reply.Success)
throw new ProxyProtocolException (string.Format (CultureInfo.InvariantCulture, "Failed to connect to {0}:{1}: {2}", host, port, GetFailureReason (buffer[1])));
// +-----+-----+-------+------+----------+----------+
// | VER | REP | RSV | ATYP | BND.ADDR | BND.PORT |
// +-----+-----+-------+------+----------+----------+
// | 1 | 1 | X'00' | 1 | Variable | 2 |
// +-----+-----+-------+------+----------+----------+
var addrType = (Socks5AddressType) buffer[3];
switch (addrType) {
case Socks5AddressType.Domain: return 4 + 1 + buffer[4] + 2;
case Socks5AddressType.IPv6: return 4 + 16 + 2;
case Socks5AddressType.IPv4: return 4 + 4 + 2;
default: throw new ProxyProtocolException ("Proxy server returned unknown address type.");
}
}
/// <summary>
/// Connect to the target host.View on GitHub (pinned to 9d3859a785)