已經發現的問題是 JavaMail 在建立 Socket 連線時會噴以下的 Exception:
javax.mail.MessagingException: Could not connect to SMTP host: smtp.gmail.com, port: 465; nested exception is: java.io.IOException: Can't create MailSSLSocketFactory at com.sun.mail.smtp.SMTPTransport.openServer(SMTPTransport.java:1966) at com.sun.mail.smtp.SMTPTransport.protocolConnect(SMTPTransport.java:654) at javax.mail.Service.connect(Service.java:295) at javax.mail.Service.connect(Service.java:176) at org.twgogo.jimwayne.mail.MailService.sendMail(MailService.java:266) at org.twgogo.jimwayne.mail.MailService.sendMail(MailService.java:157) at org.twgogo.jimwayne.main.Main.sendMail(Main.java:52) at org.twgogo.jimwayne.main.Main.main(Main.java:23) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:616) at org.eclipse.jdt.internal.jarinjarloader.JarRsrcLoader.main(JarRsrcLoader.java:58) Caused by: java.io.IOException: Can't create MailSSLSocketFactory at com.sun.mail.util.SocketFetcher.createSocket(SocketFetcher.java:344) at com.sun.mail.util.SocketFetcher.getSocket(SocketFetcher.java:239) at com.sun.mail.smtp.SMTPTransport.openServer(SMTPTransport.java:1929) ... 12 more Caused by: java.security.KeyStoreException: problem accessing trust storejava.io.EOFException at sun.security.ssl.TrustManagerFactoryImpl.engineInit(TrustManagerFactoryImpl.java:75) at javax.net.ssl.TrustManagerFactory.init(TrustManagerFactory.java:247) at com.sun.mail.util.MailSSLSocketFactory$MailTrustManager.<init>(MailSSLSocketFactory.java:333) at com.sun.mail.util.MailSSLSocketFactory$MailTrustManager.<init>(MailSSLSocketFactory.java:331) at com.sun.mail.util.MailSSLSocketFactory.<init>(MailSSLSocketFactory.java:115) at com.sun.mail.util.MailSSLSocketFactory.<init>(MailSSLSocketFactory.java:94) at com.sun.mail.util.SocketFetcher.createSocket(SocketFetcher.java:337) ... 14 more
我把建立 Socket 的程式碼獨立拿出來執行時,發現 Exception 變成以下的內容:
java.net.SocketException: java.security.NoSuchAlgorithmException: Error constructing implementation (algorithm: Default, provider: SunJSSE, class: sun.security.ssl.DefaultSSLContextImpl) at javax.net.ssl.DefaultSSLSocketFactory.throwException(SSLSocketFactory.java:196) at javax.net.ssl.DefaultSSLSocketFactory.createSocket(SSLSocketFactory.java:203) at org.twgogo.jimwayne.socket.SocketTester.createSocket(SocketTester.java:16) at org.twgogo.jimwayne.main.TestMain.main(TestMain.java:15) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:616) at org.eclipse.jdt.internal.jarinjarloader.JarRsrcLoader.main(JarRsrcLoader.java:58) Caused by: java.security.NoSuchAlgorithmException: Error constructing implementation (algorithm: Default, provider: SunJSSE, class: sun.security.ssl.DefaultSSLContextImpl) at java.security.Provider$Service.newInstance(Provider.java:1262) at sun.security.jca.GetInstance.getInstance(GetInstance.java:236) at sun.security.jca.GetInstance.getInstance(GetInstance.java:164) at javax.net.ssl.SSLContext.getInstance(SSLContext.java:142) at javax.net.ssl.SSLContext.getDefault(SSLContext.java:85) at javax.net.ssl.SSLSocketFactory.getDefault(SSLSocketFactory.java:119) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:616) at org.twgogo.jimwayne.socket.SocketTester.getSocketFactory(SocketTester.java:42) at org.twgogo.jimwayne.socket.SocketTester.createSocket(SocketTester.java:15) ... 6 more Caused by: java.io.EOFException at java.io.DataInputStream.readInt(DataInputStream.java:392) at sun.security.provider.JavaKeyStore.engineLoad(JavaKeyStore.java:645) at sun.security.provider.JavaKeyStore$JKS.engineLoad(JavaKeyStore.java:55) at java.security.KeyStore.load(KeyStore.java:1201) at sun.security.ssl.TrustManagerFactoryImpl.getCacertsKeyStore(TrustManagerFactoryImpl.java:221) at sun.security.ssl.DefaultSSLContextImpl.getDefaultTrustManager(DefaultSSLContextImpl.java:87) at sun.security.ssl.DefaultSSLContextImpl.<init>(DefaultSSLContextImpl.java:57) at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) at java.lang.reflect.Constructor.newInstance(Constructor.java:532) at java.lang.Class.newInstance0(Class.java:372) at java.lang.Class.newInstance(Class.java:325) at java.security.Provider$Service.newInstance(Provider.java:1238) ... 17 more
看起來有點奇怪,因為獨立抽出來的程式碼中並沒有指定要用 SunJSSE 的東西
只有指定 SocketFactory 要用 javax.net.ssl.SSLSocketFactory。
而 Google 時看起來 OpenJDK 內建應該有 javax.net.ssl.SSLSocketFactory 這個 class
不知道為什麼程式跑一跑自己會跑去抓 SunJSSE。
雖然也有可能是本來就要去找 SunJSSE 的某些東西,但因為網路上搜尋時好像沒有看到有人說 JavaMail 在 OpenJDK 上沒辦法用
理論上應該比較有可能的還是我有哪裡弄錯了才對。
Still keep working!
2013-02-26 補充:
後來交給廠商處理,廠商說他們用的 OpenJDK 是自己客製化過的版本,所以並不是 OpenJDK 本身有問題...
他們更新了自己客製化的 OpenJDK 後,這個問題就消失了...。
後來雖然又有出現 Read timeout 的問題,但把 JavaMail 版本從 1.4.4 升級成 1.4.6 就好了
不知道是被什麼影響到的~原本我們自己的環境中用 Sun JDK 1.6.0 + JavaMail 1.4.4 一直都用得很好。
參考資料:
1、SSL with javamail not working
2、Is Java SSL broken in OpenJDK on Ubuntu?
沒有留言:
張貼留言