others-how to solve java mail SMTP TLS error?
1. Purpose
In this post, I will demonstrate how to solve the following error or exception when using java mail to send emails via SMTP over TLS protocol:
javax.mail.MessagingException: Could not convert socket to TLS;
nested exception is:
javax.net.ssl.SSLException: Received fatal alert: protocol_version
at com.sun.mail.smtp.SMTPTransport.startTLS(SMTPTransport.java:1907)
at com.sun.mail.smtp.SMTPTransport.protocolConnect(SMTPTransport.java:666)
at javax.mail.Service.connect(Service.java:295)
at com.bswen.wx.utils.EmailTest.sendMail(EmailTest.java:109)
at com.bswen.wx.utils.EmailTest.main(EmailTest.java:58)
Caused by: javax.net.ssl.SSLException: Received fatal alert: protocol_version
at sun.security.ssl.Alerts.getSSLException(Alerts.java:208)
at sun.security.ssl.Alerts.getSSLException(Alerts.java:154)
at sun.security.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java:2023)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1125)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1375)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1403)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1387)
at com.sun.mail.util.SocketFetcher.configureSSLSocket(SocketFetcher.java:549)
at com.sun.mail.util.SocketFetcher.startTLS(SocketFetcher.java:486)
at com.sun.mail.smtp.SMTPTransport.startTLS(SMTPTransport.java:1902)
... 4 more
Process finished with exit code 0
2. Solution
2.1 The code that caused the problem
package com.bswen.email.utils;
import com.sun.mail.smtp.SMTPTransport;
import com.sun.mail.util.MailSSLSocketFactory;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeUtility;
import java.io.UnsupportedEncodingException;
import java.security.GeneralSecurityException;
import java.util.Properties;
/**
* email utils.
*/
public class EmailTest {
private static Log log = LogFactory.getLog(EmailTest.class);
private static final String host = "smtp.bswen.com";
private static final int port = 587;
private static final String sender = "[email protected]";
private static final Properties props;
private static final String senderPasswd = "******";
public static void sendMail(String subject,String body,
String recipients) throws MessagingException {
Properties tmpProps = props;
String tmpSender = sender;
String tmpPasswd = senderPasswd;
Session mailSession = Session.getInstance(tmpProps, null);
MimeMessage message = new MimeMessage(mailSession);
try {
InternetAddress from = new InternetAddress(tmpSender);
message.setFrom(from);
String[] recvUsers = parseRecipients(recipients);
InternetAddress[] recipientsAdresses = new InternetAddress[recvUsers.length];
int i=0;
for(String recvUser:recvUsers) {
InternetAddress to = new InternetAddress(recvUser);
recipientsAdresses[i++]=to;
}
message.setRecipients(MimeMessage.RecipientType.TO, recipientsAdresses);
try {
message.setSubject(subject);
} catch (UnsupportedEncodingException e) {
message.setSubject(subject);
}
SMTPTransport t =
(SMTPTransport) mailSession.getTransport("smtp");
t.connect(host,port, tmpSender, tmpPasswd);
t.sendMessage(message, message.getAllRecipients());
}
catch (MessagingException e) {
throw e;
}
}
}
The pom dependency of java mail:
<dependency>
<groupId>com.sun.mail</groupId>
<artifactId>javax.mail</artifactId>
<version>1.4.7</version>
</dependency>
2.2 The solution
Upgrade the java mail jar :
Using 1.6 javax.mail jar as follows:
<dependency>
<groupId>com.sun.mail</groupId>
<artifactId>javax.mail</artifactId>
<version>1.6.2</version>
</dependency>
If you get the following error after upgrading the dependency:
I got this error:
/Library/Java/JavaVirtualMachines/jdk1.8.0_121.jdk/Contents/Home/bin/java
javax.mail.MessagingException: Could not convert socket to TLS;
nested exception is:
javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at com.sun.mail.smtp.SMTPTransport.startTLS(SMTPTransport.java:2155)
at com.sun.mail.smtp.SMTPTransport.protocolConnect(SMTPTransport.java:752)
at javax.mail.Service.connect(Service.java:366)
at com.bswen.wx.utils.EmailTest.sendMail(EmailTest.java:109)
at com.bswen.wx.utils.EmailTest.main(EmailTest.java:58)
Caused by: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1949)
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:302)
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:296)
at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1514)
at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:216)
at sun.security.ssl.Handshaker.processLoop(Handshaker.java:1026)
at sun.security.ssl.Handshaker.process_record(Handshaker.java:961)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1062)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1375)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1403)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1387)
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)
... 4 more
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:387)
at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:230)
at sun.security.validator.Validator.validate(Validator.java:260)
at sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:324)
at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:229)
at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:124)
at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1496)
... 14 more
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.provider.certpath.SunCertPathBuilder.build(SunCertPathBuilder.java:141)
at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:126)
at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:280)
at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:382)
... 20 more
Process finished with exit code 0
You can just add trust to the SMTP host/server. for example:
props.put("mail.smtp.starttls.enable", "true");
props.put("mail.smtp.ssl.trust", host);
props.put("mail.smtp.ssl.trust", host);
Because:
mail.smtp.ssl.trust String If set, and a socket factory hasn’t been specified, enables use of a MailSSLSocketFactory. If set to “*”, all hosts are trusted. If set to a whitespace separated list of hosts, those hosts are trusted. Otherwise, trust depends on the certificate the server presents.
3. Summary
In this post, I demonstrated how to solve the errors when using java mail to send email via SMTP servers. That’s it, thanks for your reading.