Rewrite SMTP connect code to properly handle all network errors
Previously e.g. a SocketTimeoutException would exit the loop to test all addresses early.
This commit is contained in:
parent
142124c19a
commit
2bd2f22b1f
1 changed files with 36 additions and 29 deletions
|
@ -33,7 +33,6 @@ import java.net.Inet6Address
|
||||||
import java.net.InetAddress
|
import java.net.InetAddress
|
||||||
import java.net.InetSocketAddress
|
import java.net.InetSocketAddress
|
||||||
import java.net.Socket
|
import java.net.Socket
|
||||||
import java.net.SocketException
|
|
||||||
import java.security.GeneralSecurityException
|
import java.security.GeneralSecurityException
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
import javax.net.ssl.SSLException
|
import javax.net.ssl.SSLException
|
||||||
|
@ -83,35 +82,10 @@ class SmtpTransport(
|
||||||
@Throws(MessagingException::class)
|
@Throws(MessagingException::class)
|
||||||
override fun open() {
|
override fun open() {
|
||||||
try {
|
try {
|
||||||
var secureConnection = false
|
var secureConnection = connectionSecurity == ConnectionSecurity.SSL_TLS_REQUIRED
|
||||||
val addresses = InetAddress.getAllByName(host)
|
|
||||||
for ((index, address) in addresses.withIndex()) {
|
|
||||||
try {
|
|
||||||
val socketAddress = InetSocketAddress(address, port)
|
|
||||||
if (connectionSecurity == ConnectionSecurity.SSL_TLS_REQUIRED) {
|
|
||||||
socket = trustedSocketFactory.createSocket(null, host, port, clientCertificateAlias).also {
|
|
||||||
it.connect(socketAddress, SOCKET_CONNECT_TIMEOUT)
|
|
||||||
}
|
|
||||||
secureConnection = true
|
|
||||||
} else {
|
|
||||||
socket = Socket().also {
|
|
||||||
it.connect(socketAddress, SOCKET_CONNECT_TIMEOUT)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (e: SocketException) {
|
|
||||||
if (index < addresses.lastIndex) {
|
|
||||||
// there are still other addresses for that host to try
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
throw MessagingException("Cannot connect to host", e)
|
val socket = connect()
|
||||||
}
|
this.socket = socket
|
||||||
|
|
||||||
// connection success
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
val socket = this.socket ?: error("socket == null")
|
|
||||||
|
|
||||||
socket.soTimeout = SOCKET_READ_TIMEOUT
|
socket.soTimeout = SOCKET_READ_TIMEOUT
|
||||||
|
|
||||||
|
@ -263,6 +237,39 @@ class SmtpTransport(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun connect(): Socket {
|
||||||
|
val inetAddresses = InetAddress.getAllByName(host)
|
||||||
|
|
||||||
|
var connectException: Exception? = null
|
||||||
|
for (address in inetAddresses) {
|
||||||
|
connectException = try {
|
||||||
|
return connectToAddress(address)
|
||||||
|
} catch (e: IOException) {
|
||||||
|
Timber.w(e, "Could not connect to %s", address)
|
||||||
|
e
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw MessagingException("Cannot connect to host", connectException)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun connectToAddress(address: InetAddress): Socket {
|
||||||
|
if (K9MailLib.isDebug() && K9MailLib.DEBUG_PROTOCOL_SMTP) {
|
||||||
|
Timber.d("Connecting to %s as %s", host, address)
|
||||||
|
}
|
||||||
|
|
||||||
|
val socketAddress = InetSocketAddress(address, port)
|
||||||
|
val socket = if (connectionSecurity == ConnectionSecurity.SSL_TLS_REQUIRED) {
|
||||||
|
trustedSocketFactory.createSocket(null, host, port, clientCertificateAlias)
|
||||||
|
} else {
|
||||||
|
Socket()
|
||||||
|
}
|
||||||
|
|
||||||
|
socket.connect(socketAddress, SOCKET_CONNECT_TIMEOUT)
|
||||||
|
|
||||||
|
return socket
|
||||||
|
}
|
||||||
|
|
||||||
private fun readGreeting() {
|
private fun readGreeting() {
|
||||||
val smtpResponse = responseParser!!.readGreeting()
|
val smtpResponse = responseParser!!.readGreeting()
|
||||||
logResponse(smtpResponse)
|
logResponse(smtpResponse)
|
||||||
|
|
Loading…
Reference in a new issue