问题
I am trying to build an email client app in android and right now i want to configure the javaMail part.
i am trying to establish the connection with the imap server but something is wrong with my code.. here is my code:
package mailpackage;
import java.util.Properties;
import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.NoSuchProviderException;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Store;
public class Connection implements Runnable
{
boolean done;
public Connection()
{
this.done=false;
}
@Override
public void run()
{
System.out.println("Hello from Connection Thread!");
while(!done)
{
String host = "myhost";// change accordingly
String mailStoreType = "imap";
String username = "myusername";// change accordingly
String password = "mypasswd";// change accordingly
check(host, mailStoreType, username, password);
}
}
public static void receiveEmail(String host, String storeType, String username, String password)
{
try
{
Properties properties = new Properties();
properties.put("mail.imap.com", host);
properties.put("mail.imap.starttls.enable","true");
properties.put("mail.imap.auth", "true"); // If you need to authenticate
// Use the following if you need SSL
properties.put("mail.imap.socketFactory.port", 993);
properties.put("mail.imap.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
properties.put("mail.imap.socketFactory.fallback", "false");
Session emailSession = Session.getDefaultInstance(properties);
emailSession.setDebug(true);
//2) create the IMAP store object and connect with the Imap server
IMAPStore emailStore = (IMAPStore) emailSession.getStore(storeType);
emailStore.connect(host, username, password);
//3) create the folder object and open it
Folder emailFolder = emailStore.getFolder("INBOX");
emailFolder.open(Folder.READ_ONLY);
//4) retrieve the messages from the folder in an array and print it
Message[] messages = emailFolder.getMessages();
for (int i = 0; i <messages.length; i++)
{
Message message = messages[i];
MimeMessage m = new MimeMessage(emailSession);
m.setContent(((MimeMessage)messages[i]).getContent() , "text/plain; charset=UTF-8");
System.out.println("---------------------------------");
System.out.println("Email Number " + (i + 1));
System.out.println("Subject: " + message.getSubject());
System.out.println("From: " + message.getFrom()[0]);
System.out.println("Text: " + message.getContent().toString());
m.writeTo(System.out);
}
//5) close the store and folder objects
emailFolder.close(false);
emailStore.close();
}
catch (NoSuchProviderException e) {e.printStackTrace();}
catch (MessagingException e) {e.printStackTrace();}
catch (IOException e) {e.printStackTrace();}
}
public void stopThread()
{
this.done=true;
}
}
I call the thread from another class like this
connec=new Connection();
(new Thread(connec)).start();
I get the Following errors:
javax.mail.MessagingException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target;
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.imap.IMAPStore.protocolConnect(IMAPStore.java:571)
at javax.mail.Service.connect(Service.java:288)
at javax.mail.Service.connect(Service.java:169)
at mailpackage.Connection.check(Connection.java:63)
at mailpackage.Connection.run(Connection.java:33)
at java.lang.Thread.run(Thread.java:744)
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:1884)
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:276)
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:270)
at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1341)
at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:153)
at sun.security.ssl.Handshaker.processLoop(Handshaker.java:868)
at sun.security.ssl.Handshaker.process_record(Handshaker.java:804)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1016)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1312)
at sun.security.ssl.SSLSocketImpl.readDataRecord(SSLSocketImpl.java:882)
at sun.security.ssl.AppInputStream.read(AppInputStream.java:102)
at com.sun.mail.util.TraceInputStream.read(TraceInputStream.java:110)
at java.io.BufferedInputStream.fill(BufferedInputStream.java:235)
at java.io.BufferedInputStream.read(BufferedInputStream.java:254)
at com.sun.mail.iap.ResponseInputStream.readResponse(ResponseInputStream.java:98)
at com.sun.mail.iap.Response.<init>(Response.java:96)
at com.sun.mail.imap.protocol.IMAPResponse.<init>(IMAPResponse.java:61)
at com.sun.mail.imap.protocol.IMAPResponse.readResponse(IMAPResponse.java:135)
at com.sun.mail.imap.protocol.IMAPProtocol.readResponse(IMAPProtocol.java:261)
at com.sun.mail.iap.Protocol.<init>(Protocol.java:114)
at com.sun.mail.imap.protocol.IMAPProtocol.<init>(IMAPProtocol.java:104)
at com.sun.mail.imap.IMAPStore.protocolConnect(IMAPStore.java:538)
... 5 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:385)
at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:292)
at sun.security.validator.Validator.validate(Validator.java:260)
at sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:326)
at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:231)
at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:126)
at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1323)
... 23 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:196)
at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:268)
at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:380)
... 29 more
i read something about PKIX path error that says to add the cert to java store as a trusted cert, but i dont know if this is the solution for this, and if it is i dont know how to do it.
// i dont have access to the mail server
Any suggestions? thanks!
回答1:
Ok problem solved!
The solution is this:
First get the self-signed certificate from the mail server via openssl:
echo | openssl s_client -connect yoursever:port 2>&1 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > yourcert.pem
Then save the yourcert.pem file into this path /Library/Java/Home/lib/security (on macOSX) and put the cert file into the cacerts like this
keytool -keystore cacerts -importcert -alias youralias -file yourcert.pem
The default keystore password is changeit
You can view the change that you made with this command that shows the Certificate fingerprint.
keytool -list -keystore cacerts
After this you should pass these argument in VM
(for windows and linux type yourpath between " " )
-Djavax.net.ssl.trustStore="/Library/Java/Home/lib/security/cacerts"
-Djavax.net.ssl.trustStorePassword="changeit"
For Debug:
-Djava.security.debug=certpath
-Djavax.net.debug=trustmanager
回答2:
You can try upgrade library javax.mail.jar at https://java.net/projects/javamail/pages/Home (now version is 1.5.5) and add code :
MailSSLSocketFactory sf = new MailSSLSocketFactory();
sf.setTrustAllHosts(true);
properties.put("mail.imap.ssl.trust", "*");
properties.put("mail.imap.ssl.socketFactory", sf);
回答3:
This JavaMail FAQ entry should help.
Quoted text from the linked site:
Q: When connecting to my mail server over SSL I get an exception like "unable to find valid certification path to requested target".
A: Your server is probably using a test certificate or self-signed certificate instead of a certificate signed by a commercial Certificate Authority. You'll need to install the server's certificate into your trust store. The InstallCert program will help.
Alternatively, you can set the "mail.protocol.ssl.trust" property to the host name of your mail server. See the javadocs for the protocol provider packages for details.
Other common causes of this problem are:
- There's a firewall or anti-virus program intercepting your request.
- There's something wrong in your JDK installation preventing it from finding the certificates for the trusted certificate authorities.
- You're running in an application server that has overridden the JDK's list of trusted certificate authorities.
回答4:
easy way to solve this problem by getiing certificate file from Java 7
copy the "cacerts" file from following java 7 directory
C:\Program Files\Java\jdk1.7.0_79\jre\lib\security
and paste it in java 6 directory
C:\Program Files\Java\jdk1.6.0\jre\lib\security
回答5:
I've lost so many days searching for a solution, and this post was helps to me. I had the same problem. I created a pem file like here, and then, the cert file .pem, was incrusted in cacert file (a copy called TrustStore.jks) with this command:
keytool.exe -import -noprompt -keystore TrustStore.jks -storepass changeit ^ -alias DOMAINNAME -file MYCERTFILE.pem
(DOMAINNAME must be replace by hostname -this trick is very important-, and MYCERTFILE by file recent create...)
I hope that this solution can helps to somebody.
回答6:
I also have run across this problem when talking to a mail server. However, the root cause was that the server (Exchange 2013) had both a real certificate AND a self-signed applied to it. The appropriate course of action was to remove the self-signed on the server because it was taking precedence and blocking the real certificate.
来源:https://stackoverflow.com/questions/20122099/error-in-javamail-pkix-path-building-failed-unable-to-find-valid-certification