I'm trying to send an email using JavaMail through Gmail SMTP Server. This is the code:
final String username = "mygmail@gmail.com";
final String password = "mygmailpassword";
Properties props = new Properties();
props.put("mail.smtp.auth", true);
props.put("mail.smtp.starttls.enable", true);
props.put("mail.smtp.host", "smtp.gmail.com");
props.put("mail.smtp.port", "587");
Session session = Session.getInstance(props,
new javax.mail.Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(username, password);
}
}
);
try {
Message message = new MimeMessage(session);
message.setFrom(new InternetAddress("no-reply@gmail.com"));
message.setRecipients(Message.RecipientType.TO,
InternetAddress.parse("test@gmail.com"));
message.setSubject("Testing Subject");
message.setText("Dear Mail Crawler," + "\n\n No spam to my email, please!");
Transport.send(message);
System.out.println("Done");
} catch (MessagingException e) {
throw new RuntimeException(e);
}
Returns an this error:
Could not convert socket to TLS;
The complete stacktrace:
Exception in thread "main" java.lang.RuntimeException: 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 Test.main(Test.java:43) Caused by: 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:1907) at com.sun.mail.smtp.SMTPTransport.protocolConnect(SMTPTransport.java:666) at javax.mail.Service.connect(Service.java:317) at javax.mail.Service.connect(Service.java:176) at javax.mail.Service.connect(Service.java:125) at javax.mail.Transport.send0(Transport.java:194) at javax.mail.Transport.send(Transport.java:124) at Test.main(Test.java:38) 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 com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:174) at com.sun.net.ssl.internal.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1649) at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:241) at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:235) at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1206) at com.sun.net.ssl.internal.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:136) at com.sun.net.ssl.internal.ssl.Handshaker.processLoop(Handshaker.java:593) at com.sun.net.ssl.internal.ssl.Handshaker.process_record(Handshaker.java:529) at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:893) at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1138) at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1165) at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1149) 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) ... 7 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:323) at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:217) at sun.security.validator.Validator.validate(Validator.java:218) at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:126) at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:209) at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:249) at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1185) ... 17 more Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:174) at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:238) at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:318) ... 23 more
props.put("mail.smtp.ssl.trust", "smtp.gmail.com");
I disabled avast antivirus for 10 minutes and get it working.
Make sure your antivirus program isn't interfering and be sure to add an exclusion to your firewall.
I got similar problem when default SSL protocol for sending emails was set to TLSv1 and smtp server was not supporting this protocol anymore. Trick was to use newer protocol:
mail.smtp.ssl.protocols=TLSv1.2
The first answer from @carlos worked for me:
session.getProperties().put("mail.smtp.ssl.trust", "smtp.gmail.com");
I have tested the property below and worked perfectly for me too:
session.getProperties().put("mail.smtp.starttls.enable", "true");
The two properties alone solved this type of problem, but by guarantee I used both.
In my case the problem was solved by deleting the line
prop.put("mail.smtp.starttls.enable", "true");
It may be because of some ssl configuration errors on email server, I'm not sure. Email server administrators never admit it and always blame hosting provider :)
After a full day of search, I disabled Avast for 10 minutes and Windows Firewall (important) and everything started working!
This was my error:
Mail server connection failed; nested exception is 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. Failed messages: 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
Here is how to fix the issue in Avast 19.8.2393 by adding an exclusion to SMTP port 587 (or whichever port your application uses):
Open Avast Click on 'Settings' Click on 'Troubleshooting' and then 'Open old settings'
https://i.stack.imgur.com/XZww0.png
Click again on 'Troubleshooting', scroll down to 'Redirect settings' and delete the port that your app uses.
https://i.stack.imgur.com/oWxtD.png
In my case, I just removed 587 from SMTP ports.
Now I am able to use Avast and also have my Windows Firewall switched on (no need to add additional exclusion for the Firewall).
Here are my application.properties e-mail properties:
###### I am using a Google App Password which I generated in my Gmail Security settings ######
spring.mail.host = smtp.gmail.com
spring.mail.port = 587
spring.mail.protocol = smtp
spring.mail.username = gmail account
spring.mail.password = password
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=true
spring.mail.properties.mail.smtp.connectiontimeout=5000
spring.mail.properties.mail.smtp.timeout=5000
spring.mail.properties.mail.smtp.writetimeout=5000
above application.properties worked amazing for me:
spring.mail.properties.mail.smtp.starttls.enable=true
spring.mail.properties.mail.smtp.starttls.required=true
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.ssl.trust=smtp.gmail.com
This can also be if the application does not support the TLS version the SMTP host is using.
For example, trying to configure an SMTP server that uses TLSv1.2 without fallback, when your application(or java program using an older javax.mail JAR) supports only upto TLSv1.1.
check that you have all this fields
Properties props = new Properties();
props.put("mail.smtp.host", "smtp.gmail.com");
props.put("mail.smtp.port", "587");
props.put("mail.smtp.auth", "true");
props.put("mail.smtp.ssl.protocols", "TLSv1.2");
props.put("mail.smtp.starttls.enable", "true");
Try changing the port to 465
mail.smtp.socketFactory.port=465
mail.smtp.port=465
It depends on the "Nested Exception". If the nested exception is "no appropriate protocol" then specify the protocol in a System property:
-Dmail.smtp.ssl.protocols=TLSv1.2
I see that some people suggest to set it in the code that creates the STMP session, but that would require a patching and deployment if you want to update the value in the future. Using a System property allows you to update it without changing the code.
If your context is android application , then make sure your android device time is set to current date and time. The underlying exception is "The SSL certificates was not getting authenticated."
Yes, it works for me on localhost:
props.put("mail.smtp.ssl.trust", "smtp.gmail.com");
The error is only thrown on localhost, so you should try on remote servers too. Usually, it is the snippet of code mentioned above that works well without ssl.trust
property
Here is the working solution bro. It's guaranteed
1) First of all open your gmail account from which you wanted to send mail, like in you case ""xyz@gmail.com"
2) open this link below https://support.google.com/accounts/answer/6010255?hl=en
3) click on "Go to the "Less secure apps" section in My Account." option
4) Then turn on it
5) that's it (:
here is my code
import javax.mail.*;
import javax.mail.internet.*;
import java.util.*;
public class SendEmail {
final String senderEmailID = "Sender Email id";
final String senderPassword = "Sender Pass word";
final String emailSMTPserver = "smtp.gmail.com";
final String emailServerPort = "465";
String receiverEmailID = null;
static String emailSubject = "Test Mail";
static String emailBody = ":)";
public SendEmail(String receiverEmailID, String emailSubject, String emailBody)
{
this.receiverEmailID=receiverEmailID;
this.emailSubject=emailSubject;
this.emailBody=emailBody;
Properties props = new Properties();
props.put("mail.smtp.user",senderEmailID);
props.put("mail.smtp.host", emailSMTPserver);
props.put("mail.smtp.port", emailServerPort);
props.put("mail.smtp.starttls.enable", "true");
props.put("mail.smtp.auth", "true");
props.put("mail.smtp.socketFactory.port", emailServerPort);
props.put("mail.smtp.socketFactory.class","javax.net.ssl.SSLSocketFactory");
props.put("mail.smtp.socketFactory.fallback", "false");
SecurityManager security = System.getSecurityManager();
try
{
Authenticator auth = new SMTPAuthenticator();
Session session = Session.getInstance(props, auth);
MimeMessage msg = new MimeMessage(session);
msg.setText(emailBody);
msg.setSubject(emailSubject);
msg.setFrom(new InternetAddress(senderEmailID));
msg.addRecipient(Message.RecipientType.TO,
new InternetAddress(receiverEmailID));
Transport.send(msg);
System.out.println("Message send Successfully:)");
}
catch (Exception mex)
{
mex.printStackTrace();
}
}
public class SMTPAuthenticator extends javax.mail.Authenticator
{
public PasswordAuthentication getPasswordAuthentication()
{
return new PasswordAuthentication(senderEmailID, senderPassword);
}
}
public static void main(String[] args) {
SendEmail mailSender;
mailSender = new SendEmail("Receiver Email id","Testing Code 2 example","Testing Code Body yess");
}
}
Check the version of your JavaMail lib (mail.jar or javax.mail.jar). Maybe you need a newer one. Download the newest version from here: https://javaee.github.io/javamail/
Below set of properties in application.properties
did the trick for me:
spring.mail.host=smtp.gmail.com
spring.mail.port=587
spring.mail.username=<gmail_id>
spring.mail.password=<gmail_password>
spring.mail.properties.mail.smtp.ssl.trust=smtp.gmail.com
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=true
spring.mail.properties.mail.smtp.starttls.required=true
Note that if you have enabled 2-Step Verification for your Gmail account then the gmail_password
in the above configuration should not be an ordinary password but a 16-character application password generated for your Google account. Follow this link to see the details and to generate your Google App Password.
In my case, I was using OpenJDK, when I switched to OracleJDK the issue was resolved.
The main answer:
props.put("mail.smtp.ssl.trust", "smtp.gmail.com");
only worked after I removed the following:
mail.smtp.socketFactory.class=javax.net.ssl.SSLSocketFactory
Try using the smtpsend program that comes with JavaMail, as described here. If that fails in the same way, there's something wrong with your JDK configuration or your network configuration.
What helped me fix this, and i have tried everything before this, was to configure my installed jre to JRE 1.8.
Steps in Eclipse: Windows>preferences>java>installed JRE>jre1.8.0
If it is set to jdk, switch to jre(which is what is supposed to be set to by default with the latest java version).
Success story sharing
mail.smtp.ssl.trust
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.props.put("mail.smtp.ssl.trust", "*");
did the trick