Check all resolved addresses [deb #413030]
From: Mark Brown <broonie@sirena.org.uk> Currently offlineimap will attempt to connect to the first address returned by addrinfo() for the remote system and will fail if that fails even if another result would have worked. This is particularly common when the remote system supports both IPv4 and IPv6 - a laptop may in some environments have no routable IPv6 connectivity so if the IPv6 address is returned first the connect will fail even though IPv4 would have worked. This is actually a bug in imaplib, a copy of which is included in offlineimap. This patch fixes the problem by looping over all the results returned by getaddrinfo(). Unfortunately it mangles the error reporting slightly since I couldn't work out how to raise an appropriate exception, though given that that that was a Python backtrace there was work to do there anyway. Note that I have only tested the SSL case.
This commit is contained in:
parent
ca3a306ecc
commit
82d5d5e675
@ -218,15 +218,26 @@ class IMAP4:
|
||||
"""
|
||||
self.host = host
|
||||
self.port = port
|
||||
#This connects to the first ip found ipv4/ipv6
|
||||
#Added by Adriaan Peeters <apeeters@lashout.net> based on a socket
|
||||
#example from the python documentation:
|
||||
#http://www.python.org/doc/lib/socket-example.html
|
||||
res = socket.getaddrinfo(host, port, socket.AF_UNSPEC,
|
||||
socket.SOCK_STREAM)
|
||||
af, socktype, proto, canonname, sa = res[0]
|
||||
self.sock = socket.socket(af, socktype, proto)
|
||||
self.sock.connect(sa)
|
||||
|
||||
# Try each address returned by getaddrinfo in turn until we
|
||||
# manage to connect to one.
|
||||
# Try all the addresses in turn until we connect()
|
||||
last_error = 0
|
||||
for remote in res:
|
||||
af, socktype, proto, canonname, sa = remote
|
||||
self.sock = socket.socket(af, socktype, proto)
|
||||
last_error = self.sock.connect_ex(sa)
|
||||
print af
|
||||
if last_error == 0:
|
||||
break
|
||||
else:
|
||||
self.sock.close()
|
||||
if last_error != 0:
|
||||
# FIXME
|
||||
raise socket.error(last_error)
|
||||
self.file = self.sock.makefile('rb')
|
||||
|
||||
def read(self, size):
|
||||
@ -1132,9 +1143,20 @@ class IMAP4_SSL(IMAP4):
|
||||
#http://www.python.org/doc/lib/socket-example.html
|
||||
res = socket.getaddrinfo(host, port, socket.AF_UNSPEC,
|
||||
socket.SOCK_STREAM)
|
||||
af, socktype, proto, canonname, sa = res[0]
|
||||
# Try all the addresses in turn until we connect()
|
||||
last_error = 0
|
||||
for remote in res:
|
||||
af, socktype, proto, canonname, sa = remote
|
||||
self.sock = socket.socket(af, socktype, proto)
|
||||
self.sock.connect(sa)
|
||||
last_error = self.sock.connect_ex(sa)
|
||||
print af
|
||||
if last_error == 0:
|
||||
break
|
||||
else:
|
||||
self.sock.close()
|
||||
if last_error != 0:
|
||||
# FIXME
|
||||
raise socket.error(last_error)
|
||||
if sys.version_info[0] <= 2 and sys.version_info[1] <= 2:
|
||||
self.sslobj = socket.ssl(self.sock, self.keyfile, self.certfile)
|
||||
else:
|
||||
|
Loading…
Reference in New Issue
Block a user