已經發現的問題是 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?
沒有留言:
張貼留言