Try all IP addresses when connecting to a POP3 server

This commit is contained in:
cketti 2022-10-28 12:24:22 +02:00
parent 4d070167b2
commit 4908bcad47
2 changed files with 45 additions and 13 deletions

View file

@ -5,9 +5,10 @@ import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;
import java.net.UnknownHostException;
import java.security.GeneralSecurityException;
import java.security.KeyManagementException;
import java.security.MessageDigest;
@ -61,15 +62,7 @@ class Pop3Connection {
void open() throws MessagingException {
try {
SocketAddress socketAddress = new InetSocketAddress(settings.getHost(), settings.getPort());
if (settings.getConnectionSecurity() == ConnectionSecurity.SSL_TLS_REQUIRED) {
socket = trustedSocketFactory.createSocket(null, settings.getHost(),
settings.getPort(), settings.getClientCertificateAlias());
} else {
socket = new Socket();
}
socket.connect(socketAddress, SOCKET_CONNECT_TIMEOUT);
socket = connect();
in = new BufferedInputStream(socket.getInputStream(), 1024);
out = new BufferedOutputStream(socket.getOutputStream(), 512);
@ -102,6 +95,44 @@ class Pop3Connection {
}
}
private Socket connect()
throws IOException, MessagingException, NoSuchAlgorithmException, KeyManagementException {
InetAddress[] inetAddresses = InetAddress.getAllByName(settings.getHost());
IOException connectException = null;
for (InetAddress address : inetAddresses) {
try {
return connectToAddress(address);
} catch (IOException e) {
Timber.w(e, "Could not connect to %s", address);
connectException = e;
}
}
throw connectException != null ? connectException : new UnknownHostException();
}
private Socket connectToAddress(InetAddress address)
throws IOException, MessagingException, NoSuchAlgorithmException, KeyManagementException {
if (K9MailLib.isDebug() && K9MailLib.DEBUG_PROTOCOL_POP3) {
Timber.d("Connecting to %s as %s", settings.getHost(), address);
}
InetSocketAddress socketAddress = new InetSocketAddress(address, settings.getPort());
final Socket socket;
if (settings.getConnectionSecurity() == ConnectionSecurity.SSL_TLS_REQUIRED) {
socket = trustedSocketFactory.createSocket(null, settings.getHost(), settings.getPort(),
settings.getClientCertificateAlias());
} else {
socket = new Socket();
}
socket.connect(socketAddress, SOCKET_CONNECT_TIMEOUT);
return socket;
}
/*
* If STARTTLS is not available throws a CertificateValidationException which in K-9
* triggers a "Certificate error" notification that takes the user to the incoming

View file

@ -37,7 +37,7 @@ class Pop3StoreTest {
@Test(expected = MessagingException::class)
fun `checkSettings() with TrustedSocketFactory throwing should throw MessagingException`() {
stubbing(trustedSocketFactory) {
on { createSocket(null, "server", 12345, null) } doThrow IOException()
on { createSocket(null, HOST, 12345, null) } doThrow IOException()
}
store.checkSettings()
@ -72,7 +72,7 @@ class Pop3StoreTest {
private fun createServerSettings(): ServerSettings {
return ServerSettings(
type = "pop3",
host = "server",
host = HOST,
port = 12345,
connectionSecurity = ConnectionSecurity.SSL_TLS_REQUIRED,
authenticationType = AuthType.PLAIN,
@ -93,13 +93,14 @@ class Pop3StoreTest {
}
stubbing(trustedSocketFactory) {
on { createSocket(null, "server", 12345, null) } doReturn socket
on { createSocket(null, HOST, 12345, null) } doReturn socket
}
return outputStream
}
companion object {
private const val HOST = "127.0.0.1"
private const val INITIAL_RESPONSE = "+OK POP3 server greeting\r\n"
private const val CAPA_RESPONSE = "+OK Listing of supported mechanisms follows\r\n" +