简体   繁体   中英

Sending an email in Java with commons-mail

So I'm trying to send a code to my email with Java. I started out with javax.mail but remember I had problems with it last time I used it so I moved on to Apache Commons Mail.

I'm getting a bunch of errors though. On SSL, I'm getting a java.net.SocketTimeoutException and on TLS, I'm getting a handful of errors:

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

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

Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

When I did a quick Google search, I found this question . Now because I'm a complete idiot, I do not understand the answer.

What can I do to resolve the errors? Whether it be preventing the Timeout on SSL or the others on TLS.

EDIT: I do not have a problem sending emails and MessageException is NOT my problem so please stop answering with that.

As far as I remember that had a similar issue with sending emails too.

I'll show on example of org.springframework.mail.javamail.JavaMailSenderImpl . Basically there are several approaches for handling this case. The answer that you've found will also work but it will work on the JVM level. I've stopped not on the JVM approach like you've found.

What should be done

Add host (for example let's take a look at gmail host: smtp.gmail.com ). By adding host to the trusted - everything started to work as expected. In my case I had to add this host to the

Part of spring xml configuration

<bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
    <property name="host" value="${mail.host}"/>
    <property name="port" value="${mail.port}"/>
    <property name="username" value="${mail.username}"/>
    <property name="password" value="${mail.password}"/>
    <property name="javaMailProperties">
        <props>
            <prop key="mail.transport.protocol">${mail.transport.protocol}</prop>
            <prop key="mail.smtp.auth">${mail.smtp.auth}</prop>
            <prop key="mail.smtp.starttls.enable">${mail.smtp.starttls.enable}</prop>
            <prop key="mail.smtp.ssl.trust">${mail.smtp.ssl.trust}</prop>
        </props>
    </property>
</bean>

Properties file

mail.host=smtp.gmail.com
mail.port=587
mail.username=user@gmail.com
mail.password=password
mail.transport.protocol=smtp
mail.smtp.auth=true
mail.smtp.starttls.enable=true
mail.smtp.ssl.trust=smtp.gmail.com

Take into account that you should give the appropriate permissions in case of gmail from the security console .

UPDATE

Did you have a chance to try the code below from the official website of Apache Common Email :

Email email = new SimpleEmail();
email.setHostName("smtp.googlemail.com");
email.setSmtpPort(465);
email.setAuthenticator(new DefaultAuthenticator("username", "password"));
email.setSSLOnConnect(true);
email.setFrom("user@gmail.com");
email.setSubject("TestMail");
email.setMsg("This is a test mail ... :-)");
email.addTo("foo@bar.com");
email.send();
Email email = new SimpleEmail();
...

// add this line
email.getMailSession().getProperties().put("mail.smtp.ssl.trust", "smtp.gmail.com");

...
email.send();

Using library javax.mail with version 1.5.0-b01 you can find that there is simple method to avoid that kind of errors. Here is example that i used sometime ago and it works pretty much fine:

        Properties props = new Properties();
        MailSSLSocketFactory socketFactory = new MailSSLSocketFactory();
        socketFactory.setTrustAllHosts(true);
        props.put("mail.imaps.ssl.socketFactory", socketFactory);

If you are using maven you can add this dependency:

 <dependency>
  <groupId>javax.mail</groupId>
  <artifactId>mail</artifactId>
  <version>1.5.0-b01</version>
</dependency>

i got the same kind of error, here is the solution for it

add this line: props.put("mail.smtp.ssl.trust", "smtp.gmail.com");

Reference: http://javainfinite.com/java/send-email-using-gmail-in-java/

to resolve the ssl hank shake issue persisted in java 6.get certificateds from java 7.java 7 have the certificates file having the capability of ignoring certificate authentication.

copy the "cacerts" file from following java 7 directory

C:\\Program Files\\Java\\jdk1.7.0_79\\jre\\lib\\security

and paste it in

C:\\Program Files\\Java\\jdk1.6.0\\jre\\lib\\security

The error

PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target 

is that the certificate chain is broken. That means that the provider might be using a self signed certificate which is not trusted by the client system. The trusted Certificates are stored in the cacerts in C:\\Program Files\\Java\\jdk1.6.0\\jre\\lib\\security as described in an answer above.

A solution to this might be to add the Root certificates or intermediate certificates that are missing to cacerts. Of course you do that if you trust the host that provides these certificates. ie usually corporations tent to create their own certificates for internal use.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM