无法握手具有端口 587 和 server="smtp.gmail.com" 的 ssl 套接字
Cannot handshake ssl sockets having port 587 and server="smtp.gmail.com"
此代码适用于 PORT=465。
但是对于 PORT=587,它抛出异常 "Exception in thread main javax.net.ssl.SSLException: Unrecognized SSL message, plaintext connection?"
package smtpClient;
import java.io.IOException;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import javax.naming.NamingException;
import javax.net.ssl.HandshakeCompletedEvent;
import javax.net.ssl.HandshakeCompletedListener;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
class TLS_Mime_G {
static final int PORT = 587;
static String REMOTEHOST = "smtp.gmail.com";
public static void main(String[] args)
throws IOException, NoSuchAlgorithmException, NamingException, KeyManagementException {
SSLSocketFactory ssf = (SSLSocketFactory) SSLSocketFactory.getDefault();
SSLSocket socket = (SSLSocket) ssf.createSocket(REMOTEHOST, PORT);
socket.setEnabledProtocols(socket.getSupportedProtocols());
socket.setEnabledCipherSuites(socket.getSupportedCipherSuites());
socket.addHandshakeCompletedListener(new MyTLSHandshakeListener());
socket.startHandshake();//Throws Error
System.out.println("Connected to " + socket.getRemoteSocketAddress());
}
}
class MyTLSHandshakeListener implements HandshakeCompletedListener {
public void handshakeCompleted(HandshakeCompletedEvent e) {
System.out.println("Handshake succesful!");
System.out.println("Cipher suite used: " + e.getCipherSuite());
}
}
/*
支持的协议:SSLv2Hello
支持的协议:SSLv3
支持的协议:TLSv1
支持的协议:TLSv1.1
支持的协议:TLSv1.2
启用的协议:TLSv1
启用的协议:TLSv1.1
启用的协议:TLSv1.2
*/
465 是 'implicit' TLS-前身-SSL;您在 TCP 级别连接,然后立即并始终启动 TLS 连接,并且(如果成功)然后通过 TLS(通过 TCP)连接执行 SMTP。
587 是 'explicit' TLS-前身-SSL;您在 TCP 级别连接并通过阅读服务器公告并至少执行 EHLO 命令和响应(以及 possibly/optionally 其他)开始执行 SMTP,然后执行 STARTTLS 命令并检查响应,如果成功则启动 TLS通过现有 TCP 连接建立连接,然后(如果成功)通过 TLS over TCP 连接执行 SMTP。 Have a look at rfc 3207.
你的异常已经告诉你了;它表明您已经连接到一个服务器,该服务器(尚未)执行 SSL/TLS 而是执行明文 - 在本例中为明文 SMTP。
此外,启用所有受支持的版本和密码套件是一个非常糟糕的主意;默认情况下禁用其中许多 因为 它们不安全。尽管 SSLv3 在这种特殊情况下被 POODLE(!) 破坏了,但没关系,因为 gmail(非常正确)永远不会协商它;启用像 ECDH_anon_AES* 这样的匿名套件的 OTOH 允许主动攻击者轻松拦截、读取 and/or 更改您所谓的安全电子邮件。
或者只使用 javamail,它已经实现了所有这些选项以及更多 正确。
此代码适用于 PORT=465。 但是对于 PORT=587,它抛出异常 "Exception in thread main javax.net.ssl.SSLException: Unrecognized SSL message, plaintext connection?"
package smtpClient;
import java.io.IOException;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import javax.naming.NamingException;
import javax.net.ssl.HandshakeCompletedEvent;
import javax.net.ssl.HandshakeCompletedListener;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
class TLS_Mime_G {
static final int PORT = 587;
static String REMOTEHOST = "smtp.gmail.com";
public static void main(String[] args)
throws IOException, NoSuchAlgorithmException, NamingException, KeyManagementException {
SSLSocketFactory ssf = (SSLSocketFactory) SSLSocketFactory.getDefault();
SSLSocket socket = (SSLSocket) ssf.createSocket(REMOTEHOST, PORT);
socket.setEnabledProtocols(socket.getSupportedProtocols());
socket.setEnabledCipherSuites(socket.getSupportedCipherSuites());
socket.addHandshakeCompletedListener(new MyTLSHandshakeListener());
socket.startHandshake();//Throws Error
System.out.println("Connected to " + socket.getRemoteSocketAddress());
}
}
class MyTLSHandshakeListener implements HandshakeCompletedListener {
public void handshakeCompleted(HandshakeCompletedEvent e) {
System.out.println("Handshake succesful!");
System.out.println("Cipher suite used: " + e.getCipherSuite());
}
}
/* 支持的协议:SSLv2Hello 支持的协议:SSLv3 支持的协议:TLSv1 支持的协议:TLSv1.1 支持的协议:TLSv1.2 启用的协议:TLSv1 启用的协议:TLSv1.1 启用的协议:TLSv1.2 */
465 是 'implicit' TLS-前身-SSL;您在 TCP 级别连接,然后立即并始终启动 TLS 连接,并且(如果成功)然后通过 TLS(通过 TCP)连接执行 SMTP。
587 是 'explicit' TLS-前身-SSL;您在 TCP 级别连接并通过阅读服务器公告并至少执行 EHLO 命令和响应(以及 possibly/optionally 其他)开始执行 SMTP,然后执行 STARTTLS 命令并检查响应,如果成功则启动 TLS通过现有 TCP 连接建立连接,然后(如果成功)通过 TLS over TCP 连接执行 SMTP。 Have a look at rfc 3207.
你的异常已经告诉你了;它表明您已经连接到一个服务器,该服务器(尚未)执行 SSL/TLS 而是执行明文 - 在本例中为明文 SMTP。
此外,启用所有受支持的版本和密码套件是一个非常糟糕的主意;默认情况下禁用其中许多 因为 它们不安全。尽管 SSLv3 在这种特殊情况下被 POODLE(!) 破坏了,但没关系,因为 gmail(非常正确)永远不会协商它;启用像 ECDH_anon_AES* 这样的匿名套件的 OTOH 允许主动攻击者轻松拦截、读取 and/or 更改您所谓的安全电子邮件。
或者只使用 javamail,它已经实现了所有这些选项以及更多 正确。