Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 25cee19

Browse files
committed
Issue #4473: Add a POP3.capa() method to query the capabilities advertised by the POP3 server.
Patch by Lorenzo Catucci.
1 parent d89824b commit 25cee19

4 files changed

Lines changed: 57 additions & 0 deletions

File tree

Doc/library/poplib.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,14 @@ An :class:`POP3` instance has the following methods:
9797
Returns the greeting string sent by the POP3 server.
9898

9999

100+
.. method:: POP3.capa()
101+
102+
Query the server's capabilities as specified in :rfc:`2449`.
103+
Returns a dictionary in the form ``{'name': ['param'...]}``.
104+
105+
.. versionadded:: 3.4
106+
107+
100108
.. method:: POP3.user(username)
101109

102110
Send user command, response should indicate that a password is required.

Lib/poplib.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ class POP3:
5555
APOP name digest apop(name, digest)
5656
TOP msg n top(msg, n)
5757
UIDL [msg] uidl(msg = None)
58+
CAPA capa()
5859
5960
Raises one exception: 'error_proto'.
6061
@@ -322,6 +323,35 @@ def uidl(self, which=None):
322323
return self._shortcmd('UIDL %s' % which)
323324
return self._longcmd('UIDL')
324325

326+
327+
def capa(self):
328+
"""Return server capabilities (RFC 2449) as a dictionary
329+
>>> c=poplib.POP3('localhost')
330+
>>> c.capa()
331+
{'IMPLEMENTATION': ['Cyrus', 'POP3', 'server', 'v2.2.12'],
332+
'TOP': [], 'LOGIN-DELAY': ['0'], 'AUTH-RESP-CODE': [],
333+
'EXPIRE': ['NEVER'], 'USER': [], 'STLS': [], 'PIPELINING': [],
334+
'UIDL': [], 'RESP-CODES': []}
335+
>>>
336+
337+
Really, according to RFC 2449, the cyrus folks should avoid
338+
having the implementation splitted into multiple arguments...
339+
"""
340+
def _parsecap(line):
341+
lst = line.decode('ascii').split()
342+
return lst[0], lst[1:]
343+
344+
caps = {}
345+
try:
346+
resp = self._longcmd('CAPA')
347+
rawcaps = resp[1]
348+
for capline in rawcaps:
349+
capnm, capargs = _parsecap(capline)
350+
caps[capnm] = capargs
351+
except error_proto as _err:
352+
raise error_proto('-ERR CAPA not supported by server')
353+
return caps
354+
325355
try:
326356
import ssl
327357
except ImportError:

Lib/test/test_poplib.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@
3333

3434
class DummyPOP3Handler(asynchat.async_chat):
3535

36+
CAPAS = {'UIDL': [], 'IMPLEMENTATION': ['python-testlib-pop-server']}
37+
3638
def __init__(self, conn):
3739
asynchat.async_chat.__init__(self, conn)
3840
self.set_terminator(b"\r\n")
@@ -112,6 +114,16 @@ def cmd_quit(self, arg):
112114
self.push('+OK closing.')
113115
self.close_when_done()
114116

117+
def cmd_capa(self, arg):
118+
self.push('+OK Capability list follows')
119+
if self.CAPAS:
120+
for cap, params in self.CAPAS.items():
121+
_ln = [cap]
122+
if params:
123+
_ln.extend(params)
124+
self.push(' '.join(_ln))
125+
self.push('.')
126+
115127

116128
class DummyPOP3Server(asyncore.dispatcher, threading.Thread):
117129

@@ -232,6 +244,10 @@ def test_uidl(self):
232244
self.client.uidl()
233245
self.client.uidl('foo')
234246

247+
def test_capa(self):
248+
capa = self.client.capa()
249+
self.assertTrue('IMPLEMENTATION' in capa.keys())
250+
235251
def test_quit(self):
236252
resp = self.client.quit()
237253
self.assertTrue(resp)

Misc/NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,9 @@ Core and Builtins
138138
Library
139139
-------
140140

141+
- Issue #4473: Add a POP3.capa() method to query the capabilities advertised
142+
by the POP3 server. Patch by Lorenzo Catucci.
143+
141144
- Issue #4473: Ensure the socket is shutdown cleanly in POP3.close().
142145
Patch by Lorenzo Catucci.
143146

0 commit comments

Comments
 (0)