blob: cbd1df9fc99b50e73d773e0b51921b9b409bb762 [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
Guido van Rossum484772d1998-04-06 18:27:27 +000019
Antoine Pitrou8618d742012-11-23 20:13:48 +010020try:
21 import ssl
22 HAVE_SSL = True
23except ImportError:
24 HAVE_SSL = False
25
Thomas Wouters47b49bf2007-08-30 22:15:33 +000026__all__ = ["POP3","error_proto"]
Skip Montanaroc62c81e2001-02-12 02:00:42 +000027
Guido van Rossum484772d1998-04-06 18:27:27 +000028# Exception raised when an error or invalid response is received:
Guido van Rossum03774bb1998-04-09 13:50:55 +000029
30class error_proto(Exception): pass
Guido van Rossum484772d1998-04-06 18:27:27 +000031
32# Standard Port
33POP3_PORT = 110
34
Martin v. Löwis48440b72003-10-31 12:52:35 +000035# POP SSL PORT
36POP3_SSL_PORT = 995
37
Guido van Rossum03774bb1998-04-09 13:50:55 +000038# Line terminators (we always output CRLF, but accept any of CRLF, LFCR, LF)
Jeremy Hylton88d06a72007-08-29 19:08:30 +000039CR = b'\r'
40LF = b'\n'
Guido van Rossum03774bb1998-04-09 13:50:55 +000041CRLF = CR+LF
Guido van Rossum484772d1998-04-06 18:27:27 +000042
43
44class POP3:
Guido van Rossum03774bb1998-04-09 13:50:55 +000045
Tim Peters2344fae2001-01-15 00:50:52 +000046 """This class supports both the minimal and optional command sets.
47 Arguments can be strings or integers (where appropriate)
48 (e.g.: retr(1) and retr('1') both work equally well.
Guido van Rossum03774bb1998-04-09 13:50:55 +000049
Tim Peters2344fae2001-01-15 00:50:52 +000050 Minimal Command Set:
51 USER name user(name)
52 PASS string pass_(string)
53 STAT stat()
54 LIST [msg] list(msg = None)
55 RETR msg retr(msg)
56 DELE msg dele(msg)
57 NOOP noop()
58 RSET rset()
59 QUIT quit()
Guido van Rossum03774bb1998-04-09 13:50:55 +000060
Tim Peters2344fae2001-01-15 00:50:52 +000061 Optional Commands (some servers support these):
62 RPOP name rpop(name)
63 APOP name digest apop(name, digest)
64 TOP msg n top(msg, n)
65 UIDL [msg] uidl(msg = None)
Antoine Pitrou25cee192012-11-23 20:07:39 +010066 CAPA capa()
Antoine Pitrou8618d742012-11-23 20:13:48 +010067 STLS stls()
Guido van Rossum03774bb1998-04-09 13:50:55 +000068
Tim Peters2344fae2001-01-15 00:50:52 +000069 Raises one exception: 'error_proto'.
Guido van Rossum03774bb1998-04-09 13:50:55 +000070
Tim Peters2344fae2001-01-15 00:50:52 +000071 Instantiate with:
72 POP3(hostname, port=110)
Guido van Rossum03774bb1998-04-09 13:50:55 +000073
Tim Peters2344fae2001-01-15 00:50:52 +000074 NB: the POP protocol locks the mailbox from user
75 authorization until QUIT, so be sure to get in, suck
76 the messages, and quit, each time you access the
77 mailbox.
Guido van Rossum03774bb1998-04-09 13:50:55 +000078
Tim Peters2344fae2001-01-15 00:50:52 +000079 POP is a line-based protocol, which means large mail
80 messages consume lots of python cycles reading them
81 line-by-line.
Guido van Rossum03774bb1998-04-09 13:50:55 +000082
Tim Peters2344fae2001-01-15 00:50:52 +000083 If it's available on your mail server, use IMAP4
84 instead, it doesn't suffer from the two problems
85 above.
86 """
Guido van Rossum03774bb1998-04-09 13:50:55 +000087
Christian Heimesd3956292008-11-05 19:48:27 +000088 encoding = 'UTF-8'
Guido van Rossum03774bb1998-04-09 13:50:55 +000089
Georg Brandlf78e02b2008-06-10 17:40:04 +000090 def __init__(self, host, port=POP3_PORT,
91 timeout=socket._GLOBAL_DEFAULT_TIMEOUT):
Martin v. Löwis4eb59402001-07-26 13:37:33 +000092 self.host = host
93 self.port = port
Antoine Pitrou8618d742012-11-23 20:13:48 +010094 self._tls_established = False
Christian Heimesd3956292008-11-05 19:48:27 +000095 self.sock = self._create_socket(timeout)
Martin v. Löwis4eb59402001-07-26 13:37:33 +000096 self.file = self.sock.makefile('rb')
97 self._debugging = 0
98 self.welcome = self._getresp()
Guido van Rossum484772d1998-04-06 18:27:27 +000099
Christian Heimesd3956292008-11-05 19:48:27 +0000100 def _create_socket(self, timeout):
101 return socket.create_connection((self.host, self.port), timeout)
Guido van Rossum03774bb1998-04-09 13:50:55 +0000102
Tim Peters2344fae2001-01-15 00:50:52 +0000103 def _putline(self, line):
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000104 if self._debugging > 1: print('*put*', repr(line))
Christian Heimesd3956292008-11-05 19:48:27 +0000105 self.sock.sendall(line + CRLF)
Guido van Rossum03774bb1998-04-09 13:50:55 +0000106
Guido van Rossum484772d1998-04-06 18:27:27 +0000107
Tim Peters2344fae2001-01-15 00:50:52 +0000108 # Internal: send one command to the server (through _putline())
Guido van Rossum03774bb1998-04-09 13:50:55 +0000109
Tim Peters2344fae2001-01-15 00:50:52 +0000110 def _putcmd(self, line):
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000111 if self._debugging: print('*cmd*', repr(line))
Christian Heimesd3956292008-11-05 19:48:27 +0000112 line = bytes(line, self.encoding)
Tim Peters2344fae2001-01-15 00:50:52 +0000113 self._putline(line)
Guido van Rossum484772d1998-04-06 18:27:27 +0000114
Guido van Rossum03774bb1998-04-09 13:50:55 +0000115
Tim Peters2344fae2001-01-15 00:50:52 +0000116 # Internal: return one line from the server, stripping CRLF.
117 # This is where all the CPU time of this module is consumed.
118 # Raise error_proto('-ERR EOF') if the connection is closed.
Guido van Rossum03774bb1998-04-09 13:50:55 +0000119
Tim Peters2344fae2001-01-15 00:50:52 +0000120 def _getline(self):
121 line = self.file.readline()
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000122 if self._debugging > 1: print('*get*', repr(line))
Tim Peters2344fae2001-01-15 00:50:52 +0000123 if not line: raise error_proto('-ERR EOF')
124 octets = len(line)
125 # server can send any combination of CR & LF
126 # however, 'readline()' returns lines ending in LF
127 # so only possibilities are ...LF, ...CRLF, CR...LF
128 if line[-2:] == CRLF:
129 return line[:-2], octets
130 if line[0] == CR:
131 return line[1:-1], octets
132 return line[:-1], octets
Guido van Rossum03774bb1998-04-09 13:50:55 +0000133
Guido van Rossum484772d1998-04-06 18:27:27 +0000134
Tim Peters2344fae2001-01-15 00:50:52 +0000135 # Internal: get a response from the server.
136 # Raise 'error_proto' if the response doesn't start with '+'.
Guido van Rossum03774bb1998-04-09 13:50:55 +0000137
Tim Peters2344fae2001-01-15 00:50:52 +0000138 def _getresp(self):
139 resp, o = self._getline()
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000140 if self._debugging > 1: print('*resp*', repr(resp))
Christian Heimesd3956292008-11-05 19:48:27 +0000141 if not resp.startswith(b'+'):
Tim Peters2344fae2001-01-15 00:50:52 +0000142 raise error_proto(resp)
143 return resp
Guido van Rossum484772d1998-04-06 18:27:27 +0000144
Guido van Rossum03774bb1998-04-09 13:50:55 +0000145
Tim Peters2344fae2001-01-15 00:50:52 +0000146 # Internal: get a response plus following text from the server.
Guido van Rossum03774bb1998-04-09 13:50:55 +0000147
Tim Peters2344fae2001-01-15 00:50:52 +0000148 def _getlongresp(self):
149 resp = self._getresp()
150 list = []; octets = 0
151 line, o = self._getline()
Guido van Rossum0ec34772007-09-10 00:27:13 +0000152 while line != b'.':
Christian Heimesd3956292008-11-05 19:48:27 +0000153 if line.startswith(b'..'):
Tim Peters2344fae2001-01-15 00:50:52 +0000154 o = o-1
155 line = line[1:]
156 octets = octets + o
157 list.append(line)
158 line, o = self._getline()
159 return resp, list, octets
Guido van Rossum03774bb1998-04-09 13:50:55 +0000160
Guido van Rossum484772d1998-04-06 18:27:27 +0000161
Tim Peters2344fae2001-01-15 00:50:52 +0000162 # Internal: send a command and get the response
Guido van Rossum03774bb1998-04-09 13:50:55 +0000163
Tim Peters2344fae2001-01-15 00:50:52 +0000164 def _shortcmd(self, line):
165 self._putcmd(line)
166 return self._getresp()
Guido van Rossum484772d1998-04-06 18:27:27 +0000167
Guido van Rossum03774bb1998-04-09 13:50:55 +0000168
Tim Peters2344fae2001-01-15 00:50:52 +0000169 # Internal: send a command and get the response plus following text
Guido van Rossum03774bb1998-04-09 13:50:55 +0000170
Tim Peters2344fae2001-01-15 00:50:52 +0000171 def _longcmd(self, line):
172 self._putcmd(line)
173 return self._getlongresp()
Guido van Rossum484772d1998-04-06 18:27:27 +0000174
Guido van Rossum03774bb1998-04-09 13:50:55 +0000175
Tim Peters2344fae2001-01-15 00:50:52 +0000176 # These can be useful:
177
178 def getwelcome(self):
179 return self.welcome
180
181
182 def set_debuglevel(self, level):
183 self._debugging = level
184
185
186 # Here are all the POP commands:
187
188 def user(self, user):
189 """Send user name, return response
Guido van Rossum484772d1998-04-06 18:27:27 +0000190
Tim Peters2344fae2001-01-15 00:50:52 +0000191 (should indicate password required).
192 """
193 return self._shortcmd('USER %s' % user)
Guido van Rossum484772d1998-04-06 18:27:27 +0000194
Guido van Rossum03774bb1998-04-09 13:50:55 +0000195
Tim Peters2344fae2001-01-15 00:50:52 +0000196 def pass_(self, pswd):
197 """Send password, return response
Guido van Rossum484772d1998-04-06 18:27:27 +0000198
Tim Peters2344fae2001-01-15 00:50:52 +0000199 (response includes message count, mailbox size).
Guido van Rossum03774bb1998-04-09 13:50:55 +0000200
Tim Peters2344fae2001-01-15 00:50:52 +0000201 NB: mailbox is locked by server from here to 'quit()'
202 """
203 return self._shortcmd('PASS %s' % pswd)
Guido van Rossum484772d1998-04-06 18:27:27 +0000204
Guido van Rossum03774bb1998-04-09 13:50:55 +0000205
Tim Peters2344fae2001-01-15 00:50:52 +0000206 def stat(self):
207 """Get mailbox status.
Guido van Rossum484772d1998-04-06 18:27:27 +0000208
Tim Peters2344fae2001-01-15 00:50:52 +0000209 Result is tuple of 2 ints (message count, mailbox size)
210 """
211 retval = self._shortcmd('STAT')
Eric S. Raymond341f9292001-02-09 06:56:56 +0000212 rets = retval.split()
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000213 if self._debugging: print('*stat*', repr(rets))
Eric S. Raymond341f9292001-02-09 06:56:56 +0000214 numMessages = int(rets[1])
215 sizeMessages = int(rets[2])
Tim Peters2344fae2001-01-15 00:50:52 +0000216 return (numMessages, sizeMessages)
Guido van Rossum03774bb1998-04-09 13:50:55 +0000217
Guido van Rossum03774bb1998-04-09 13:50:55 +0000218
Tim Peters2344fae2001-01-15 00:50:52 +0000219 def list(self, which=None):
220 """Request listing, return result.
Guido van Rossum484772d1998-04-06 18:27:27 +0000221
Tim Peters2344fae2001-01-15 00:50:52 +0000222 Result without a message number argument is in form
Georg Brandl2772c672005-08-05 21:01:58 +0000223 ['response', ['mesg_num octets', ...], octets].
Guido van Rossum484772d1998-04-06 18:27:27 +0000224
Tim Peters2344fae2001-01-15 00:50:52 +0000225 Result when a message number argument is given is a
226 single response: the "scan listing" for that message.
227 """
Raymond Hettinger16e3c422002-06-01 16:07:16 +0000228 if which is not None:
Tim Peters2344fae2001-01-15 00:50:52 +0000229 return self._shortcmd('LIST %s' % which)
230 return self._longcmd('LIST')
Guido van Rossum03774bb1998-04-09 13:50:55 +0000231
Guido van Rossum03774bb1998-04-09 13:50:55 +0000232
Tim Peters2344fae2001-01-15 00:50:52 +0000233 def retr(self, which):
234 """Retrieve whole message number 'which'.
Guido van Rossumf6ae7431998-09-02 14:42:02 +0000235
Tim Peters2344fae2001-01-15 00:50:52 +0000236 Result is in form ['response', ['line', ...], octets].
237 """
238 return self._longcmd('RETR %s' % which)
Guido van Rossum03774bb1998-04-09 13:50:55 +0000239
Guido van Rossum484772d1998-04-06 18:27:27 +0000240
Tim Peters2344fae2001-01-15 00:50:52 +0000241 def dele(self, which):
242 """Delete message number 'which'.
Guido van Rossum03774bb1998-04-09 13:50:55 +0000243
Tim Peters2344fae2001-01-15 00:50:52 +0000244 Result is 'response'.
245 """
246 return self._shortcmd('DELE %s' % which)
Guido van Rossum03774bb1998-04-09 13:50:55 +0000247
Guido van Rossum484772d1998-04-06 18:27:27 +0000248
Tim Peters2344fae2001-01-15 00:50:52 +0000249 def noop(self):
250 """Does nothing.
Guido van Rossum03774bb1998-04-09 13:50:55 +0000251
Tim Peters2344fae2001-01-15 00:50:52 +0000252 One supposes the response indicates the server is alive.
253 """
254 return self._shortcmd('NOOP')
Guido van Rossum03774bb1998-04-09 13:50:55 +0000255
Guido van Rossum484772d1998-04-06 18:27:27 +0000256
Tim Peters2344fae2001-01-15 00:50:52 +0000257 def rset(self):
Benjamin Petersona37cfc62008-05-26 13:48:34 +0000258 """Unmark all messages marked for deletion."""
Tim Peters2344fae2001-01-15 00:50:52 +0000259 return self._shortcmd('RSET')
Guido van Rossum484772d1998-04-06 18:27:27 +0000260
Guido van Rossum03774bb1998-04-09 13:50:55 +0000261
Tim Peters2344fae2001-01-15 00:50:52 +0000262 def quit(self):
263 """Signoff: commit changes on server, unlock mailbox, close connection."""
Giampaolo Rodolà95bcb932011-02-25 22:28:24 +0000264 resp = self._shortcmd('QUIT')
265 self.close()
Tim Peters2344fae2001-01-15 00:50:52 +0000266 return resp
Guido van Rossum484772d1998-04-06 18:27:27 +0000267
Giampaolo Rodolà95bcb932011-02-25 22:28:24 +0000268 def close(self):
269 """Close the connection without assuming anything about it."""
270 if self.file is not None:
271 self.file.close()
272 if self.sock is not None:
Antoine Pitroud89824b2012-11-23 20:04:45 +0100273 try:
274 self.sock.shutdown(socket.SHUT_RDWR)
275 except socket.error as e:
276 # The server might already have closed the connection
277 if e.errno != errno.ENOTCONN:
278 raise
279 finally:
280 self.sock.close()
Giampaolo Rodolà95bcb932011-02-25 22:28:24 +0000281 self.file = self.sock = None
282
Tim Peters2344fae2001-01-15 00:50:52 +0000283 #__del__ = quit
Guido van Rossum484772d1998-04-06 18:27:27 +0000284
Guido van Rossum484772d1998-04-06 18:27:27 +0000285
Tim Peters2344fae2001-01-15 00:50:52 +0000286 # optional commands:
Guido van Rossum03774bb1998-04-09 13:50:55 +0000287
Tim Peters2344fae2001-01-15 00:50:52 +0000288 def rpop(self, user):
289 """Not sure what this does."""
290 return self._shortcmd('RPOP %s' % user)
Guido van Rossum03774bb1998-04-09 13:50:55 +0000291
Guido van Rossum03774bb1998-04-09 13:50:55 +0000292
Christian Heimesd3956292008-11-05 19:48:27 +0000293 timestamp = re.compile(br'\+OK.*(<[^>]+>)')
Guido van Rossum03774bb1998-04-09 13:50:55 +0000294
Christian Heimesd3956292008-11-05 19:48:27 +0000295 def apop(self, user, password):
Tim Peters2344fae2001-01-15 00:50:52 +0000296 """Authorisation
Guido van Rossum03774bb1998-04-09 13:50:55 +0000297
Tim Peters2344fae2001-01-15 00:50:52 +0000298 - only possible if server has supplied a timestamp in initial greeting.
Guido van Rossum03774bb1998-04-09 13:50:55 +0000299
Tim Peters2344fae2001-01-15 00:50:52 +0000300 Args:
Christian Heimesd3956292008-11-05 19:48:27 +0000301 user - mailbox user;
302 password - mailbox password.
Guido van Rossum03774bb1998-04-09 13:50:55 +0000303
Tim Peters2344fae2001-01-15 00:50:52 +0000304 NB: mailbox is locked by server from here to 'quit()'
305 """
Mark Dickinsonea1158f2009-08-06 16:06:25 +0000306 secret = bytes(password, self.encoding)
Moshe Zadkaccc2e3d2001-01-19 19:56:27 +0000307 m = self.timestamp.match(self.welcome)
308 if not m:
Tim Peters2344fae2001-01-15 00:50:52 +0000309 raise error_proto('-ERR APOP not supported by server')
Thomas Wouters477c8d52006-05-27 19:21:47 +0000310 import hashlib
Christian Heimesd3956292008-11-05 19:48:27 +0000311 digest = m.group(1)+secret
312 digest = hashlib.md5(digest).hexdigest()
Tim Peters2344fae2001-01-15 00:50:52 +0000313 return self._shortcmd('APOP %s %s' % (user, digest))
Guido van Rossum03774bb1998-04-09 13:50:55 +0000314
Guido van Rossum03774bb1998-04-09 13:50:55 +0000315
Tim Peters2344fae2001-01-15 00:50:52 +0000316 def top(self, which, howmuch):
317 """Retrieve message header of message number 'which'
318 and first 'howmuch' lines of message body.
Guido van Rossum03774bb1998-04-09 13:50:55 +0000319
Tim Peters2344fae2001-01-15 00:50:52 +0000320 Result is in form ['response', ['line', ...], octets].
321 """
322 return self._longcmd('TOP %s %s' % (which, howmuch))
Guido van Rossum03774bb1998-04-09 13:50:55 +0000323
Guido van Rossum03774bb1998-04-09 13:50:55 +0000324
Tim Peters2344fae2001-01-15 00:50:52 +0000325 def uidl(self, which=None):
326 """Return message digest (unique id) list.
Guido van Rossum03774bb1998-04-09 13:50:55 +0000327
Tim Peters2344fae2001-01-15 00:50:52 +0000328 If 'which', result contains unique id for that message
329 in the form 'response mesgnum uid', otherwise result is
330 the list ['response', ['mesgnum uid', ...], octets]
331 """
Raymond Hettinger16e3c422002-06-01 16:07:16 +0000332 if which is not None:
Tim Peters2344fae2001-01-15 00:50:52 +0000333 return self._shortcmd('UIDL %s' % which)
334 return self._longcmd('UIDL')
Guido van Rossum03774bb1998-04-09 13:50:55 +0000335
Antoine Pitrou25cee192012-11-23 20:07:39 +0100336
337 def capa(self):
338 """Return server capabilities (RFC 2449) as a dictionary
339 >>> c=poplib.POP3('localhost')
340 >>> c.capa()
341 {'IMPLEMENTATION': ['Cyrus', 'POP3', 'server', 'v2.2.12'],
342 'TOP': [], 'LOGIN-DELAY': ['0'], 'AUTH-RESP-CODE': [],
343 'EXPIRE': ['NEVER'], 'USER': [], 'STLS': [], 'PIPELINING': [],
344 'UIDL': [], 'RESP-CODES': []}
345 >>>
346
347 Really, according to RFC 2449, the cyrus folks should avoid
348 having the implementation splitted into multiple arguments...
349 """
350 def _parsecap(line):
351 lst = line.decode('ascii').split()
352 return lst[0], lst[1:]
353
354 caps = {}
355 try:
356 resp = self._longcmd('CAPA')
357 rawcaps = resp[1]
358 for capline in rawcaps:
359 capnm, capargs = _parsecap(capline)
360 caps[capnm] = capargs
361 except error_proto as _err:
362 raise error_proto('-ERR CAPA not supported by server')
363 return caps
364
Antoine Pitrou8618d742012-11-23 20:13:48 +0100365
366 def stls(self, context=None):
367 """Start a TLS session on the active connection as specified in RFC 2595.
368
369 context - a ssl.SSLContext
370 """
371 if not HAVE_SSL:
372 raise error_proto('-ERR TLS support missing')
373 if self._tls_established:
374 raise error_proto('-ERR TLS session already established')
375 caps = self.capa()
376 if not 'STLS' in caps:
377 raise error_proto('-ERR STLS not supported by server')
378 if context is None:
379 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
380 context.options |= ssl.OP_NO_SSLv2
381 resp = self._shortcmd('STLS')
382 self.sock = context.wrap_socket(self.sock)
383 self.file = self.sock.makefile('rb')
384 self._tls_established = True
385 return resp
386
387
388if HAVE_SSL:
Martin v. Löwis48440b72003-10-31 12:52:35 +0000389
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000390 class POP3_SSL(POP3):
391 """POP3 client class over SSL connection
Martin v. Löwis48440b72003-10-31 12:52:35 +0000392
Antoine Pitrou8618d742012-11-23 20:13:48 +0100393 Instantiate with: POP3_SSL(hostname, port=995, keyfile=None, certfile=None,
394 context=None)
Martin v. Löwis48440b72003-10-31 12:52:35 +0000395
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000396 hostname - the hostname of the pop3 over ssl server
397 port - port number
398 keyfile - PEM formatted file that countains your private key
399 certfile - PEM formatted certificate chain file
Antoine Pitrou8618d742012-11-23 20:13:48 +0100400 context - a ssl.SSLContext
Martin v. Löwis48440b72003-10-31 12:52:35 +0000401
Christian Heimesd3956292008-11-05 19:48:27 +0000402 See the methods of the parent class POP3 for more documentation.
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000403 """
Martin v. Löwis48440b72003-10-31 12:52:35 +0000404
Giampaolo Rodolà42382fe2010-08-17 16:09:53 +0000405 def __init__(self, host, port=POP3_SSL_PORT, keyfile=None, certfile=None,
406 timeout=socket._GLOBAL_DEFAULT_TIMEOUT, context=None):
407 if context is not None and keyfile is not None:
408 raise ValueError("context and keyfile arguments are mutually "
409 "exclusive")
410 if context is not None and certfile is not None:
411 raise ValueError("context and certfile arguments are mutually "
412 "exclusive")
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000413 self.keyfile = keyfile
414 self.certfile = certfile
Giampaolo Rodolà42382fe2010-08-17 16:09:53 +0000415 self.context = context
Christian Heimesd3956292008-11-05 19:48:27 +0000416 POP3.__init__(self, host, port, timeout)
Martin v. Löwis48440b72003-10-31 12:52:35 +0000417
Christian Heimesd3956292008-11-05 19:48:27 +0000418 def _create_socket(self, timeout):
419 sock = POP3._create_socket(self, timeout)
Giampaolo Rodolà42382fe2010-08-17 16:09:53 +0000420 if self.context is not None:
421 sock = self.context.wrap_socket(sock)
422 else:
423 sock = ssl.wrap_socket(sock, self.keyfile, self.certfile)
424 return sock
Martin v. Löwis48440b72003-10-31 12:52:35 +0000425
Antoine Pitrou8618d742012-11-23 20:13:48 +0100426 def stls(self, keyfile=None, certfile=None, context=None):
427 """The method unconditionally raises an exception since the
428 STLS command doesn't make any sense on an already established
429 SSL/TLS session.
430 """
431 raise error_proto('-ERR TLS session already established')
432
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000433 __all__.append("POP3_SSL")
Guido van Rossum03774bb1998-04-09 13:50:55 +0000434
Guido van Rossum484772d1998-04-06 18:27:27 +0000435if __name__ == "__main__":
Eric S. Raymond341f9292001-02-09 06:56:56 +0000436 import sys
437 a = POP3(sys.argv[1])
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000438 print(a.getwelcome())
Eric S. Raymond341f9292001-02-09 06:56:56 +0000439 a.user(sys.argv[2])
440 a.pass_(sys.argv[3])
Tim Peters2344fae2001-01-15 00:50:52 +0000441 a.list()
442 (numMsgs, totalSize) = a.stat()
443 for i in range(1, numMsgs + 1):
444 (header, msg, octets) = a.retr(i)
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000445 print("Message %d:" % i)
Tim Peters2344fae2001-01-15 00:50:52 +0000446 for line in msg:
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000447 print(' ' + line)
448 print('-----------------------')
Tim Peters2344fae2001-01-15 00:50:52 +0000449 a.quit()