{"record":{"id":"c0833b18d7026086","repo":"nginx/nginx","slug":"err-no-required-ssl-certificate","errorCode":null,"errorMessage":"-ERR No required SSL certificate","messagePattern":"-ERR No required SSL certificate","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/mail/ngx_mail_pop3_module.c","lineNumber":60,"sourceCode":"    ngx_string(\"EXTERNAL\"),\n    ngx_null_string   /* NONE */\n};\n\n\nstatic ngx_mail_protocol_t  ngx_mail_pop3_protocol = {\n    ngx_string(\"pop3\"),\n    ngx_string(\"\\x04pop3\"),\n    { 110, 995, 0, 0 },\n    NGX_MAIL_POP3_PROTOCOL,\n\n    ngx_mail_pop3_init_session,\n    ngx_mail_pop3_init_protocol,\n    ngx_mail_pop3_parse_command,\n    ngx_mail_pop3_auth_state,\n\n    ngx_string(\"-ERR internal server error\" CRLF),\n    ngx_string(\"-ERR SSL certificate error\" CRLF),\n    ngx_string(\"-ERR No required SSL certificate\" CRLF)\n};\n\n\nstatic ngx_command_t  ngx_mail_pop3_commands[] = {\n\n    { ngx_string(\"pop3_capabilities\"),\n      NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_1MORE,\n      ngx_mail_capabilities,\n      NGX_MAIL_SRV_CONF_OFFSET,\n      offsetof(ngx_mail_pop3_srv_conf_t, capabilities),\n      NULL },\n\n    { ngx_string(\"pop3_auth\"),\n      NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_1MORE,\n      ngx_conf_set_bitmask_slot,\n      NGX_MAIL_SRV_CONF_OFFSET,\n      offsetof(ngx_mail_pop3_srv_conf_t, auth_methods),\n      &ngx_mail_pop3_auth_methods },","sourceCodeStart":42,"sourceCodeEnd":78,"githubUrl":"https://github.com/nginx/nginx/blob/3f6f7824d4e2eb1ac37dec76683d525ac0ff521c/src/mail/ngx_mail_pop3_module.c#L42-L78","documentation":"POP3 flavor of the missing-client-certificate banner ('no_cert' field of ngx_mail_protocol_t, src/mail/ngx_mail_pop3_module.c:60). Set in ngx_mail_verify_cert (src/mail/ngx_mail_handler.c:424-443): when 'ssl_verify_client on' (mandatory mode, sslcf->verify == 1) and the TLS handshake completed with no client certificate at all (SSL_get_peer_certificate() returns NULL), nginx logs 'client sent no required SSL certificate', sends this '-ERR' line, and closes the connection.","triggerScenarios":"TLS handshake finishes successfully but the client never sends a certificate while ssl_verify_client is 'on'; mail client configured without any client certificate/key; client cert configured but not requested by the TLS layer (wrong profile, e.g. some clients skip the cert when no CA is advertised or when using a stale TLS 1.3 resumption).","commonSituations":"New mail clients or kiosks onboarded without receiving the required client PKI material; Thunderbird/Outlook account set up before mTLS was enforced; TLS session resumption after the policy change; verify changed from optional to on without notifying users.","solutions":["Configure the mail client to present a client certificate for this account (Thunderbird: certificate management per account; openssl s_client for scripted checks).","Confirm the server advertises acceptable CAs (ssl_client_certificate) so clients actually prompt/send the cert.","If the requirement is softer than 'mandatory', use 'ssl_verify_client optional' — absent certs are then allowed and only bad certs are rejected (error 2309 path).","After policy changes, tell clients to start a fresh TLS session (no resumption) — nginx already removes cached sessions on failure, but stale client state can persist."],"exampleFix":"# before\nssl_client_certificate /etc/nginx/client-ca.pem;\nssl_verify_client on;\n# client connects with no client cert -> -ERR No required SSL certificate\n\n# after (option A: give the client a cert)\nopenssl s_client -connect mail.example.com:995 -CAfile client-ca.pem \\\n  -cert user@example.com.pem -key user.key -starttls pop3\n# after (option B: relax the policy)\n#   ssl_verify_client optional;","handlingStrategy":"validation","validationCode":"# assert the session will present a cert\nimport os, ssl\nassert os.path.exists('user.pem') and os.path.exists('user.key'), 'mTLS material missing'\nctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)\nctx.load_cert_chain('user.pem', 'user.key'); ctx.load_verify_locations('client-ca.pem')\n# smoke test: server must not answer with -ERR No required SSL certificate\nwith socket.create_connection(('mail.example.com', 995), timeout=5) as s:\n    tls = ctx.wrap_socket(s, server_hostname='mail.example.com')\n    line = tls.recv(256)\n    assert not line.startswith(b'-ERR No required'), 'no-cert path hit'","typeGuard":null,"tryCatchPattern":"try:\n    m = poplib.POP3_SSL('mail.example.com', 995)\n    m.user(u)\nexcept poplib.error_proto as e:\n    if 'No required SSL certificate' in str(e):\n        raise MTLSConfigError('configure a client certificate for this account') from e\n    raise","preventionTips":["Provision client certs as part of account onboarding, not as an afterthought.","Automated clients: fail fast at startup if cert files are missing before connecting.","After switching ssl_verify_client to on, canary-test a subset of clients first."],"tags":["nginx-mail","pop3","ssl","client-certificate","missing-certificate","mtls"],"backgroundTag":"missing-client-certificate","analyzedSha":"3f6f7824d4e2eb1ac37dec76683d525ac0ff521c","analyzedAt":"2026-08-22T03:09:46.447Z","schemaVersion":2},"datasetVersion":"2026-08-22T04:17:13.399Z"}