STARTTLS and certificates Re:[ANNOUNCE] OfflineIMAP v6.3.4-rc3 released

Johannes Stezenbach js at
Sun Jul 10 11:31:23 BST 2011

On Fri, Jul 08, 2011 at 05:22:09PM +0200, Nicolas Sebrecht wrote:
> On Thu, Jul 07, 2011 at 10:15:47PM +0200, Johannes Stezenbach wrote:
> > 
> > However, I'm too lame to send a patch myself..
> I not sure what you mean by "I'm too lame" but it's sad to hear you
> won't write a patch. It looks like you have good knowledge in this area
> (more than I have, at least).
> Could you try to send a patch, please?

Sorry for slow reply, but it illustrates the problem: time.

> Or, "a middle hack not yet finished but giving the keys to let other
> finish the work"?
> Or at least, a beginning of something like comments highlighting the
> lines of code to improve?
> Or is there nothing you can do to help us a bit more, actually?

Well, cert verification is already implemented in,
and both and eventually call
ssl.wrap_socket().  At the minimum imaplib2's starttls()
method should pass the ca_certs and cert_reqs arguments,
and a callback function for cert verification.
But maybe the imapliib2 maintainer should absorb all the
code from WrappedIMAP4_SSL into imaplib?  It seems
every imaplib2 user would need this, not just offlineimap.

diff --git a/offlineimap/ b/offlineimap/
index ec6cd0d..e98c216 100644
--- a/offlineimap/
+++ b/offlineimap/
@@ -999,7 +999,8 @@ class IMAP4(object):
         return self._simple_command(name, sort_criteria, charset, *search_criteria, **kw)
-    def starttls(self, keyfile=None, certfile=None, **kw):
+    def starttls(self, keyfile=None, certfile=None,
+                 ca_certs=None, cert_reqs=None, cert_verify_cb=None, **kw):
         """(typ, [data]) = starttls(keyfile=None, certfile=None)
         Start TLS negotiation as per RFC 2595."""
@@ -1034,10 +1035,15 @@ class IMAP4(object):
                 import ssl
-                self.sock = ssl.wrap_socket(self.sock, keyfile, certfile)
+                self.sock = ssl.wrap_socket(self.sock, keyfile, certfile,
+                                           ca_certs=ca_certs, cert_reqs=cert_reqs)
             except ImportError:
                 self.sock = socket.ssl(self.sock, keyfile, certfile)
+            if cert_verify_cb is not None:
+                error = cert_verify_cb(self.sock,
+                if error:
+                    raise ssl.SSLError("SSL Certificate host name mismatch: %s" % error)
             self.read_fd = self.sock.fileno()
             # Restart reader thread


More information about the OfflineIMAP-project mailing list