imaplib: how to specify SSL/TLS protocol version?

G

Grant Edwards

Connecting to Exchange server fails like this:

File "/usr/lib64/python2.7/imaplib.py", line 1148, in __init__
IMAP4.__init__(self, host, port)
SSLError: [Errno 1] _ssl.c:1419: error:1408F10B:SSL routines:SSL3_GET_RECORD:wrong version number

Experiments show that when calling ssl.wrap_socket() I have to specify
ssl_version=PROTOCOL_TLSv1 to avoid the above error.

How do I tell imaplib to use TLS1 instead of SSL3?
 
G

Grant Edwards

Connecting to Exchange server fails like this:

File "/usr/lib64/python2.7/imaplib.py", line 1148, in __init__
IMAP4.__init__(self, host, port)
SSLError: [Errno 1] _ssl.c:1419: error:1408F10B:SSL routines:SSL3_GET_RECORD:wrong version number

Experiments show that when calling ssl.wrap_socket() I have to specify
ssl_version=PROTOCOL_TLSv1 to avoid the above error.

How do I tell imaplib to use TLS1 instead of SSL3?

I'm not too keen on this approach, but monkey-patching the open()
method seems to work:

def my_imap4_ssl_open(self, host = '', port = 993):
self.host = host
self.port = port
self.sock = socket.create_connection((host, port))
self.sslobj = ssl.wrap_socket(self.sock, self.keyfile, self.certfile, ssl_version=ssl.PROTOCOL_TLSv1)
self.file = self.sslobj.makefile('rb')

imaplib.IMAP4_SSL.open = my_imap4_ssl_open
 
T

Tim Chase

File "/usr/lib64/python2.7/imaplib.py", line 1148, in __init__
IMAP4.__init__(self, host, port)
SSLError: [Errno 1] _ssl.c:1419: error:1408F10B:SSL
routines:SSL3_GET_RECORD:wrong version number

Experiments show that when calling ssl.wrap_socket() I have to
specify ssl_version=PROTOCOL_TLSv1 to avoid the above error.

How do I tell imaplib to use TLS1 instead of SSL3?

Sounds like you'd need to make a subclass, something like

class IMAP4_TLS(imaplib.IMAP4_SSL):
def open(self, host="", port=IMAP4_SSL_PORT):
self.host = host
self.port = port
self.sock = socket.create_connection((host, port))
self.sslobj = ssl.wrap_socket(
self.sock,
self.keyfile,
self.certfile,
ssl_version=PROTOCOL_TLSv1,
)
self.file = self.sslobj.makefile('rb')

Alternatively, you could genericify it something like


class IMAP4_TLS(imaplib.IMAP4_SSL):
def open(self, host="",
port=IMAP4_SSL_PORT,
ssl_version=PROTOCOL_SSLv23,
):
self.host = host
self.port = port
self.sock = socket.create_connection((host, port))
self.sslobj = ssl.wrap_socket(
self.sock,
self.keyfile,
self.certfile,
ssl_version=ssl_version,
)
self.file = self.sslobj.makefile('rb')

and then call .open(..., ssl_version=PROTOCOL_TLSv1) or specify any
other protocol that you need.

-tkc
 
T

Tim Chase

I'm not too keen on this approach, but monkey-patching the open()
method seems to work:

def my_imap4_ssl_open(self, host = '', port = 993):
self.host = host
self.port = port
self.sock = socket.create_connection((host, port))
self.sslobj = ssl.wrap_socket(self.sock, self.keyfile,
self.certfile, ssl_version=ssl.PROTOCOL_TLSv1) self.file =
self.sslobj.makefile('rb')

imaplib.IMAP4_SSL.open = my_imap4_ssl_open

Our messages passed in the ether. You don't have to feel dirty
for monkey-patching, as you can just do it with inheritance.

-tkc
 
G

Grant Edwards

Yep saw that. Thanks for the answers.


Doh. I don't know why I didn't think of that...

Now I remember...

I left out a relevent fact: I'm not the one calling IMAP4_<whatever>.

That's being done by the imapclient library. There's no way to pass
imapclient a custom class to use. It's hard-waired to call either
imaplib.IMAP4_stream(), imaplib.IMAP4(), or imaplib.IMAP4_SSL(). I
could create an IMAP4_TLS1 class, but I would then have to sub-class
imapclient.IMAPClient and override its _create_IMAP4() method to make
it call my IMAP4_TLS1() class instead of calling imaplib.IMAP4_SSL().

Monkey-patching imaplib seems a little better since it it doesn't
depend on assumptions about the internal workings of imapclient (other
than the fact that it uses imaplib.IMAP4_SSL).
 
C

Chris Angelico

I left out a relevent fact: I'm not the one calling IMAP4_<whatever>.

That's being done by the imapclient library. There's no way to pass
imapclient a custom class to use. It's hard-waired to call either
imaplib.IMAP4_stream(), imaplib.IMAP4(), or imaplib.IMAP4_SSL(). I
could create an IMAP4_TLS1 class, but I would then have to sub-class
imapclient.IMAPClient and override its _create_IMAP4() method to make
it call my IMAP4_TLS1() class instead of calling imaplib.IMAP4_SSL().

Monkey-patching imaplib seems a little better since it it doesn't
depend on assumptions about the internal workings of imapclient (other
than the fact that it uses imaplib.IMAP4_SSL).

That's an argument in favour of a minor case of serious
monkey-patching. Although if you do feel dirty, try to hold on to that
feeling because that is the proper reaction to being told that you're
monkey-patching.

ChrisA
okay, now I feel like a moron... not just a regular moron, though...
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,057
Messages
2,570,443
Members
47,113
Latest member
XZJMike318

Latest Threads

Top