Unrecognized SSL message, plaintext connection?

       本文来自: 高爽|Coder,原文地址: http://blog.csdn.net/ghsau/article/details/17779165,转载请注明。
       以这个错误信息为文章标题是不是更醒目一点,这是JavaMail使用SSL的方式登录邮箱时抛出的异常。代码如:
public class JavaMailTest1 {
	public static void main(String[] args) throws MessagingException {
		Properties props = new Properties();
		props.setProperty("mail.debug", "true");
		props.setProperty("mail.smtp.auth", "true");
		props.setProperty("mail.transport.protocol", "smtp");
		
		// SSL
		props.setProperty("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
		props.setProperty("mail.smtp.socketFactory.fallback", "false");
		props.setProperty("mail.smtp.port", "465");
		props.setProperty("mail.smtp.socketFactory.port", "465");
		
		Session session = Session.getInstance(props);
		
		Message msg = new MimeMessage(session);
		msg.setText("你好吗?");
		msg.setFrom(new InternetAddress("发件箱地址"));
		
		Transport transport = session.getTransport();
		transport.connect("smtp.sina.com", "用户名", "密码");
		transport.sendMessage(msg, new Address[] {new InternetAddress("收件箱地址")});
		transport.close();
	}
}
       解决该问题方式:将端口号修改成465。通常服务器的SSL端口是443,邮箱服务器中的是465。修改后,运行程序,又会出现一个新的异常:
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:1972)
	at com.sun.mail.smtp.SMTPTransport.protocolConnect(SMTPTransport.java:642)
	at javax.mail.Service.connect(Service.java:295)
	at javax.mail.Service.connect(Service.java:176)
       这通常意味着是该服务器使用的是测试证书(使用密钥工具可能产生的),而不是从一个著名的商业证书颁发机构如Verisign或GoDaddy的证书。 在此情况下,但由于JSSE( Java(TM)SecureSocketExtension)不能假定一个交互式的用户存在,它只是在默认情况下会抛出异常。解决该问题的思路就是将你要连接的SSL服务器的证书添加为JSSE受信任的证书。那如何产生证书呢?通过下面的代码(如果没有看到请刷新页面):         编译该类并运行,运行时要传一个参数:SSL服务器域名:端口号,如:java InstallCert smtp.sina.com:465,不输端口的话默认为443。运行之后:
Loading KeyStore C:\Program Files\Java\jre7\lib\security\cacerts...
Opening connection to smtp.sina.com:465...
Starting SSL handshake...

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 InstallCert.main(InstallCert.java:97)
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)
        at InstallCert$SavingTrustManager.checkServerTrusted(InstallCert.java:192)
        at sun.security.ssl.AbstractTrustManagerWrapper.checkServerTrusted(Unknown Source)
        ... 9 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)
        ... 17 more

Server sent 1 certificate(s):

 1 Subject CN=*.sina.com, O="Sina.com Technology(China)Co.,ltd", L=Beijing, ST=Beijing, C=CN, SERIALNUMBER=mL/iTnzl-0Pr1rH-6U2RZH/h3zFjZxoK
   Issuer  CN=GeoTrust SSL CA, O="GeoTrust, Inc.", C=US
   sha1    43 a9 5b bc 9b 86 85 99 e3 21 63 af b0 09 78 4a 67 25 d7 a1
   md5     90 c2 45 da 67 68 cd c2 44 56 21 ef ed c6 6b 5e

Enter certificate to add to trusted keystore or 'q' to quit: [1]
       抛出了与我们程序中同样的错误,这里我们输入1,回车。它又输出了一堆信息,这里不粘了,这时证书已经生成了,在哪呢?在InstallCert.java所在的目录中,有一个名为jssecacerts的文件,这就是我们要的证书。将其放到我们程序所在的JSSE中,$JAVA_HOME/jre/lib/security。这时,再次运行我们的发邮件程序,发送成功。
        更新2014-01-04
       今天无意中看到了JavaMail有这样的协议支持描述:
Protocol	Store or	Uses	Supports
Name		Transport?	SSL?	STARTTLS?
-------------------------------------------------
imap		Store		No	    Yes
imaps		Store		Yes	    N/A
pop3		Store		No	    Yes
pop3s		Store		Yes	    N/A
smtp		Transport	No	    Yes
smtps		Transport	Yes	    N/A
       Transport使用SSL连接邮箱协议名称需要使用smtps,而不是smtp,那前面提到的程序只需这样:
public class JavaMailTest1 {
	public static void main(String[] args) throws MessagingException {
		Properties props = new Properties();
		props.setProperty("mail.debug", "true");
		props.setProperty("mail.smtp.auth", "true");
		
		// 协议名称设置为smtps,会使用SSL
		props.setProperty("mail.transport.protocol", "smtps");
		
		Session session = Session.getInstance(props);
		
		Message msg = new MimeMessage(session);
		msg.setText("你好吗?");
		msg.setFrom(new InternetAddress("发件箱地址"));
		
		Transport transport = session.getTransport();
		transport.connect("smtp.sina.com", "用户名", "密码");
		transport.sendMessage(msg, new Address[] {new InternetAddress("收件箱地址")});
		transport.close();
	}
}
       这样,JavaMail会自动使用SSL,并且使用465端口。
       参考: https://java.net/projects/javamail/pages/InstallCert  http://infposs.blogspot.com/2013/06/installcert-and-java-7.html
       本文来自: 高爽|Coder,原文地址: http://blog.csdn.net/ghsau/article/details/17779165,转载请注明。

你可能感兴趣的:(java,ssl,tls,javamail)