web-dev-qa-db-ja.com

JavaMailのエラー:PKIXパスの構築が、要求されたターゲットへの有効な証明書パスを見つけることができませんでした

Android=でメールクライアントアプリを構築しようとしていますが、今はjavaMail部分を構成したいと考えています。

私はimapサーバーとの接続を確立しようとしていますが、私のコードに何か問題があります。ここに私のコードがあります:

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

このような別のクラスからスレッドを呼び出します

connec=new Connection();
 (new Thread(connec)).start();

次のエラーが表示されます。

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

私は証明書をJava信頼できる証明書として保存それをするために。

//メールサーバーにアクセスできません

助言がありますか?ありがとう!

21
fnkbz

OK問題が解決しました!

解決策は次のとおりです。

まず、opensslを介してメールサーバーから自己署名証明書を取得します。

echo | openssl s_client -connect yoursever:port 2>&1 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > yourcert.pem

次に、yourcert.pemファイルをこのパス/ Library/Java/Home/lib/security(macOSX上)に保存し、このようなcacertsに証明書ファイルを配置します

keytool -keystore cacerts -importcert -alias youralias -file yourcert.pem

デフォルトのキーストアパスワードはchangeitです

証明書のフィンガープリントを表示するこのコマンドで行った変更を表示できます。

keytool -list -keystore cacerts

この後、VMでこれらの引数を渡す必要があります

(WindowsおよびLinuxの場合、「」の間にyourpathを入力します)

-Djavax.net.ssl.trustStore="/Library/Java/Home/lib/security/cacerts"

-Djavax.net.ssl.trustStorePassword="changeit"

デバッグ用:

-Djava.security.debug=certpath

-Djavax.net.debug=trustmanager

35
fnkbz

ライブラリjavax.mail.jarを https://Java.net/projects/javamail/pages/Home (現在のバージョンは1.5.5)にアップグレードして、コードを追加できます。

MailSSLSocketFactory sf = new MailSSLSocketFactory();
sf.setTrustAllHosts(true); 
properties.put("mail.imap.ssl.trust", "*");
properties.put("mail.imap.ssl.socketFactory", sf);
25
TungHarry

Java 7から証明書ファイルを取得することにより、この問題を解決する簡単な方法

次のJava 7ディレクトリから「cacerts」ファイルをコピーします

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

それをJava 6ディレクトリに貼り付けます

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

このJavaMail FAQエントリが役立つはずです。

リンクされたサイトからの引用テキスト:

Q:SSL経由でメールサーバーに接続すると、「要求されたターゲットへの有効な証明書パスが見つかりません」などの例外が表示されます。

A:サーバーはおそらく、商用認証局によって署名された証明書ではなく、テスト証明書または自己署名証明書を使用しています。サーバーの証明書をトラストストアにインストールする必要があります。 InstallCertプログラムが役立ちます。

または、「mail.protocol.ssl.trust」プロパティをメールサーバーのホスト名に設定できます。詳細については、プロトコルプロバイダーパッケージのjavadocsを参照してください。

この問題の他の一般的な原因は次のとおりです。

  • 要求を傍受するファイアウォールまたはウイルス対策プログラムがあります。
  • JDKのインストールに問題があり、信頼できる認証局の証明書を見つけることができません。
  • JDKの信頼できる認証局のリストをオーバーライドしたアプリケーションサーバーで実行しています。
3
Bill Shannon

また、メールサーバーと通信するときにこの問題に遭遇しました。ただし、根本的な原因は、サーバー(Exchange 2013)に実際の証明書と自己署名の両方が適用されていることです。適切な対応策は、サーバー上の自己署名を削除することでした。これは、自己署名が優先され、実際の証明書をブロックしていたためです。

0
Brian Knoblauch

私は交換する必要がありました:

props.setProperty("mail.smtp.starttls.enable", "true");
props.setProperty("mail.smtp.auth", "true");

で:

props.put("mail.smtp.starttls.enable", true);
props.put("mail.smtp.auth", true);

エラーを取り除きます。

古代のjavamailバージョンを含むjetty 9を使用していることに注意してください。

このエラーは、証明書に問題があることを意味する必要がないため、これを投稿しました。

0
Tinus Tate

解決策を探すのに何日も費やしましたが、この投稿は私にとって助けになりました。同じ問題がありました。次のようなpemファイルを作成した後、次のコマンドを使用して、certファイルの.pemをcacertファイル(TrustStore.jksというコピー)に追加しました。

keytool.exe -import -noprompt -keystore TrustStore.jks -storepass changeit ^ -alias DOMAINNAME -file MYCERTFILE.pem

(DOMAINNAMEはホスト名に置き換える必要があります-このトリックは非常に重要です-およびMYCERTFILEはファイルの最近の作成によって...)

このソリューションが誰かに役立つことを願っています。

0
titojusto