From 4908bcad47fbe6992b16ae21c96d279f466d3cb4 Mon Sep 17 00:00:00 2001 From: cketti Date: Fri, 28 Oct 2022 12:24:22 +0200 Subject: [PATCH] Try all IP addresses when connecting to a POP3 server --- .../k9/mail/store/pop3/Pop3Connection.java | 51 +++++++++++++++---- .../fsck/k9/mail/store/pop3/Pop3StoreTest.kt | 7 +-- 2 files changed, 45 insertions(+), 13 deletions(-) diff --git a/mail/protocols/pop3/src/main/java/com/fsck/k9/mail/store/pop3/Pop3Connection.java b/mail/protocols/pop3/src/main/java/com/fsck/k9/mail/store/pop3/Pop3Connection.java index aaff29d73..4badc73e5 100644 --- a/mail/protocols/pop3/src/main/java/com/fsck/k9/mail/store/pop3/Pop3Connection.java +++ b/mail/protocols/pop3/src/main/java/com/fsck/k9/mail/store/pop3/Pop3Connection.java @@ -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 diff --git a/mail/protocols/pop3/src/test/java/com/fsck/k9/mail/store/pop3/Pop3StoreTest.kt b/mail/protocols/pop3/src/test/java/com/fsck/k9/mail/store/pop3/Pop3StoreTest.kt index 82ab36616..554f76683 100644 --- a/mail/protocols/pop3/src/test/java/com/fsck/k9/mail/store/pop3/Pop3StoreTest.kt +++ b/mail/protocols/pop3/src/test/java/com/fsck/k9/mail/store/pop3/Pop3StoreTest.kt @@ -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" +