我正在尝试通过Java邮件API连接到使用StartTLS和自签名证书的邮件服务器。 这似乎是一个问题,因为我找不到任何方法为StartTLS设置接受的证书或信任库。
Properties props = new Properties();
props.put("mail.imap.starttls.enable", "true");
props.put("mail.imap.starttls.required", "true");
Session session = Session.getInstance(props);
Store store = session.getStore("imap");
store.connect(hostName, port, userName, userPassword);
当我按原样运行我的应用程序时,我收到此PKIX路径错误:
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
我不想使用像"-Djavax.net.ssl.trustStore"
这样的虚拟机参数,因为我希望每次访问都能控制可信证书。
旁注:我看到人们使用"mail.imap.socketFactory.class"
设置自己SocketFactory
的自定义TrustManager
实现。
但是当我这样做时,我的连接失败了
javax.net.ssl.SSLException: Unrecognized SSL message, plaintext connection?
我认为这是因为设置套接字工厂实际上将使用SMTP over SSL而不是StartTLS(以纯文本连接方式启动并稍后切换到TLS)。
答案 0 :(得分:1)
我使用com.sun.mail:javax.mail:1.5.5
和(根)证书从(不是那么标准的)pfx文件加载的SMTP连接(不是IMAP)。提供给Session.getInstance(props)
的属性按以下方式构建(另请参阅API文档here和here,我认为您只需将smtp
替换为imap
对于大多数属性):
" mail.transport.protocol"," smtp"
" mail.smtp.host","主机名"
" mail.smtp.port"," 25"
" mail.smtp.connecttimeout"," 5000" // 5秒
" mail.smtp.timeout"," 50000" // 50秒
" mail.smtp.ssl.protocols"," TLSv1.2"
" mail.smtp.starttls.required"," true"
现在使用com.sun.mail.util.MailSSLSocketFactory
构建SSL套接字工厂(阅读链接中的API-docs):
MailSSLSocketFactory sslSocketFactory = new MailSSLSocketFactory("TLSv1.2");
创建并初始化(默认)KeyManagerFactory kmf
(例如,通过加载密钥库)。
创建并初始化(默认)TrustManagerFactory tmf
。
拨打sslSocketFactory.setKeyManagers(kmf.getKeyManagers())
和sslSocketFactory.setTrustManagers(tmf.getTrustManagers())
设置属性" mail.smtp.ssl.socketFactory"到sslSocketFactory
实例(使用props.put(k,v)
- 方法)。请注意,已设置已创建和配置的套接字工厂实例,而不是某些String或类。 Javamail将直接使用set socket工厂实例。
使用属性创建会话。
确保已正确配置日志记录并将其设置为TRACE for com.sun.mail。记录显示了"越过线路"在我的例子中显示例如:
DEBUG com.sun.mail.smtp - Found extension "STARTTLS", arg ""
...
TRACE com.sun.mail.smtp.protocol - STARTTLS
TRACE com.sun.mail.smtp.protocol - 220 Ready to start TLS
旁注:创建默认密钥库和信任可以使用this SslUtils
类,方法loadKeyStore(null)
和createDefaultTrustStore()
完成(我之前创建了这个实用程序类来帮助我加载不那么标准的pfx文件。)