diff options
| -rw-r--r-- | Doc/library/poplib.rst | 10 | ||||
| -rw-r--r-- | Doc/whatsnew/3.2.rst | 7 | ||||
| -rw-r--r-- | Lib/poplib.py | 18 | ||||
| -rw-r--r-- | Lib/test/test_poplib.py | 21 | ||||
| -rw-r--r-- | Misc/NEWS | 5 | 
5 files changed, 53 insertions, 8 deletions
diff --git a/Doc/library/poplib.rst b/Doc/library/poplib.rst index b397b4b26c..b60ad0ea4b 100644 --- a/Doc/library/poplib.rst +++ b/Doc/library/poplib.rst @@ -32,13 +32,19 @@ A single class is provided by the :mod:`poplib` module:     be used). -.. class:: POP3_SSL(host, port=POP3_SSL_PORT, keyfile=None, certfile=None[, timeout]) +.. class:: POP3_SSL(host, port=POP3_SSL_PORT, keyfile=None, certfile=None, timeout=None, context=None)     This is a subclass of :class:`POP3` that connects to the server over an SSL     encrypted socket.  If *port* is not specified, 995, the standard POP3-over-SSL     port is used.  *keyfile* and *certfile* are also optional - they can contain a     PEM formatted private key and certificate chain file for the SSL connection. -   *timeout* works as in the :class:`POP3` constructor. +   *timeout* works as in the :class:`POP3` constructor. *context* parameter is a +   :class:`ssl.SSLContext` object which allows bundling SSL configuration +   options, certificates and private keys into a single (potentially long-lived) +   structure. + +   .. versionchanged:: 3.2 +      *context* parameter added.  One exception is defined as an attribute of the :mod:`poplib` module: diff --git a/Doc/whatsnew/3.2.rst b/Doc/whatsnew/3.2.rst index d03a67fd6a..a2b7af4d93 100644 --- a/Doc/whatsnew/3.2.rst +++ b/Doc/whatsnew/3.2.rst @@ -186,6 +186,13 @@ New, Improved, and Deprecated Modules    (Contributed by Giampaolo RodolĂ ; :issue:`8866`.) +* :class:`~poplib.POP3_SSL` class now accepts a *context* parameter, which is a +  :class:`ssl.SSLContext` object allowing bundling SSL configuration options, +  certificates and private keys into a single (potentially long-lived) +  structure. + +  (Contributed by Giampaolo RodolĂ ; :issue:`8807`.) +  Multi-threading  =============== diff --git a/Lib/poplib.py b/Lib/poplib.py index 1a529d0a13..84ea88de46 100644 --- a/Lib/poplib.py +++ b/Lib/poplib.py @@ -331,16 +331,26 @@ else:          See the methods of the parent class POP3 for more documentation.          """ -        def __init__(self, host, port=POP3_SSL_PORT, -        keyfile=None, certfile=None, -        timeout=socket._GLOBAL_DEFAULT_TIMEOUT): +        def __init__(self, host, port=POP3_SSL_PORT, keyfile=None, certfile=None, +                     timeout=socket._GLOBAL_DEFAULT_TIMEOUT, context=None): +            if context is not None and keyfile is not None: +                raise ValueError("context and keyfile arguments are mutually " +                                 "exclusive") +            if context is not None and certfile is not None: +                raise ValueError("context and certfile arguments are mutually " +                                 "exclusive")              self.keyfile = keyfile              self.certfile = certfile +            self.context = context              POP3.__init__(self, host, port, timeout)          def _create_socket(self, timeout):              sock = POP3._create_socket(self, timeout) -            return ssl.wrap_socket(sock, self.keyfile, self.certfile) +            if self.context is not None: +                sock = self.context.wrap_socket(sock) +            else: +                sock = ssl.wrap_socket(sock, self.keyfile, self.certfile) +            return sock      __all__.append("POP3_SSL") diff --git a/Lib/test/test_poplib.py b/Lib/test/test_poplib.py index c831fb467a..2adc849282 100644 --- a/Lib/test/test_poplib.py +++ b/Lib/test/test_poplib.py @@ -122,6 +122,7 @@ class DummyPOP3Server(asyncore.dispatcher, threading.Thread):          self.active = False          self.active_lock = threading.Lock()          self.host, self.port = self.socket.getsockname()[:2] +        self.handler_instance = None      def start(self):          assert not self.active @@ -145,8 +146,7 @@ class DummyPOP3Server(asyncore.dispatcher, threading.Thread):      def handle_accept(self):          conn, addr = self.accept() -        self.handler = self.handler(conn) -        self.close() +        self.handler_instance = self.handler(conn)      def handle_connect(self):          self.close() @@ -287,6 +287,23 @@ if hasattr(poplib, 'POP3_SSL'):          def test__all__(self):              self.assertIn('POP3_SSL', poplib.__all__) +        def test_context(self): +            ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1) +            self.assertRaises(ValueError, poplib.POP3_SSL, self.server.host, +                              self.server.port, keyfile=CERTFILE, context=ctx) +            self.assertRaises(ValueError, poplib.POP3_SSL, self.server.host, +                              self.server.port, certfile=CERTFILE, context=ctx) +            self.assertRaises(ValueError, poplib.POP3_SSL, self.server.host, +                              self.server.port, keyfile=CERTFILE, +                              certfile=CERTFILE, context=ctx) + +            self.client.quit() +            self.client = poplib.POP3_SSL(self.server.host, self.server.port, +                                          context=ctx) +            self.assertIsInstance(self.client.sock, ssl.SSLSocket) +            self.assertIs(self.client.sock.context, ctx) +            self.assertTrue(self.client.noop().startswith(b'+OK')) +  class TestTimeouts(TestCase): @@ -93,6 +93,11 @@ Extensions  Library  ------- +- Issue #8807: poplib.POP3_SSL class now accepts a context parameter, which is a +  ssl.SSLContext object allowing bundling SSL configuration options, +  certificates and private keys into a single (potentially long-lived) +  structure. +  - Issue #8866: parameters passed to socket.getaddrinfo can now be specified as    single keyword arguments.  | 
