ChatGPT解决这个技术问题 Extra ChatGPT

Javamail Could not convert socket to TLS GMail

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

please give the complete stack trace. Your exact code runs fine on my machine
@Laabidi I already posted it.

Z
Zero Piraeus
props.put("mail.smtp.ssl.trust", "smtp.gmail.com");

Can you expand on why/how you think this proposed solution will resolve the question?
This one did the magic but the answer could do better at expanding on a bit of more details like @Denomales says. Good tip though. My guess is that this prop tells you programme to blindly trust ssl connection whether it has the right certificate ?
From javamail docs - 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.
For me props.put("mail.smtp.ssl.trust", "*"); did the trick
@AryaPourtabatabaie, no. He should rely on the operating system to automatically sort that out. It's likely, actually probable, that he has a configuration issue. He's circumventing the protections put in place.
S
Shahid Abbasi

I disabled avast antivirus for 10 minutes and get it working.


P
Paul Lammertsma

Make sure your antivirus program isn't interfering and be sure to add an exclusion to your firewall.


am a victim of this question, what i gave is my own solution,
Truly said. Avast was creating problem. Thanx buddy
Same here, Avast was somehow the problem
AVG version 18.1.3044 (with Windows 10) interfer with my Spring application. Solution: enter in AVG section called "Web and email" and disable the "email protection".
Avast was my problem as well. Deactivated it for 10 minutes and everything worked.
D
Delirante

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


Thank you so much, this was the trick for me ;)
Yep this was it, great answer
Yep, this was it. Thanks.
ℛɑƒæĿᴿᴹᴿ

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.


n
nurb

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 :)


Commenting the Jave line of code "htmlEmail.setStartTLSEnabled(true);" (org.apache.commons.mail.HtmlEmail) also solved the problem for me.
P
Petar Bivolarski

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

In my case it was the same but different antivirus. Thanks, It helped a lot
P
Priyanka Wagh

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

when using spring - plain javamail properties can be found here: javaee.github.io/javamail/docs/api/com/sun/mail/smtp/…
C
Catalan Cabbage

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.


V
Vladi

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");

t
trilogy

Try changing the port to 465

mail.smtp.socketFactory.port=465
mail.smtp.port=465

i
isapir

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.


This was the solution for me, thanks!
R
Rizwan_Khan

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."


s
surajs1n

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


R
Robert

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");
    }

}

S
SJX

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/


Latest version has moved to the Eclipse Foundation: projects.eclipse.org/projects/ee4j.mail
d
dev

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.


I
Ishfaq

In my case, I was using OpenJDK, when I switched to OracleJDK the issue was resolved.


I don't think that's a solution.
t
trilogy

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

B
Bill Shannon

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.


It Still did not, How would I know if there's a problem with my JDK configuration or network configuration?
What still did not what? If smtpsend fails in the same way, that's how you know the problem isn't with your code but with something else, most likely your JDK configuration or network configuration. If you have a firewall or antivirus running on your machine, try disabling while you run the test. What version of the JDK are you using? Try reinstalling the JDK to see if that helps.
M
Miadnew

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).