将JavaMail与自签名证书一起使用

我有一个包含以下代码的servlet:

System.setProperty("javax.net.ssl.keyStore", getServletContext().getRealPath("keystore.jks")); System.setProperty("javax.net.ssl.keyStorePassword", "123456"); System.setProperty("javax.net.ssl.trustStore",getServletContext().getRealPath("keystore.jks")); System.setProperty("javax.net.ssl.trustStorePassword","123456"); SSLSocketFactory sslsocketfactory = (SSLSocketFactory) SSLSocketFactory.getDefault(); SSLSocket sslsocket = (SSLSocket) sslsocketfactory.createSocket("127.0.0.1", 606); 

使用此代码,我可以使用SSL(我的情况是强制性的)。 稍后在同一个servlet中我需要使用JavaMail发送电子邮件。 当我尝试在不使用其他代码中的证书的情况下发送此电子邮件时,它工作正常,但当我尝试使用它时,返回以下消息:使用端口465 – >

 DEBUG: setDebug: JavaMail version 1.4.7 DEBUG: setDebug: JavaMail version 1.4.7 DEBUG: getProvider() returning javax.mail.Provider[TRANSPORT,smtp,com.sun.mail.smtp.SMTPTransport,Oracle] DEBUG SMTP: useEhlo true, useAuth true DEBUG SMTP: useEhlo true, useAuth true DEBUG SMTP: trying to connect to host "smtp.gmail.com", port 465, isSSL false 

Aaand陷入了这个= p。

使用端口587 – >

 DEBUG: setDebug: JavaMail version 1.4.7 DEBUG: getProvider() returning javax.mail.Provider[TRANSPORT,smtp,com.sun.mail.smtp.SMTPTransport,Oracle] DEBUG SMTP: useEhlo true, useAuth true DEBUG SMTP: useEhlo true, useAuth true DEBUG SMTP: trying to connect to host "smtp.gmail.com", port 587, isSSL false 220 mx.google.com ESMTP g66sm55412571yhd.11 - gsmtp DEBUG SMTP: connected to host "smtp.gmail.com", port: 587 EHLO RAI-PC 250-mx.google.com at your service, [201.82.118.174] 250-SIZE 35882577 250-8BITMIME 250-STARTTLS 250 ENHANCEDSTATUSCODES DEBUG SMTP: Found extension "SIZE", arg "35882577" DEBUG SMTP: Found extension "8BITMIME", arg "" DEBUG SMTP: Found extension "STARTTLS", arg "" DEBUG SMTP: Found extension "ENHANCEDSTATUSCODES", arg "" DEBUG SMTP: use8bit false MAIL FROM: 530 5.7.0 Must issue a STARTTLS command first. g66sm55412571yhd.11 - gsmtp DEBUG SMTP: got response code 530, with response: 530 5.7.0 Must issue a STARTTLS command first. g66sm55412571yhd.11 - gsmtp RSET 250 2.1.5 Flushed g66sm55412571yhd.11 - gsmtp DEBUG SMTP: MessagingException while sending, THROW: com.sun.mail.smtp.SMTPSendFailedException: 530 5.7.0 Must issue a STARTTLS command first. g66sm55412571yhd.11 - gsmtp at com.sun.mail.smtp.SMTPTransport.issueSendCommand(SMTPTransport.java:2108) at com.sun.mail.smtp.SMTPTransport.mailFrom(SMTPTransport.java:1609) at com.sun.mail.smtp.SMTPTransport.sendMessage(SMTPTransport.java:1117) at javax.mail.Transport.send0(Transport.java:195) at javax.mail.Transport.send(Transport.java:124) at servlet.Main.service(Main.java:221) at javax.servlet.http.HttpServlet.service(HttpServlet.java:728) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123) at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99) at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:953) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408) at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1023) at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:589) at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:310) at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) at java.lang.Thread.run(Unknown Source) QUIT 221 2.0.0 closing connection g66sm55412571yhd.11 - gsmtp Jul 10, 2013 7:04:40 PM org.apache.catalina.core.StandardWrapperValve invoke SEVERE: Servlet.service() for servlet [servletMain] in context with path [/servicotcc] threw exception java.lang.RuntimeException: com.sun.mail.smtp.SMTPSendFailedException: 530 5.7.0 Must issue a STARTTLS command first. g66sm55412571yhd.11 - gsmtp at servlet.Main.service(Main.java:226) at javax.servlet.http.HttpServlet.service(HttpServlet.java:728) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123) at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99) at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:953) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408) at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1023) at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:589) at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:310) at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) at java.lang.Thread.run(Unknown Source) Caused by: com.sun.mail.smtp.SMTPSendFailedException: 530 5.7.0 Must issue a STARTTLS command first. g66sm55412571yhd.11 - gsmtp at com.sun.mail.smtp.SMTPTransport.issueSendCommand(SMTPTransport.java:2108) at com.sun.mail.smtp.SMTPTransport.mailFrom(SMTPTransport.java:1609) at com.sun.mail.smtp.SMTPTransport.sendMessage(SMTPTransport.java:1117) at javax.mail.Transport.send0(Transport.java:195) at javax.mail.Transport.send(Transport.java:124) at servlet.Main.service(Main.java:221) ... 17 more 

属性代码:

 Properties props = new Properties(); props.put("mail.smtp.host", "smtp.gmail.com"); props.put("mail.smtp.socketFactory.port", "465"); props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory"); props.put("mail.smtp.auth", "true"); props.put("mail.smtp.port", "465"); 

我无法发送这样的电子邮件(我不确定究竟是什么原因)。 我该怎么办?

– 编辑 –

将Google SMTP证书导入我的密钥库并将端口和属性更改为:

 Properties props = new Properties(); props.put("mail.smtp.host", "smtp.gmail.com"); props.put("mail.smtp.socketFactory.port", "465"); props.put("mail.smtp.socketFactory.class", sslsocketfactory); props.put("mail.smtp.auth", "true"); props.put("mail.smtp.port", "465"); props.put("mail.smtp.ssl.enable", "true"); props.put("mail.smtp.starttls.enable", "true"); 

我的输出更改为:

 DEBUG: setDebug: JavaMail version 1.4.7 DEBUG: getProvider() returning javax.mail.Provider[TRANSPORT,smtp,com.sun.mail.smtp.SMTPTransport,Oracle] DEBUG SMTP: useEhlo true, useAuth true DEBUG SMTP: useEhlo true, useAuth true DEBUG SMTP: trying to connect to host "smtp.gmail.com", port 465, isSSL true Jul 10, 2013 8:26:46 PM org.apache.catalina.core.StandardWrapperValve invoke SEVERE: Servlet.service() for servlet [servletMain] in context with path [/servicotcc] threw exception java.lang.RuntimeException: javax.mail.MessagingException: Could not connect to SMTP host: smtp.gmail.com, port: 465; 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 servlet.Main.service(Main.java:229) at javax.servlet.http.HttpServlet.service(HttpServlet.java:728) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123) at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99) at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:953) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408) at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1023) at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:589) at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:310) at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) at java.lang.Thread.run(Unknown Source) Caused by: javax.mail.MessagingException: Could not connect to SMTP host: smtp.gmail.com, port: 465; 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.smtp.SMTPTransport.openServer(SMTPTransport.java:1961) at com.sun.mail.smtp.SMTPTransport.protocolConnect(SMTPTransport.java:654) at javax.mail.Service.connect(Service.java:317) at javax.mail.Service.connect(Service.java:176) at javax.mail.Service.connect(Service.java:125) at javax.mail.Transport.send0(Transport.java:194) at javax.mail.Transport.send(Transport.java:124) at servlet.Main.service(Main.java:224) ... 17 more 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(Unknown Source) at sun.security.ssl.SSLSocketImpl.fatal(Unknown Source) at sun.security.ssl.Handshaker.fatalSE(Unknown Source) at sun.security.ssl.Handshaker.fatalSE(Unknown Source) at sun.security.ssl.ClientHandshaker.serverCertificate(Unknown Source) at sun.security.ssl.ClientHandshaker.processMessage(Unknown Source) at sun.security.ssl.Handshaker.processLoop(Unknown Source) at sun.security.ssl.Handshaker.process_record(Unknown Source) at sun.security.ssl.SSLSocketImpl.readRecord(Unknown Source) at sun.security.ssl.SSLSocketImpl.performInitialHandshake(Unknown Source) at sun.security.ssl.SSLSocketImpl.startHandshake(Unknown Source) at sun.security.ssl.SSLSocketImpl.startHandshake(Unknown Source) at com.sun.mail.util.SocketFetcher.configureSSLSocket(SocketFetcher.java:549) at com.sun.mail.util.SocketFetcher.createSocket(SocketFetcher.java:354) at com.sun.mail.util.SocketFetcher.getSocket(SocketFetcher.java:237) at com.sun.mail.smtp.SMTPTransport.openServer(SMTPTransport.java:1927) ... 24 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(Unknown Source) at sun.security.validator.PKIXValidator.engineValidate(Unknown Source) at sun.security.validator.Validator.validate(Unknown Source) at sun.security.ssl.X509TrustManagerImpl.validate(Unknown Source) at sun.security.ssl.X509TrustManagerImpl.checkTrusted(Unknown Source) at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(Unknown Source) ... 36 more Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(Unknown Source) at java.security.cert.CertPathBuilder.build(Unknown Source) ... 42 more 

摆脱套接字工厂的东西 :

设置各种socketFactory属性。 很久很久以前,JavaMail没有内置对SSL连接的支持,因此有必要将这些属性设置为使用SSL。 多年来情况并非如此; 删除这些属性并简化您的代码。 在当前版本的JavaMail中启用SSL支持的最简单方法是将属性“mail.smtp.ssl.enable”设置为“true”。 (根据需要将“smtp”替换为“imap”或“pop3”。)

请参阅这些Gmail示例 。

Gmail证书需要位于您的信任存储区 ,而不是您的密钥存储区。

解决方案 – 将属性更改为:

  Properties props = new Properties(); props.put("mail.smtp.host", "smtp.gmail.com"); props.put("mail.smtp.socketFactory.port", "587"); props.put("mail.smtp.socketFactory.class", "javax.net.SocketFactory"); props.put("mail.smtp.auth", "true"); props.put("mail.smtp.port", "587"); props.put("mail.smtp.ssl.enable", "false"); props.put("mail.smtp.starttls.enable", "true"); props.put("mail.smtp.ssl.trust", "smtp.gmail.com");