diff options
author | Antoine Pitrou <solipsis@pitrou.net> | 2010-11-12 18:49:16 (GMT) |
---|---|---|
committer | Antoine Pitrou <solipsis@pitrou.net> | 2010-11-12 18:49:16 (GMT) |
commit | f3b001f966d8e16662241e2ed7c7f345cd7051db (patch) | |
tree | d1f3d82d1a743763eda10f2b820783d966c1de21 /Lib/imaplib.py | |
parent | e0bf419ae7586b8e40b16eaec63122e71023e4fa (diff) | |
download | cpython-f3b001f966d8e16662241e2ed7c7f345cd7051db.zip cpython-f3b001f966d8e16662241e2ed7c7f345cd7051db.tar.gz cpython-f3b001f966d8e16662241e2ed7c7f345cd7051db.tar.bz2 |
Issue #4471: Add the IMAP.starttls() method to enable encryption on
standard IMAP4 connections. Original patch by Lorenzo M. Catucci.
Diffstat (limited to 'Lib/imaplib.py')
-rw-r--r-- | Lib/imaplib.py | 41 |
1 files changed, 36 insertions, 5 deletions
diff --git a/Lib/imaplib.py b/Lib/imaplib.py index 77806db..421cb97 100644 --- a/Lib/imaplib.py +++ b/Lib/imaplib.py @@ -24,6 +24,12 @@ __version__ = "2.58" import binascii, errno, random, re, socket, subprocess, sys, time +try: + import ssl + HAVE_SSL = True +except ImportError: + HAVE_SSL = False + __all__ = ["IMAP4", "IMAP4_stream", "Internaldate2tuple", "Int2AP", "ParseFlags", "Time2Internaldate"] @@ -71,6 +77,7 @@ Commands = { 'SETANNOTATION':('AUTH', 'SELECTED'), 'SETQUOTA': ('AUTH', 'SELECTED'), 'SORT': ('SELECTED',), + 'STARTTLS': ('NONAUTH',), 'STATUS': ('AUTH', 'SELECTED'), 'STORE': ('SELECTED',), 'SUBSCRIBE': ('AUTH', 'SELECTED'), @@ -156,6 +163,7 @@ class IMAP4: self.continuation_response = '' # Last continuation response self.is_readonly = False # READ-ONLY desired state self.tagnum = 0 + self._tls_established = False # Open socket to server. @@ -711,6 +719,33 @@ class IMAP4: return self._untagged_response(typ, dat, name) + def starttls(self, ssl_context=None): + name = 'STARTTLS' + if not HAVE_SSL: + raise self.error('SSL support missing') + if self._tls_established: + raise self.abort('TLS session already established') + if name not in self.capabilities: + raise self.abort('TLS not supported by server') + # Generate a default SSL context if none was passed. + if ssl_context is None: + ssl_context = ssl.SSLContext(ssl.PROTOCOL_SSLv23) + # SSLv2 considered harmful. + ssl_context.options |= ssl.OP_NO_SSLv2 + typ, dat = self._simple_command(name) + if typ == 'OK': + self.sock = ssl_context.wrap_socket(self.sock) + self.file = self.sock.makefile('rb') + self._tls_established = True + typ, dat = self.capability() + if dat == [None]: + raise self.error('no CAPABILITY response from server') + self.capabilities = tuple(dat[-1].upper().split()) + else: + raise self.error("Couldn't establish TLS session") + return self._untagged_response(typ, dat, name) + + def status(self, mailbox, names): """Request named status conditions for mailbox. @@ -1125,12 +1160,8 @@ class IMAP4: n -= 1 +if HAVE_SSL: -try: - import ssl -except ImportError: - pass -else: class IMAP4_SSL(IMAP4): """IMAP4 client class over SSL connection |