blob: e3bd2ab1ebc8bd2b08da1631993d344d3e8b5cc1 [file] [log] [blame]
Guido van Rossum03774bb1998-04-09 13:50:55 +00001"""A POP3 client class.
Guido van Rossum484772d1998-04-06 18:27:27 +00002
Guido van Rossum03774bb1998-04-09 13:50:55 +00003Based on the J. Myers POP3 draft, Jan. 96
Guido van Rossum484772d1998-04-06 18:27:27 +00004"""
5
Guido van Rossum98d9fd32000-02-28 15:12:25 +00006# Author: David Ascher <david_ascher@brown.edu>
7# [heavily stealing from nntplib.py]
8# Updated: Piers Lauder <piers@cs.su.oz.au> [Jul '97]
Eric S. Raymond341f9292001-02-09 06:56:56 +00009# String method conversion and test jig improvements by ESR, February 2001.
Martin v. Löwis48440b72003-10-31 12:52:35 +000010# Added the POP3_SSL class. Methods loosely based on IMAP_SSL. Hector Urtubia <urtubia@mrbook.org> Aug 2003
Guido van Rossum98d9fd32000-02-28 15:12:25 +000011
Guido van Rossum484772d1998-04-06 18:27:27 +000012# Example (see the test function at the end of this file)
13
Guido van Rossum484772d1998-04-06 18:27:27 +000014# Imports
15
Antoine Pitrou7fde5b32012-11-24 18:14:12 +010016import errno
17import re
18import socket
Steve Dower60419a72019-06-24 08:42:54 -070019import sys
Guido van Rossum484772d1998-04-06 18:27:27 +000020
Antoine Pitrou8618d742012-11-23 20:13:48 +010021try:
22 import ssl
23 HAVE_SSL = True
Brett Cannoncd171c82013-07-04 17:43:24 -040024except ImportError:
Antoine Pitrou8618d742012-11-23 20:13:48 +010025 HAVE_SSL = False
26
Thomas Wouters47b49bf2007-08-30 22:15:33 +000027__all__ = ["POP3","error_proto"]
Skip Montanaroc62c81e2001-02-12 02:00:42 +000028
Guido van Rossum484772d1998-04-06 18:27:27 +000029# Exception raised when an error or invalid response is received:
Guido van Rossum03774bb1998-04-09 13:50:55 +000030
31class error_proto(Exception): pass
Guido van Rossum484772d1998-04-06 18:27:27 +000032
33# Standard Port
34POP3_PORT = 110
35
Martin v. Löwis48440b72003-10-31 12:52:35 +000036# POP SSL PORT
37POP3_SSL_PORT = 995
38
Guido van Rossum03774bb1998-04-09 13:50:55 +000039# Line terminators (we always output CRLF, but accept any of CRLF, LFCR, LF)
Jeremy Hylton88d06a72007-08-29 19:08:30 +000040CR = b'\r'
41LF = b'\n'
Guido van Rossum03774bb1998-04-09 13:50:55 +000042CRLF = CR+LF
Guido van Rossum484772d1998-04-06 18:27:27 +000043
Georg Brandl7e27abb2013-10-27 07:23:53 +010044# maximal line length when calling readline(). This is to prevent
Berker Peksagf23530f2014-10-19 18:04:38 +030045# reading arbitrary length lines. RFC 1939 limits POP3 line length to
Georg Brandl7e27abb2013-10-27 07:23:53 +010046# 512 characters, including CRLF. We have selected 2048 just to be on
47# the safe side.
48_MAXLINE = 2048
49
Guido van Rossum484772d1998-04-06 18:27:27 +000050
51class POP3:
Guido van Rossum03774bb1998-04-09 13:50:55 +000052
Tim Peters2344fae2001-01-15 00:50:52 +000053 """This class supports both the minimal and optional command sets.
54 Arguments can be strings or integers (where appropriate)
55 (e.g.: retr(1) and retr('1') both work equally well.
Guido van Rossum03774bb1998-04-09 13:50:55 +000056
Tim Peters2344fae2001-01-15 00:50:52 +000057 Minimal Command Set:
58 USER name user(name)
59 PASS string pass_(string)
60 STAT stat()
61 LIST [msg] list(msg = None)
62 RETR msg retr(msg)
63 DELE msg dele(msg)
64 NOOP noop()
65 RSET rset()
66 QUIT quit()
Guido van Rossum03774bb1998-04-09 13:50:55 +000067
Tim Peters2344fae2001-01-15 00:50:52 +000068 Optional Commands (some servers support these):
69 RPOP name rpop(name)
70 APOP name digest apop(name, digest)
71 TOP msg n top(msg, n)
72 UIDL [msg] uidl(msg = None)
Antoine Pitrou25cee192012-11-23 20:07:39 +010073 CAPA capa()
Antoine Pitrou8618d742012-11-23 20:13:48 +010074 STLS stls()
R David Murrayb8cd3e42015-05-16 15:05:53 -040075 UTF8 utf8()
Guido van Rossum03774bb1998-04-09 13:50:55 +000076
Tim Peters2344fae2001-01-15 00:50:52 +000077 Raises one exception: 'error_proto'.
Guido van Rossum03774bb1998-04-09 13:50:55 +000078
Tim Peters2344fae2001-01-15 00:50:52 +000079 Instantiate with:
80 POP3(hostname, port=110)
Guido van Rossum03774bb1998-04-09 13:50:55 +000081
Tim Peters2344fae2001-01-15 00:50:52 +000082 NB: the POP protocol locks the mailbox from user
83 authorization until QUIT, so be sure to get in, suck
84 the messages, and quit, each time you access the
85 mailbox.
Guido van Rossum03774bb1998-04-09 13:50:55 +000086
Tim Peters2344fae2001-01-15 00:50:52 +000087 POP is a line-based protocol, which means large mail
88 messages consume lots of python cycles reading them
89 line-by-line.
Guido van Rossum03774bb1998-04-09 13:50:55 +000090
Tim Peters2344fae2001-01-15 00:50:52 +000091 If it's available on your mail server, use IMAP4
92 instead, it doesn't suffer from the two problems
93 above.
94 """
Guido van Rossum03774bb1998-04-09 13:50:55 +000095
Christian Heimesd3956292008-11-05 19:48:27 +000096 encoding = 'UTF-8'
Guido van Rossum03774bb1998-04-09 13:50:55 +000097
Georg Brandlf78e02b2008-06-10 17:40:04 +000098 def __init__(self, host, port=POP3_PORT,
99 timeout=socket._GLOBAL_DEFAULT_TIMEOUT):
Martin v. Löwis4eb59402001-07-26 13:37:33 +0000100 self.host = host
101 self.port = port
Antoine Pitrou8618d742012-11-23 20:13:48 +0100102 self._tls_established = False
Steve Dower44f91c32019-06-27 10:47:59 -0700103 sys.audit("poplib.connect", self, host, port)
Christian Heimesd3956292008-11-05 19:48:27 +0000104 self.sock = self._create_socket(timeout)
Martin v. Löwis4eb59402001-07-26 13:37:33 +0000105 self.file = self.sock.makefile('rb')
106 self._debugging = 0
107 self.welcome = self._getresp()
Guido van Rossum484772d1998-04-06 18:27:27 +0000108
Christian Heimesd3956292008-11-05 19:48:27 +0000109 def _create_socket(self, timeout):
110 return socket.create_connection((self.host, self.port), timeout)
Guido van Rossum03774bb1998-04-09 13:50:55 +0000111
Tim Peters2344fae2001-01-15 00:50:52 +0000112 def _putline(self, line):
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000113 if self._debugging > 1: print('*put*', repr(line))
Steve Dower44f91c32019-06-27 10:47:59 -0700114 sys.audit("poplib.putline", self, line)
Christian Heimesd3956292008-11-05 19:48:27 +0000115 self.sock.sendall(line + CRLF)
Guido van Rossum03774bb1998-04-09 13:50:55 +0000116
Guido van Rossum484772d1998-04-06 18:27:27 +0000117
Tim Peters2344fae2001-01-15 00:50:52 +0000118 # Internal: send one command to the server (through _putline())
Guido van Rossum03774bb1998-04-09 13:50:55 +0000119
Tim Peters2344fae2001-01-15 00:50:52 +0000120 def _putcmd(self, line):
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000121 if self._debugging: print('*cmd*', repr(line))
Christian Heimesd3956292008-11-05 19:48:27 +0000122 line = bytes(line, self.encoding)
Tim Peters2344fae2001-01-15 00:50:52 +0000123 self._putline(line)
Guido van Rossum484772d1998-04-06 18:27:27 +0000124
Guido van Rossum03774bb1998-04-09 13:50:55 +0000125
Tim Peters2344fae2001-01-15 00:50:52 +0000126 # Internal: return one line from the server, stripping CRLF.
127 # This is where all the CPU time of this module is consumed.
128 # Raise error_proto('-ERR EOF') if the connection is closed.
Guido van Rossum03774bb1998-04-09 13:50:55 +0000129
Tim Peters2344fae2001-01-15 00:50:52 +0000130 def _getline(self):
Georg Brandl7e27abb2013-10-27 07:23:53 +0100131 line = self.file.readline(_MAXLINE + 1)
132 if len(line) > _MAXLINE:
133 raise error_proto('line too long')
134
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000135 if self._debugging > 1: print('*get*', repr(line))
Tim Peters2344fae2001-01-15 00:50:52 +0000136 if not line: raise error_proto('-ERR EOF')
137 octets = len(line)
138 # server can send any combination of CR & LF
139 # however, 'readline()' returns lines ending in LF
140 # so only possibilities are ...LF, ...CRLF, CR...LF
141 if line[-2:] == CRLF:
142 return line[:-2], octets
Serhiy Storchaka74a49ac2015-03-20 16:46:19 +0200143 if line[:1] == CR:
Tim Peters2344fae2001-01-15 00:50:52 +0000144 return line[1:-1], octets
145 return line[:-1], octets
Guido van Rossum03774bb1998-04-09 13:50:55 +0000146
Guido van Rossum484772d1998-04-06 18:27:27 +0000147
Tim Peters2344fae2001-01-15 00:50:52 +0000148 # Internal: get a response from the server.
149 # Raise 'error_proto' if the response doesn't start with '+'.
Guido van Rossum03774bb1998-04-09 13:50:55 +0000150
Tim Peters2344fae2001-01-15 00:50:52 +0000151 def _getresp(self):
152 resp, o = self._getline()
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000153 if self._debugging > 1: print('*resp*', repr(resp))
Christian Heimesd3956292008-11-05 19:48:27 +0000154 if not resp.startswith(b'+'):
Tim Peters2344fae2001-01-15 00:50:52 +0000155 raise error_proto(resp)
156 return resp
Guido van Rossum484772d1998-04-06 18:27:27 +0000157
Guido van Rossum03774bb1998-04-09 13:50:55 +0000158
Tim Peters2344fae2001-01-15 00:50:52 +0000159 # Internal: get a response plus following text from the server.
Guido van Rossum03774bb1998-04-09 13:50:55 +0000160
Tim Peters2344fae2001-01-15 00:50:52 +0000161 def _getlongresp(self):
162 resp = self._getresp()
163 list = []; octets = 0
164 line, o = self._getline()
Guido van Rossum0ec34772007-09-10 00:27:13 +0000165 while line != b'.':
Christian Heimesd3956292008-11-05 19:48:27 +0000166 if line.startswith(b'..'):
Tim Peters2344fae2001-01-15 00:50:52 +0000167 o = o-1
168 line = line[1:]
169 octets = octets + o
170 list.append(line)
171 line, o = self._getline()
172 return resp, list, octets
Guido van Rossum03774bb1998-04-09 13:50:55 +0000173
Guido van Rossum484772d1998-04-06 18:27:27 +0000174
Tim Peters2344fae2001-01-15 00:50:52 +0000175 # Internal: send a command and get the response
Guido van Rossum03774bb1998-04-09 13:50:55 +0000176
Tim Peters2344fae2001-01-15 00:50:52 +0000177 def _shortcmd(self, line):
178 self._putcmd(line)
179 return self._getresp()
Guido van Rossum484772d1998-04-06 18:27:27 +0000180
Guido van Rossum03774bb1998-04-09 13:50:55 +0000181
Tim Peters2344fae2001-01-15 00:50:52 +0000182 # Internal: send a command and get the response plus following text
Guido van Rossum03774bb1998-04-09 13:50:55 +0000183
Tim Peters2344fae2001-01-15 00:50:52 +0000184 def _longcmd(self, line):
185 self._putcmd(line)
186 return self._getlongresp()
Guido van Rossum484772d1998-04-06 18:27:27 +0000187
Guido van Rossum03774bb1998-04-09 13:50:55 +0000188
Tim Peters2344fae2001-01-15 00:50:52 +0000189 # These can be useful:
190
191 def getwelcome(self):
192 return self.welcome
193
194
195 def set_debuglevel(self, level):
196 self._debugging = level
197
198
199 # Here are all the POP commands:
200
201 def user(self, user):
202 """Send user name, return response
Guido van Rossum484772d1998-04-06 18:27:27 +0000203
Tim Peters2344fae2001-01-15 00:50:52 +0000204 (should indicate password required).
205 """
206 return self._shortcmd('USER %s' % user)
Guido van Rossum484772d1998-04-06 18:27:27 +0000207
Guido van Rossum03774bb1998-04-09 13:50:55 +0000208
Tim Peters2344fae2001-01-15 00:50:52 +0000209 def pass_(self, pswd):
210 """Send password, return response
Guido van Rossum484772d1998-04-06 18:27:27 +0000211
Tim Peters2344fae2001-01-15 00:50:52 +0000212 (response includes message count, mailbox size).
Guido van Rossum03774bb1998-04-09 13:50:55 +0000213
Tim Peters2344fae2001-01-15 00:50:52 +0000214 NB: mailbox is locked by server from here to 'quit()'
215 """
216 return self._shortcmd('PASS %s' % pswd)
Guido van Rossum484772d1998-04-06 18:27:27 +0000217
Guido van Rossum03774bb1998-04-09 13:50:55 +0000218
Tim Peters2344fae2001-01-15 00:50:52 +0000219 def stat(self):
220 """Get mailbox status.
Guido van Rossum484772d1998-04-06 18:27:27 +0000221
Tim Peters2344fae2001-01-15 00:50:52 +0000222 Result is tuple of 2 ints (message count, mailbox size)
223 """
224 retval = self._shortcmd('STAT')
Eric S. Raymond341f9292001-02-09 06:56:56 +0000225 rets = retval.split()
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000226 if self._debugging: print('*stat*', repr(rets))
Eric S. Raymond341f9292001-02-09 06:56:56 +0000227 numMessages = int(rets[1])
228 sizeMessages = int(rets[2])
Tim Peters2344fae2001-01-15 00:50:52 +0000229 return (numMessages, sizeMessages)
Guido van Rossum03774bb1998-04-09 13:50:55 +0000230
Guido van Rossum03774bb1998-04-09 13:50:55 +0000231
Tim Peters2344fae2001-01-15 00:50:52 +0000232 def list(self, which=None):
233 """Request listing, return result.
Guido van Rossum484772d1998-04-06 18:27:27 +0000234
Tim Peters2344fae2001-01-15 00:50:52 +0000235 Result without a message number argument is in form
Georg Brandl2772c672005-08-05 21:01:58 +0000236 ['response', ['mesg_num octets', ...], octets].
Guido van Rossum484772d1998-04-06 18:27:27 +0000237
Tim Peters2344fae2001-01-15 00:50:52 +0000238 Result when a message number argument is given is a
239 single response: the "scan listing" for that message.
240 """
Raymond Hettinger16e3c422002-06-01 16:07:16 +0000241 if which is not None:
Tim Peters2344fae2001-01-15 00:50:52 +0000242 return self._shortcmd('LIST %s' % which)
243 return self._longcmd('LIST')
Guido van Rossum03774bb1998-04-09 13:50:55 +0000244
Guido van Rossum03774bb1998-04-09 13:50:55 +0000245
Tim Peters2344fae2001-01-15 00:50:52 +0000246 def retr(self, which):
247 """Retrieve whole message number 'which'.
Guido van Rossumf6ae7431998-09-02 14:42:02 +0000248
Tim Peters2344fae2001-01-15 00:50:52 +0000249 Result is in form ['response', ['line', ...], octets].
250 """
251 return self._longcmd('RETR %s' % which)
Guido van Rossum03774bb1998-04-09 13:50:55 +0000252
Guido van Rossum484772d1998-04-06 18:27:27 +0000253
Tim Peters2344fae2001-01-15 00:50:52 +0000254 def dele(self, which):
255 """Delete message number 'which'.
Guido van Rossum03774bb1998-04-09 13:50:55 +0000256
Tim Peters2344fae2001-01-15 00:50:52 +0000257 Result is 'response'.
258 """
259 return self._shortcmd('DELE %s' % which)
Guido van Rossum03774bb1998-04-09 13:50:55 +0000260
Guido van Rossum484772d1998-04-06 18:27:27 +0000261
Tim Peters2344fae2001-01-15 00:50:52 +0000262 def noop(self):
263 """Does nothing.
Guido van Rossum03774bb1998-04-09 13:50:55 +0000264
Tim Peters2344fae2001-01-15 00:50:52 +0000265 One supposes the response indicates the server is alive.
266 """
267 return self._shortcmd('NOOP')
Guido van Rossum03774bb1998-04-09 13:50:55 +0000268
Guido van Rossum484772d1998-04-06 18:27:27 +0000269
Tim Peters2344fae2001-01-15 00:50:52 +0000270 def rset(self):
Benjamin Petersona37cfc62008-05-26 13:48:34 +0000271 """Unmark all messages marked for deletion."""
Tim Peters2344fae2001-01-15 00:50:52 +0000272 return self._shortcmd('RSET')
Guido van Rossum484772d1998-04-06 18:27:27 +0000273
Guido van Rossum03774bb1998-04-09 13:50:55 +0000274
Tim Peters2344fae2001-01-15 00:50:52 +0000275 def quit(self):
276 """Signoff: commit changes on server, unlock mailbox, close connection."""
Giampaolo Rodolà95bcb932011-02-25 22:28:24 +0000277 resp = self._shortcmd('QUIT')
278 self.close()
Tim Peters2344fae2001-01-15 00:50:52 +0000279 return resp
Guido van Rossum484772d1998-04-06 18:27:27 +0000280
Giampaolo Rodolà95bcb932011-02-25 22:28:24 +0000281 def close(self):
282 """Close the connection without assuming anything about it."""
Serhiy Storchaka7e7a3db2015-04-10 13:24:41 +0300283 try:
284 file = self.file
285 self.file = None
286 if file is not None:
287 file.close()
288 finally:
289 sock = self.sock
290 self.sock = None
291 if sock is not None:
292 try:
293 sock.shutdown(socket.SHUT_RDWR)
Victor Stinner83a2c282017-05-15 17:33:45 +0200294 except OSError as exc:
295 # The server might already have closed the connection.
296 # On Windows, this may result in WSAEINVAL (error 10022):
297 # An invalid operation was attempted.
298 if (exc.errno != errno.ENOTCONN
299 and getattr(exc, 'winerror', 0) != 10022):
Serhiy Storchaka7e7a3db2015-04-10 13:24:41 +0300300 raise
301 finally:
302 sock.close()
Giampaolo Rodolà95bcb932011-02-25 22:28:24 +0000303
Tim Peters2344fae2001-01-15 00:50:52 +0000304 #__del__ = quit
Guido van Rossum484772d1998-04-06 18:27:27 +0000305
Guido van Rossum484772d1998-04-06 18:27:27 +0000306
Tim Peters2344fae2001-01-15 00:50:52 +0000307 # optional commands:
Guido van Rossum03774bb1998-04-09 13:50:55 +0000308
Tim Peters2344fae2001-01-15 00:50:52 +0000309 def rpop(self, user):
310 """Not sure what this does."""
311 return self._shortcmd('RPOP %s' % user)
Guido van Rossum03774bb1998-04-09 13:50:55 +0000312
Guido van Rossum03774bb1998-04-09 13:50:55 +0000313
Jamie Davis0e6c8ee2018-03-04 00:33:32 -0500314 timestamp = re.compile(br'\+OK.[^<]*(<.*>)')
Guido van Rossum03774bb1998-04-09 13:50:55 +0000315
Christian Heimesd3956292008-11-05 19:48:27 +0000316 def apop(self, user, password):
Tim Peters2344fae2001-01-15 00:50:52 +0000317 """Authorisation
Guido van Rossum03774bb1998-04-09 13:50:55 +0000318
Tim Peters2344fae2001-01-15 00:50:52 +0000319 - only possible if server has supplied a timestamp in initial greeting.
Guido van Rossum03774bb1998-04-09 13:50:55 +0000320
Tim Peters2344fae2001-01-15 00:50:52 +0000321 Args:
Christian Heimesd3956292008-11-05 19:48:27 +0000322 user - mailbox user;
323 password - mailbox password.
Guido van Rossum03774bb1998-04-09 13:50:55 +0000324
Tim Peters2344fae2001-01-15 00:50:52 +0000325 NB: mailbox is locked by server from here to 'quit()'
326 """
Mark Dickinsonea1158f2009-08-06 16:06:25 +0000327 secret = bytes(password, self.encoding)
Moshe Zadkaccc2e3d2001-01-19 19:56:27 +0000328 m = self.timestamp.match(self.welcome)
329 if not m:
Tim Peters2344fae2001-01-15 00:50:52 +0000330 raise error_proto('-ERR APOP not supported by server')
Thomas Wouters477c8d52006-05-27 19:21:47 +0000331 import hashlib
Christian Heimesd3956292008-11-05 19:48:27 +0000332 digest = m.group(1)+secret
333 digest = hashlib.md5(digest).hexdigest()
Tim Peters2344fae2001-01-15 00:50:52 +0000334 return self._shortcmd('APOP %s %s' % (user, digest))
Guido van Rossum03774bb1998-04-09 13:50:55 +0000335
Guido van Rossum03774bb1998-04-09 13:50:55 +0000336
Tim Peters2344fae2001-01-15 00:50:52 +0000337 def top(self, which, howmuch):
338 """Retrieve message header of message number 'which'
339 and first 'howmuch' lines of message body.
Guido van Rossum03774bb1998-04-09 13:50:55 +0000340
Tim Peters2344fae2001-01-15 00:50:52 +0000341 Result is in form ['response', ['line', ...], octets].
342 """
343 return self._longcmd('TOP %s %s' % (which, howmuch))
Guido van Rossum03774bb1998-04-09 13:50:55 +0000344
Guido van Rossum03774bb1998-04-09 13:50:55 +0000345
Tim Peters2344fae2001-01-15 00:50:52 +0000346 def uidl(self, which=None):
347 """Return message digest (unique id) list.
Guido van Rossum03774bb1998-04-09 13:50:55 +0000348
Tim Peters2344fae2001-01-15 00:50:52 +0000349 If 'which', result contains unique id for that message
350 in the form 'response mesgnum uid', otherwise result is
351 the list ['response', ['mesgnum uid', ...], octets]
352 """
Raymond Hettinger16e3c422002-06-01 16:07:16 +0000353 if which is not None:
Tim Peters2344fae2001-01-15 00:50:52 +0000354 return self._shortcmd('UIDL %s' % which)
355 return self._longcmd('UIDL')
Guido van Rossum03774bb1998-04-09 13:50:55 +0000356
Antoine Pitrou25cee192012-11-23 20:07:39 +0100357
R David Murrayb8cd3e42015-05-16 15:05:53 -0400358 def utf8(self):
359 """Try to enter UTF-8 mode (see RFC 6856). Returns server response.
360 """
361 return self._shortcmd('UTF8')
362
363
Antoine Pitrou25cee192012-11-23 20:07:39 +0100364 def capa(self):
365 """Return server capabilities (RFC 2449) as a dictionary
366 >>> c=poplib.POP3('localhost')
367 >>> c.capa()
368 {'IMPLEMENTATION': ['Cyrus', 'POP3', 'server', 'v2.2.12'],
369 'TOP': [], 'LOGIN-DELAY': ['0'], 'AUTH-RESP-CODE': [],
370 'EXPIRE': ['NEVER'], 'USER': [], 'STLS': [], 'PIPELINING': [],
371 'UIDL': [], 'RESP-CODES': []}
372 >>>
373
374 Really, according to RFC 2449, the cyrus folks should avoid
Ezio Melotti9a3777e2013-08-17 15:53:55 +0300375 having the implementation split into multiple arguments...
Antoine Pitrou25cee192012-11-23 20:07:39 +0100376 """
377 def _parsecap(line):
378 lst = line.decode('ascii').split()
379 return lst[0], lst[1:]
380
381 caps = {}
382 try:
383 resp = self._longcmd('CAPA')
384 rawcaps = resp[1]
385 for capline in rawcaps:
386 capnm, capargs = _parsecap(capline)
387 caps[capnm] = capargs
388 except error_proto as _err:
389 raise error_proto('-ERR CAPA not supported by server')
390 return caps
391
Antoine Pitrou8618d742012-11-23 20:13:48 +0100392
393 def stls(self, context=None):
394 """Start a TLS session on the active connection as specified in RFC 2595.
395
396 context - a ssl.SSLContext
397 """
398 if not HAVE_SSL:
399 raise error_proto('-ERR TLS support missing')
400 if self._tls_established:
401 raise error_proto('-ERR TLS session already established')
402 caps = self.capa()
403 if not 'STLS' in caps:
404 raise error_proto('-ERR STLS not supported by server')
405 if context is None:
Christian Heimes67986f92013-11-23 22:43:47 +0100406 context = ssl._create_stdlib_context()
Antoine Pitrou8618d742012-11-23 20:13:48 +0100407 resp = self._shortcmd('STLS')
Christian Heimes1bc70682013-12-02 20:10:50 +0100408 self.sock = context.wrap_socket(self.sock,
Benjamin Peterson7243b572014-11-23 17:04:34 -0600409 server_hostname=self.host)
Antoine Pitrou8618d742012-11-23 20:13:48 +0100410 self.file = self.sock.makefile('rb')
411 self._tls_established = True
412 return resp
413
414
415if HAVE_SSL:
Martin v. Löwis48440b72003-10-31 12:52:35 +0000416
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000417 class POP3_SSL(POP3):
418 """POP3 client class over SSL connection
Martin v. Löwis48440b72003-10-31 12:52:35 +0000419
Antoine Pitrou8618d742012-11-23 20:13:48 +0100420 Instantiate with: POP3_SSL(hostname, port=995, keyfile=None, certfile=None,
421 context=None)
Martin v. Löwis48440b72003-10-31 12:52:35 +0000422
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000423 hostname - the hostname of the pop3 over ssl server
424 port - port number
Ezio Melotti30b9d5d2013-08-17 15:50:46 +0300425 keyfile - PEM formatted file that contains your private key
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000426 certfile - PEM formatted certificate chain file
Antoine Pitrou8618d742012-11-23 20:13:48 +0100427 context - a ssl.SSLContext
Martin v. Löwis48440b72003-10-31 12:52:35 +0000428
Christian Heimesd3956292008-11-05 19:48:27 +0000429 See the methods of the parent class POP3 for more documentation.
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000430 """
Martin v. Löwis48440b72003-10-31 12:52:35 +0000431
Giampaolo Rodolà42382fe2010-08-17 16:09:53 +0000432 def __init__(self, host, port=POP3_SSL_PORT, keyfile=None, certfile=None,
433 timeout=socket._GLOBAL_DEFAULT_TIMEOUT, context=None):
434 if context is not None and keyfile is not None:
435 raise ValueError("context and keyfile arguments are mutually "
436 "exclusive")
437 if context is not None and certfile is not None:
438 raise ValueError("context and certfile arguments are mutually "
439 "exclusive")
Christian Heimesd0486372016-09-10 23:23:33 +0200440 if keyfile is not None or certfile is not None:
441 import warnings
Pablo Aguiar4b5e62d2018-11-01 11:33:35 +0100442 warnings.warn("keyfile and certfile are deprecated, use a "
Christian Heimesd0486372016-09-10 23:23:33 +0200443 "custom context instead", DeprecationWarning, 2)
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000444 self.keyfile = keyfile
445 self.certfile = certfile
Christian Heimes67986f92013-11-23 22:43:47 +0100446 if context is None:
447 context = ssl._create_stdlib_context(certfile=certfile,
448 keyfile=keyfile)
Giampaolo Rodolà42382fe2010-08-17 16:09:53 +0000449 self.context = context
Christian Heimesd3956292008-11-05 19:48:27 +0000450 POP3.__init__(self, host, port, timeout)
Martin v. Löwis48440b72003-10-31 12:52:35 +0000451
Christian Heimesd3956292008-11-05 19:48:27 +0000452 def _create_socket(self, timeout):
453 sock = POP3._create_socket(self, timeout)
Christian Heimes1bc70682013-12-02 20:10:50 +0100454 sock = self.context.wrap_socket(sock,
Benjamin Peterson7243b572014-11-23 17:04:34 -0600455 server_hostname=self.host)
Giampaolo Rodolà42382fe2010-08-17 16:09:53 +0000456 return sock
Martin v. Löwis48440b72003-10-31 12:52:35 +0000457
Antoine Pitrou8618d742012-11-23 20:13:48 +0100458 def stls(self, keyfile=None, certfile=None, context=None):
459 """The method unconditionally raises an exception since the
460 STLS command doesn't make any sense on an already established
461 SSL/TLS session.
462 """
463 raise error_proto('-ERR TLS session already established')
464
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000465 __all__.append("POP3_SSL")
Guido van Rossum03774bb1998-04-09 13:50:55 +0000466
Guido van Rossum484772d1998-04-06 18:27:27 +0000467if __name__ == "__main__":
Eric S. Raymond341f9292001-02-09 06:56:56 +0000468 import sys
469 a = POP3(sys.argv[1])
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000470 print(a.getwelcome())
Eric S. Raymond341f9292001-02-09 06:56:56 +0000471 a.user(sys.argv[2])
472 a.pass_(sys.argv[3])
Tim Peters2344fae2001-01-15 00:50:52 +0000473 a.list()
474 (numMsgs, totalSize) = a.stat()
475 for i in range(1, numMsgs + 1):
476 (header, msg, octets) = a.retr(i)
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000477 print("Message %d:" % i)
Tim Peters2344fae2001-01-15 00:50:52 +0000478 for line in msg:
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000479 print(' ' + line)
480 print('-----------------------')
Tim Peters2344fae2001-01-15 00:50:52 +0000481 a.quit()