jstedfast/MailKit · error · ProxyProtocolException
Failed to negotiate authentication method with the proxy…
Error message
Failed to negotiate authentication method with the proxy server.
What it means
MailKit's Socks5Client threw ProxyProtocolException because the SOCKS5 proxy did not accept any of the authentication methods the client offered during method negotiation. When no credentials are configured the client offers only Anonymous; with credentials it offers UserPassword plus Anonymous. If the server replies with 0xFF (no acceptable methods) or an unrecognized method byte, the negotiation switch falls to the default case and this exception is thrown.
Solutions
- Create the Socks5Client with credentials: new Socks5Client(host, port, new NetworkCredential(user, pass)) so UserPassword is negotiated.
- Verify the proxy is genuinely SOCKS5 and the host/port are correct (HTTP proxies will not speak the SOCKS5 handshake).
- Check the proxy server's allowed auth methods (may need GSSAPI or IP allowlisting instead of user/pass).
- Catch ProxyProtocolException and surface a clear configuration error to the user.
Example fix
// before
var proxy = new Socks5Client("proxy.corp.com", 1080);
// after
var proxy = new Socks5Client("proxy.corp.com", 1080, new NetworkCredential("proxyuser", "proxypass")); Defensive patterns
Strategy: try-catch
Validate before calling
var proxy = proxyCredentials != null
? new Socks5Client(proxyHost, proxyPort, proxyCredentials)
: new Socks5Client(proxyHost, proxyPort);
if (proxyCredentials == null)
Console.WriteLine("Warning: no proxy credentials supplied; proxy must allow anonymous access"); Type guard
bool IsSocks5ClientUsable(Socks5Client c) => c != null && !string.IsNullOrEmpty(c.ProxyHost) && c.ProxyPort > 0;
Try / catch
try {
var stream = proxy.Connect(host, port);
} catch (ProxyProtocolException ex) {
// auth negotiation failed: proxy likely requires credentials or an unsupported method
throw new ApplicationException("SOCKS5 proxy authentication negotiation failed; check proxy credentials/type", ex);
} Prevention
- Always configure proxy credentials when the corporate proxy requires auth
- Confirm the proxy scheme is socks5, not http, before choosing the client class
- Test the proxy handshake with a tool like curl --socks5 before deploying
When it happens
Trigger: Calling Socks5Client.Connect() against a SOCKS5 proxy that requires username/password authentication while ProxyCredentials is null (so only Anonymous is offered), or against a proxy that uses an unsupported auth method (e.g. GSSAPI), or a non-SOCKS5 server on the proxy port returning a garbage reply.
Common situations: Connecting through a corporate SOCKS5 proxy that mandates authentication but instantiating Socks5Client(host, port) without a NetworkCredential; proxy server actually an HTTP proxy; wrong proxy port pointing at a different service.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- Failed to authenticate with SOCKS5 proxy server.
- No credentials could be found for the IMAP server.
- Failed to connect to
- Failed to connect to
- Proxy server responded with unknown SOCKS version
AI-assisted analysis of jstedfast/MailKit@9d3859a785 (2026-09-15).
Data as JSON: /api/errors/3eb120e15ebb95cb.
Report an issue: GitHub.
Appendix: source
Thrown at MailKit/Net/Proxy/Socks5Client.cs:417
if (addrType == Socks5AddressType.Domain)
domain = Encoding.UTF8.GetBytes (host);
try {
Socks5AuthMethod method;
if (ProxyCredentials != null)
method = NegotiateAuthMethod (socket, cancellationToken, Socks5AuthMethod.UserPassword, Socks5AuthMethod.Anonymous);
else
method = NegotiateAuthMethod (socket, cancellationToken, Socks5AuthMethod.Anonymous);
switch (method) {
case Socks5AuthMethod.UserPassword:
Authenticate (socket, cancellationToken);
break;
case Socks5AuthMethod.Anonymous:
break;
default:
throw new ProxyProtocolException ("Failed to negotiate authentication method with the proxy server.");
}
var buffer = GetConnectCommand (addrType, domain, ip, port, out int n);
Send (socket, buffer, 0, n, cancellationToken);
// +-----+-----+-------+------+----------+----------+
// | VER | REP | RSV | ATYP | BND.ADDR | BND.PORT |
// +-----+-----+-------+------+----------+----------+
// | 1 | 1 | X'00' | 1 | Variable | 2 |
// +-----+-----+-------+------+----------+----------+
// Note: We know we'll need at least 4 bytes of header + a minimum of 1 byte
// to determine the length of the BND.ADDR field if ATYP is a domain.
int nread, need = 5;
n = 0;
do {View on GitHub (pinned to 9d3859a785)