Невозможно рукопожатие ssl сокетов, имеющих порт 587 и server="smtp.gmail.com"
Этот код отлично работает для PORT = 465. Но для PORT=587 выдается исключение "Исключение в главном потоке javax.net.ssl.SSLException: нераспознанное сообщение SSL, соединение в виде открытого текста?"
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 */
1 ответ
465 - это "неявный" TLS-ранее-SSL; вы подключаетесь на уровне TCP, затем немедленно и всегда запускаете TLS-соединение, и (в случае успеха) затем выполняете SMTP через TLS-соединение (через TCP).
587 - это "явный" TLS-ранее-SSL; вы подключаетесь на уровне TCP и начинаете делать SMTP, читая объявление сервера и выполняя хотя бы команду и ответ EHLO (и, возможно, / необязательно, другие), затем выполняете команду STARTTLS и проверяете ответ, а в случае успеха затем запускайте соединение TLS поверх существующее соединение TCP и (в случае успеха) затем выполнить SMTP через соединение TLS через TCP. Посмотрите на RFC 3207.
Ваше исключение уже говорило вам об этом; это означает, что вы подключились к серверу, который (еще) не выполняет SSL / TLS, но вместо этого выполняет открытый текст - в данном случае SMTP в открытом тексте.
Также очень плохая идея включить все поддерживаемые версии и наборы шифров; многие из них отключены по умолчанию, потому что они не защищены. Несмотря на то, что SSLv3 нарушается POODLE(!), В этом конкретном случае все в порядке, потому что gmail (совершенно правильно) никогда не будет согласовывать его; OTOH, включающий анонимные пакеты, такие как ECDH_anon_AES*, позволяет активному злоумышленнику легко перехватывать, читать и / или изменять вашу предположительно безопасную электронную почту.
Или просто используйте javamail, который уже реализует все эти опции и более правильно.