]> granicus.if.org Git - python/commitdiff
Issue #4473: Add a POP3.capa() method to query the capabilities advertised by the...
authorAntoine Pitrou <solipsis@pitrou.net>
Fri, 23 Nov 2012 19:07:39 +0000 (20:07 +0100)
committerAntoine Pitrou <solipsis@pitrou.net>
Fri, 23 Nov 2012 19:07:39 +0000 (20:07 +0100)
Patch by Lorenzo Catucci.

Doc/library/poplib.rst
Lib/poplib.py
Lib/test/test_poplib.py
Misc/NEWS

index 01f680e0a7a0f693f4276a7097a9449878a73169..2eb3b72d2ef61d168ca8971b9672257875d206ff 100644 (file)
@@ -97,6 +97,14 @@ An :class:`POP3` instance has the following methods:
    Returns the greeting string sent by the POP3 server.
 
 
+.. method:: POP3.capa()
+
+   Query the server's capabilities as specified in :rfc:`2449`.
+   Returns a dictionary in the form ``{'name': ['param'...]}``.
+
+   .. versionadded:: 3.4
+
+
 .. method:: POP3.user(username)
 
    Send user command, response should indicate that a password is required.
index 094aaa11b3fe4b463f62abf2fa007612ec965100..ccb28e58d0ae18457a87e59e46a572d2c563823c 100644 (file)
@@ -55,6 +55,7 @@ class POP3:
             APOP name digest        apop(name, digest)
             TOP msg n               top(msg, n)
             UIDL [msg]              uidl(msg = None)
+            CAPA                    capa()
 
     Raises one exception: 'error_proto'.
 
@@ -322,6 +323,35 @@ class POP3:
             return self._shortcmd('UIDL %s' % which)
         return self._longcmd('UIDL')
 
+
+    def capa(self):
+        """Return server capabilities (RFC 2449) as a dictionary
+        >>> c=poplib.POP3('localhost')
+        >>> c.capa()
+        {'IMPLEMENTATION': ['Cyrus', 'POP3', 'server', 'v2.2.12'],
+         'TOP': [], 'LOGIN-DELAY': ['0'], 'AUTH-RESP-CODE': [],
+         'EXPIRE': ['NEVER'], 'USER': [], 'STLS': [], 'PIPELINING': [],
+         'UIDL': [], 'RESP-CODES': []}
+        >>>
+
+        Really, according to RFC 2449, the cyrus folks should avoid
+        having the implementation splitted into multiple arguments...
+        """
+        def _parsecap(line):
+            lst = line.decode('ascii').split()
+            return lst[0], lst[1:]
+
+        caps = {}
+        try:
+            resp = self._longcmd('CAPA')
+            rawcaps = resp[1]
+            for capline in rawcaps:
+                capnm, capargs = _parsecap(capline)
+                caps[capnm] = capargs
+        except error_proto as _err:
+            raise error_proto('-ERR CAPA not supported by server')
+        return caps
+
 try:
     import ssl
 except ImportError:
index c0929a06b3a83d583279f05d1e3b39f0a79e1036..8fe0c4cb0999406b235adba2ead5f4a6c0449ad7 100644 (file)
@@ -33,6 +33,8 @@ line3\r\n\
 
 class DummyPOP3Handler(asynchat.async_chat):
 
+    CAPAS = {'UIDL': [], 'IMPLEMENTATION': ['python-testlib-pop-server']}
+
     def __init__(self, conn):
         asynchat.async_chat.__init__(self, conn)
         self.set_terminator(b"\r\n")
@@ -112,6 +114,16 @@ class DummyPOP3Handler(asynchat.async_chat):
         self.push('+OK closing.')
         self.close_when_done()
 
+    def cmd_capa(self, arg):
+        self.push('+OK Capability list follows')
+        if self.CAPAS:
+            for cap, params in self.CAPAS.items():
+                _ln = [cap]
+                if params:
+                    _ln.extend(params)
+                self.push(' '.join(_ln))
+        self.push('.')
+
 
 class DummyPOP3Server(asyncore.dispatcher, threading.Thread):
 
@@ -232,6 +244,10 @@ class TestPOP3Class(TestCase):
         self.client.uidl()
         self.client.uidl('foo')
 
+    def test_capa(self):
+        capa = self.client.capa()
+        self.assertTrue('IMPLEMENTATION' in capa.keys())
+
     def test_quit(self):
         resp = self.client.quit()
         self.assertTrue(resp)
index 917f4d549670e7bc60bd1dd89592734589052101..7ddb33b33ce5d01ddaaece09e7322353f44ea77d 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -138,6 +138,9 @@ Core and Builtins
 Library
 -------
 
+- Issue #4473: Add a POP3.capa() method to query the capabilities advertised
+  by the POP3 server.  Patch by Lorenzo Catucci.
+
 - Issue #4473: Ensure the socket is shutdown cleanly in POP3.close().
   Patch by Lorenzo Catucci.