Problem
Jenkins suddenly stops sending notification mails through pipeline scripts or UI-based build jobs.
/var/log/jenkins/jenkins.log
does not show any errors. When trying to send a test mail through Jenkins' administration UI, you'll receive the errror
sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at java.base/sun.security.provider.certpath.SunCertPathBuilder.build(SunCertPathBuilder.java:141)
at java.base/sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:126)
at java.base/java.security.cert.CertPathBuilder.build(CertPathBuilder.java:297)
at java.base/sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:380)
Caused: sun.security.validator.ValidatorException: PKIX path building failed
at java.base/sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:385)
at java.base/sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:290)
at java.base/sun.security.validator.Validator.validate(Validator.java:264)
at java.base/sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:313)
at java.base/sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:222)
at java.base/sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:129)
at java.base/sun.security.ssl.CertificateMessage$T12CertificateConsumer.checkServerCerts(CertificateMessage.java:625)
Caused: javax.net.ssl.SSLHandshakeException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:131)
at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:320)
at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:263)
at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:258)
at java.base/sun.security.ssl.CertificateMessage$T12CertificateConsumer.checkServerCerts(CertificateMessage.java:641)
at java.base/sun.security.ssl.CertificateMessage$T12CertificateConsumer.onCertificate(CertificateMessage.java:460)
at java.base/sun.security.ssl.CertificateMessage$T12CertificateConsumer.consume(CertificateMessage.java:360)
at java.base/sun.security.ssl.SSLHandshake.consume(SSLHandshake.java:392)
at java.base/sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:443)
at java.base/sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:421)
at java.base/sun.security.ssl.TransportContext.dispatch(TransportContext.java:177)
at java.base/sun.security.ssl.SSLTransport.decode(SSLTransport.java:164)
at java.base/sun.security.ssl.SSLSocketImpl.decode(SSLSocketImpl.java:1152)
at java.base/sun.security.ssl.SSLSocketImpl.readHandshakeRecord(SSLSocketImpl.java:1063)
at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:402)
at com.sun.mail.util.SocketFetcher.configureSSLSocket(SocketFetcher.java:626)
at com.sun.mail.util.SocketFetcher.startTLS(SocketFetcher.java:553)
at com.sun.mail.smtp.SMTPTransport.startTLS(SMTPTransport.java:2150)
Jenkins is configured (e.g. through JAVA_ARGS
in /etc/default/jenkins
) to always use STARTTLS for SMTP by passing -Dmail.smtp.starttls.enable=true
as start paramater.
Solution
The error occurs if an invalid x.509 certificate has been provided by the SMTP server, e.g. if the certificate has expired. First, check the certificate of the SMTP server:
openssl s_client -showcerts -connect ${SMTP_SERVER}:25 -starttls smtp
You can either use an online certificate decoder or get the expiration date from the following command:
openssl s_client -showcerts -connect ${SMTP_SERVER}:25 -starttls smtp 2>/dev/null | openssl x509 -noout -dates
Now, check the certificate in Java's keystore. On Debian, Java's keystore can be found at /etc/ssl/certs/java/cacerts
. /usr/lib/jvm/${JAVA_DIST}/lib/security/cacerts
is just a symlink to it.
Use changeit
as default password for the keystore.
keytool -list -v -keystore /etc/ssl/certs/java/cacerts | grep -A 10 "${SMTP_SERVER}" | grep "until"
Convert binary certificate
If the keystore has still the old certificate in it, you have to export either the SMTP server's active certificate or the root CA. For a Windows-environment with an Exchange server, you can convert the binary certificate from CER to PEM with
openssl x509 -inform der -in ${SMTP_SERVER}.cer -out ${SMTP_SERVER}.pem
Remove old certificate
Find the alias of the old certificate and then remove it
keytool -list -v -cacerts | grep -A 10 "${SMTP_SERVER}" | grep "Alias name:" # note alias
keytool -delete -alias "${ALIAS_NAME}" -v -cacerts
Import converted certificate into Java's keystore
Copy the ${SMTP_SERVER}.pem
to your host.
keytool -importcert -alias rootca -keystore /etc/ssl/certs/java/cacerts -file ${SMTP_SERVER}.pem
# restart Jenkins to apply keystore changes
systemctl restart jenkins