From 0d5496ba0a21aa6df5d10391af01d5017fb973bf Mon Sep 17 00:00:00 2001 From: Olivier Mehani Date: Mon, 10 Jun 2019 21:47:37 +1000 Subject: [PATCH] implement Happy Eyeballs This allows OfflineIMAP to not stall on malfunctional IPv6 connections, and fall-back to a functional IPv4 connection, if faster, as described in RFC6555. Signed-off-by: Olivier Mehani Signed-off-by: Nicolas Sebrecht --- offlineimap/imaplibutil.py | 10 +++++++++- requirements.txt | 1 + 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/offlineimap/imaplibutil.py b/offlineimap/imaplibutil.py index c88d04b..44338f6 100644 --- a/offlineimap/imaplibutil.py +++ b/offlineimap/imaplibutil.py @@ -19,6 +19,7 @@ import fcntl import time import subprocess import threading +import rfc6555 import socket import errno import zlib @@ -78,8 +79,15 @@ class UsefulIMAPMixIn(object): def open_socket(self): """open_socket() Open socket choosing first address family available.""" + if self.af == socket.AF_UNSPEC: + # happy-eyeballs! + return rfc6555.create_connection((self.host, self.port)) + else: + return self._open_socket_for_af(self.af) + + def _open_socket_for_af(self, af): msg = (-1, 'could not open socket') - for res in socket.getaddrinfo(self.host, self.port, self.af, socket.SOCK_STREAM): + for res in socket.getaddrinfo(self.host, self.port, af, socket.SOCK_STREAM): af, socktype, proto, canonname, sa = res try: # use socket of our own, possiblly socksified socket. diff --git a/requirements.txt b/requirements.txt index 3b1819e..1e2a2ae 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,3 +2,4 @@ six gssapi[kerberos] portalocker[cygwin] +rfc6555