add proxy support powered by PySocks

Read proxy option in imapserver, instantiate a class in imaplibutil
using a self-defined keyword and a socket instance, and use this socket
instance to substitute the default socket instance used in imaplib2.

Signed-off-by: 夏恺(Xia Kai) <xiaket@gmail.com>
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
This commit is contained in:
夏恺(Xia Kai)
2015-02-15 22:16:20 +08:00
committed by Nicolas Sebrecht
parent a1383da9b3
commit d36209a305
3 changed files with 104 additions and 18 deletions

View File

@ -15,10 +15,7 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
from offlineimap import imaplibutil, imaputil, threadutil, OfflineImapError
from offlineimap.ui import getglobalui
from threading import Lock, BoundedSemaphore, Thread, Event, currentThread
import offlineimap.accounts
import hmac
import socket
import base64
@ -28,6 +25,11 @@ from sys import exc_info
from socket import gaierror
from ssl import SSLError, cert_time_to_seconds
from offlineimap import imaplibutil, imaputil, threadutil, OfflineImapError
import offlineimap.accounts
from offlineimap.ui import getglobalui
try:
# do we have a recent pykerberos?
have_gss = False
@ -101,6 +103,31 @@ class IMAPServer:
self.gss_vc = None
self.gssapi = False
# In order to support proxy connection, we have to override the
# default socket instance with our own socksified socket instance.
# We add this option to bypass the GFW in China.
_account_section = 'Account ' + self.repos.account.name
if not self.config.has_option(_account_section, 'proxy'):
self.proxied_socket = socket.socket
else:
proxy = self.config.get(_account_section, 'proxy')
# Powered by PySocks.
try:
import socks
proxy_type, host, port = proxy.split(":")
port = int(port)
socks.setdefaultproxy(getattr(socks, proxy_type), host, port)
self.proxied_socket = socks.socksocket
except ImportError:
self.ui.warn("PySocks not installed, ignoring proxy option.")
self.proxied_socket = socket.socket
except (AttributeError, ValueError) as e:
self.ui.warn("Bad proxy option %s for account %s: %s "
"Ignoring proxy option."%
(proxy, self.repos.account.name, e))
self.proxied_socket = socket.socket
def __getpassword(self):
"""Returns the server password or None"""
if self.goodpassword != None: # use cached good one first
@ -391,25 +418,33 @@ class IMAPServer:
# Generate a new connection.
if self.tunnel:
self.ui.connecting('tunnel', self.tunnel)
imapobj = imaplibutil.IMAP4_Tunnel(self.tunnel,
timeout=socket.getdefaulttimeout())
imapobj = imaplibutil.IMAP4_Tunnel(
self.tunnel,
timeout=socket.getdefaulttimeout(),
use_socket=self.proxied_socket,
)
success = 1
elif self.usessl:
self.ui.connecting(self.hostname, self.port)
imapobj = imaplibutil.WrappedIMAP4_SSL(self.hostname,
self.port,
self.sslclientkey,
self.sslclientcert,
self.sslcacertfile,
self.__verifycert,
self.sslversion,
timeout=socket.getdefaulttimeout(),
fingerprint=self.fingerprint
)
imapobj = imaplibutil.WrappedIMAP4_SSL(
self.hostname,
self.port,
self.sslclientkey,
self.sslclientcert,
self.sslcacertfile,
self.__verifycert,
self.sslversion,
timeout=socket.getdefaulttimeout(),
fingerprint=self.fingerprint,
use_socket=self.proxied_socket,
)
else:
self.ui.connecting(self.hostname, self.port)
imapobj = imaplibutil.WrappedIMAP4(self.hostname, self.port,
timeout=socket.getdefaulttimeout())
imapobj = imaplibutil.WrappedIMAP4(
self.hostname, self.port,
timeout=socket.getdefaulttimeout(),
use_socket=self.proxied_socket,
)
if not self.preauth_tunnel:
try: