blob: bfcde028990178bbf891eb0a0a8749e4b0b9fb23 [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
Eric S. Raymond341f9292001-02-09 06:56:56 +000016import re, socket
Guido van Rossum484772d1998-04-06 18:27:27 +000017
Antoine Pitrou8618d742012-11-23 20:13:48 +010018try:
19 import ssl
20 HAVE_SSL = True
21except ImportError:
22 HAVE_SSL = False
23
Thomas Wouters47b49bf2007-08-30 22:15:33 +000024__all__ = ["POP3","error_proto"]
Skip Montanaroc62c81e2001-02-12 02:00:42 +000025
Guido van Rossum484772d1998-04-06 18:27:27 +000026# Exception raised when an error or invalid response is received:
Guido van Rossum03774bb1998-04-09 13:50:55 +000027
28class error_proto(Exception): pass
Guido van Rossum484772d1998-04-06 18:27:27 +000029
30# Standard Port
31POP3_PORT = 110
32
Martin v. Löwis48440b72003-10-31 12:52:35 +000033# POP SSL PORT
34POP3_SSL_PORT = 995
35
Guido van Rossum03774bb1998-04-09 13:50:55 +000036# Line terminators (we always output CRLF, but accept any of CRLF, LFCR, LF)
Jeremy Hylton88d06a72007-08-29 19:08:30 +000037CR = b'\r'
38LF = b'\n'
Guido van Rossum03774bb1998-04-09 13:50:55 +000039CRLF = CR+LF
Guido van Rossum484772d1998-04-06 18:27:27 +000040
41
42class POP3:
Guido van Rossum03774bb1998-04-09 13:50:55 +000043
Tim Peters2344fae2001-01-15 00:50:52 +000044 """This class supports both the minimal and optional command sets.
45 Arguments can be strings or integers (where appropriate)
46 (e.g.: retr(1) and retr('1') both work equally well.
Guido van Rossum03774bb1998-04-09 13:50:55 +000047
Tim Peters2344fae2001-01-15 00:50:52 +000048 Minimal Command Set:
49 USER name user(name)
50 PASS string pass_(string)
51 STAT stat()
52 LIST [msg] list(msg = None)
53 RETR msg retr(msg)
54 DELE msg dele(msg)
55 NOOP noop()
56 RSET rset()
57 QUIT quit()
Guido van Rossum03774bb1998-04-09 13:50:55 +000058
Tim Peters2344fae2001-01-15 00:50:52 +000059 Optional Commands (some servers support these):
60 RPOP name rpop(name)
61 APOP name digest apop(name, digest)
62 TOP msg n top(msg, n)
63 UIDL [msg] uidl(msg = None)
Antoine Pitrou25cee192012-11-23 20:07:39 +010064 CAPA capa()
Antoine Pitrou8618d742012-11-23 20:13:48 +010065 STLS stls()
Guido van Rossum03774bb1998-04-09 13:50:55 +000066
Tim Peters2344fae2001-01-15 00:50:52 +000067 Raises one exception: 'error_proto'.
Guido van Rossum03774bb1998-04-09 13:50:55 +000068
Tim Peters2344fae2001-01-15 00:50:52 +000069 Instantiate with:
70 POP3(hostname, port=110)
Guido van Rossum03774bb1998-04-09 13:50:55 +000071
Tim Peters2344fae2001-01-15 00:50:52 +000072 NB: the POP protocol locks the mailbox from user
73 authorization until QUIT, so be sure to get in, suck
74 the messages, and quit, each time you access the
75 mailbox.
Guido van Rossum03774bb1998-04-09 13:50:55 +000076
Tim Peters2344fae2001-01-15 00:50:52 +000077 POP is a line-based protocol, which means large mail
78 messages consume lots of python cycles reading them
79 line-by-line.
Guido van Rossum03774bb1998-04-09 13:50:55 +000080
Tim Peters2344fae2001-01-15 00:50:52 +000081 If it's available on your mail server, use IMAP4
82 instead, it doesn't suffer from the two problems
83 above.
84 """
Guido van Rossum03774bb1998-04-09 13:50:55 +000085
Christian Heimesd3956292008-11-05 19:48:27 +000086 encoding = 'UTF-8'
Guido van Rossum03774bb1998-04-09 13:50:55 +000087
Georg Brandlf78e02b2008-06-10 17:40:04 +000088 def __init__(self, host, port=POP3_PORT,
89 timeout=socket._GLOBAL_DEFAULT_TIMEOUT):
Martin v. Löwis4eb59402001-07-26 13:37:33 +000090 self.host = host
91 self.port = port
Antoine Pitrou8618d742012-11-23 20:13:48 +010092 self._tls_established = False
Christian Heimesd3956292008-11-05 19:48:27 +000093 self.sock = self._create_socket(timeout)
Martin v. Löwis4eb59402001-07-26 13:37:33 +000094 self.file = self.sock.makefile('rb')
95 self._debugging = 0
96 self.welcome = self._getresp()
Guido van Rossum484772d1998-04-06 18:27:27 +000097
Christian Heimesd3956292008-11-05 19:48:27 +000098 def _create_socket(self, timeout):
99 return socket.create_connection((self.host, self.port), timeout)
Guido van Rossum03774bb1998-04-09 13:50:55 +0000100
Tim Peters2344fae2001-01-15 00:50:52 +0000101 def _putline(self, line):
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000102 if self._debugging > 1: print('*put*', repr(line))
Christian Heimesd3956292008-11-05 19:48:27 +0000103 self.sock.sendall(line + CRLF)
Guido van Rossum03774bb1998-04-09 13:50:55 +0000104
Guido van Rossum484772d1998-04-06 18:27:27 +0000105
Tim Peters2344fae2001-01-15 00:50:52 +0000106 # Internal: send one command to the server (through _putline())
Guido van Rossum03774bb1998-04-09 13:50:55 +0000107
Tim Peters2344fae2001-01-15 00:50:52 +0000108 def _putcmd(self, line):
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000109 if self._debugging: print('*cmd*', repr(line))
Christian Heimesd3956292008-11-05 19:48:27 +0000110 line = bytes(line, self.encoding)
Tim Peters2344fae2001-01-15 00:50:52 +0000111 self._putline(line)
Guido van Rossum484772d1998-04-06 18:27:27 +0000112
Guido van Rossum03774bb1998-04-09 13:50:55 +0000113
Tim Peters2344fae2001-01-15 00:50:52 +0000114 # Internal: return one line from the server, stripping CRLF.
115 # This is where all the CPU time of this module is consumed.
116 # Raise error_proto('-ERR EOF') if the connection is closed.
Guido van Rossum03774bb1998-04-09 13:50:55 +0000117
Tim Peters2344fae2001-01-15 00:50:52 +0000118 def _getline(self):
119 line = self.file.readline()
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000120 if self._debugging > 1: print('*get*', repr(line))
Tim Peters2344fae2001-01-15 00:50:52 +0000121 if not line: raise error_proto('-ERR EOF')
122 octets = len(line)
123 # server can send any combination of CR & LF
124 # however, 'readline()' returns lines ending in LF
125 # so only possibilities are ...LF, ...CRLF, CR...LF
126 if line[-2:] == CRLF:
127 return line[:-2], octets
128 if line[0] == CR:
129 return line[1:-1], octets
130 return line[:-1], octets
Guido van Rossum03774bb1998-04-09 13:50:55 +0000131
Guido van Rossum484772d1998-04-06 18:27:27 +0000132
Tim Peters2344fae2001-01-15 00:50:52 +0000133 # Internal: get a response from the server.
134 # Raise 'error_proto' if the response doesn't start with '+'.
Guido van Rossum03774bb1998-04-09 13:50:55 +0000135
Tim Peters2344fae2001-01-15 00:50:52 +0000136 def _getresp(self):
137 resp, o = self._getline()
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000138 if self._debugging > 1: print('*resp*', repr(resp))
Christian Heimesd3956292008-11-05 19:48:27 +0000139 if not resp.startswith(b'+'):
Tim Peters2344fae2001-01-15 00:50:52 +0000140 raise error_proto(resp)
141 return resp
Guido van Rossum484772d1998-04-06 18:27:27 +0000142
Guido van Rossum03774bb1998-04-09 13:50:55 +0000143
Tim Peters2344fae2001-01-15 00:50:52 +0000144 # Internal: get a response plus following text from the server.
Guido van Rossum03774bb1998-04-09 13:50:55 +0000145
Tim Peters2344fae2001-01-15 00:50:52 +0000146 def _getlongresp(self):
147 resp = self._getresp()
148 list = []; octets = 0
149 line, o = self._getline()
Guido van Rossum0ec34772007-09-10 00:27:13 +0000150 while line != b'.':
Christian Heimesd3956292008-11-05 19:48:27 +0000151 if line.startswith(b'..'):
Tim Peters2344fae2001-01-15 00:50:52 +0000152 o = o-1
153 line = line[1:]
154 octets = octets + o
155 list.append(line)
156 line, o = self._getline()
157 return resp, list, octets
Guido van Rossum03774bb1998-04-09 13:50:55 +0000158
Guido van Rossum484772d1998-04-06 18:27:27 +0000159
Tim Peters2344fae2001-01-15 00:50:52 +0000160 # Internal: send a command and get the response
Guido van Rossum03774bb1998-04-09 13:50:55 +0000161
Tim Peters2344fae2001-01-15 00:50:52 +0000162 def _shortcmd(self, line):
163 self._putcmd(line)
164 return self._getresp()
Guido van Rossum484772d1998-04-06 18:27:27 +0000165
Guido van Rossum03774bb1998-04-09 13:50:55 +0000166
Tim Peters2344fae2001-01-15 00:50:52 +0000167 # Internal: send a command and get the response plus following text
Guido van Rossum03774bb1998-04-09 13:50:55 +0000168
Tim Peters2344fae2001-01-15 00:50:52 +0000169 def _longcmd(self, line):
170 self._putcmd(line)
171 return self._getlongresp()
Guido van Rossum484772d1998-04-06 18:27:27 +0000172
Guido van Rossum03774bb1998-04-09 13:50:55 +0000173
Tim Peters2344fae2001-01-15 00:50:52 +0000174 # These can be useful:
175
176 def getwelcome(self):
177 return self.welcome
178
179
180 def set_debuglevel(self, level):
181 self._debugging = level
182
183
184 # Here are all the POP commands:
185
186 def user(self, user):
187 """Send user name, return response
Guido van Rossum484772d1998-04-06 18:27:27 +0000188
Tim Peters2344fae2001-01-15 00:50:52 +0000189 (should indicate password required).
190 """
191 return self._shortcmd('USER %s' % user)
Guido van Rossum484772d1998-04-06 18:27:27 +0000192
Guido van Rossum03774bb1998-04-09 13:50:55 +0000193
Tim Peters2344fae2001-01-15 00:50:52 +0000194 def pass_(self, pswd):
195 """Send password, return response
Guido van Rossum484772d1998-04-06 18:27:27 +0000196
Tim Peters2344fae2001-01-15 00:50:52 +0000197 (response includes message count, mailbox size).
Guido van Rossum03774bb1998-04-09 13:50:55 +0000198
Tim Peters2344fae2001-01-15 00:50:52 +0000199 NB: mailbox is locked by server from here to 'quit()'
200 """
201 return self._shortcmd('PASS %s' % pswd)
Guido van Rossum484772d1998-04-06 18:27:27 +0000202
Guido van Rossum03774bb1998-04-09 13:50:55 +0000203
Tim Peters2344fae2001-01-15 00:50:52 +0000204 def stat(self):
205 """Get mailbox status.
Guido van Rossum484772d1998-04-06 18:27:27 +0000206
Tim Peters2344fae2001-01-15 00:50:52 +0000207 Result is tuple of 2 ints (message count, mailbox size)
208 """
209 retval = self._shortcmd('STAT')
Eric S. Raymond341f9292001-02-09 06:56:56 +0000210 rets = retval.split()
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000211 if self._debugging: print('*stat*', repr(rets))
Eric S. Raymond341f9292001-02-09 06:56:56 +0000212 numMessages = int(rets[1])
213 sizeMessages = int(rets[2])
Tim Peters2344fae2001-01-15 00:50:52 +0000214 return (numMessages, sizeMessages)
Guido van Rossum03774bb1998-04-09 13:50:55 +0000215
Guido van Rossum03774bb1998-04-09 13:50:55 +0000216
Tim Peters2344fae2001-01-15 00:50:52 +0000217 def list(self, which=None):
218 """Request listing, return result.
Guido van Rossum484772d1998-04-06 18:27:27 +0000219
Tim Peters2344fae2001-01-15 00:50:52 +0000220 Result without a message number argument is in form
Georg Brandl2772c672005-08-05 21:01:58 +0000221 ['response', ['mesg_num octets', ...], octets].
Guido van Rossum484772d1998-04-06 18:27:27 +0000222
Tim Peters2344fae2001-01-15 00:50:52 +0000223 Result when a message number argument is given is a
224 single response: the "scan listing" for that message.
225 """
Raymond Hettinger16e3c422002-06-01 16:07:16 +0000226 if which is not None:
Tim Peters2344fae2001-01-15 00:50:52 +0000227 return self._shortcmd('LIST %s' % which)
228 return self._longcmd('LIST')
Guido van Rossum03774bb1998-04-09 13:50:55 +0000229
Guido van Rossum03774bb1998-04-09 13:50:55 +0000230
Tim Peters2344fae2001-01-15 00:50:52 +0000231 def retr(self, which):
232 """Retrieve whole message number 'which'.
Guido van Rossumf6ae7431998-09-02 14:42:02 +0000233
Tim Peters2344fae2001-01-15 00:50:52 +0000234 Result is in form ['response', ['line', ...], octets].
235 """
236 return self._longcmd('RETR %s' % which)
Guido van Rossum03774bb1998-04-09 13:50:55 +0000237
Guido van Rossum484772d1998-04-06 18:27:27 +0000238
Tim Peters2344fae2001-01-15 00:50:52 +0000239 def dele(self, which):
240 """Delete message number 'which'.
Guido van Rossum03774bb1998-04-09 13:50:55 +0000241
Tim Peters2344fae2001-01-15 00:50:52 +0000242 Result is 'response'.
243 """
244 return self._shortcmd('DELE %s' % which)
Guido van Rossum03774bb1998-04-09 13:50:55 +0000245
Guido van Rossum484772d1998-04-06 18:27:27 +0000246
Tim Peters2344fae2001-01-15 00:50:52 +0000247 def noop(self):
248 """Does nothing.
Guido van Rossum03774bb1998-04-09 13:50:55 +0000249
Tim Peters2344fae2001-01-15 00:50:52 +0000250 One supposes the response indicates the server is alive.
251 """
252 return self._shortcmd('NOOP')
Guido van Rossum03774bb1998-04-09 13:50:55 +0000253
Guido van Rossum484772d1998-04-06 18:27:27 +0000254
Tim Peters2344fae2001-01-15 00:50:52 +0000255 def rset(self):
Benjamin Petersona37cfc62008-05-26 13:48:34 +0000256 """Unmark all messages marked for deletion."""
Tim Peters2344fae2001-01-15 00:50:52 +0000257 return self._shortcmd('RSET')
Guido van Rossum484772d1998-04-06 18:27:27 +0000258
Guido van Rossum03774bb1998-04-09 13:50:55 +0000259
Tim Peters2344fae2001-01-15 00:50:52 +0000260 def quit(self):
261 """Signoff: commit changes on server, unlock mailbox, close connection."""
Giampaolo Rodolà95bcb932011-02-25 22:28:24 +0000262 resp = self._shortcmd('QUIT')
263 self.close()
Tim Peters2344fae2001-01-15 00:50:52 +0000264 return resp
Guido van Rossum484772d1998-04-06 18:27:27 +0000265
Giampaolo Rodolà95bcb932011-02-25 22:28:24 +0000266 def close(self):
267 """Close the connection without assuming anything about it."""
268 if self.file is not None:
269 self.file.close()
270 if self.sock is not None:
Antoine Pitroud89824b2012-11-23 20:04:45 +0100271 try:
272 self.sock.shutdown(socket.SHUT_RDWR)
273 except socket.error as e:
274 # The server might already have closed the connection
275 if e.errno != errno.ENOTCONN:
276 raise
277 finally:
278 self.sock.close()
Giampaolo Rodolà95bcb932011-02-25 22:28:24 +0000279 self.file = self.sock = None
280
Tim Peters2344fae2001-01-15 00:50:52 +0000281 #__del__ = quit
Guido van Rossum484772d1998-04-06 18:27:27 +0000282
Guido van Rossum484772d1998-04-06 18:27:27 +0000283
Tim Peters2344fae2001-01-15 00:50:52 +0000284 # optional commands:
Guido van Rossum03774bb1998-04-09 13:50:55 +0000285
Tim Peters2344fae2001-01-15 00:50:52 +0000286 def rpop(self, user):
287 """Not sure what this does."""
288 return self._shortcmd('RPOP %s' % user)
Guido van Rossum03774bb1998-04-09 13:50:55 +0000289
Guido van Rossum03774bb1998-04-09 13:50:55 +0000290
Christian Heimesd3956292008-11-05 19:48:27 +0000291 timestamp = re.compile(br'\+OK.*(<[^>]+>)')
Guido van Rossum03774bb1998-04-09 13:50:55 +0000292
Christian Heimesd3956292008-11-05 19:48:27 +0000293 def apop(self, user, password):
Tim Peters2344fae2001-01-15 00:50:52 +0000294 """Authorisation
Guido van Rossum03774bb1998-04-09 13:50:55 +0000295
Tim Peters2344fae2001-01-15 00:50:52 +0000296 - only possible if server has supplied a timestamp in initial greeting.
Guido van Rossum03774bb1998-04-09 13:50:55 +0000297
Tim Peters2344fae2001-01-15 00:50:52 +0000298 Args:
Christian Heimesd3956292008-11-05 19:48:27 +0000299 user - mailbox user;
300 password - mailbox password.
Guido van Rossum03774bb1998-04-09 13:50:55 +0000301
Tim Peters2344fae2001-01-15 00:50:52 +0000302 NB: mailbox is locked by server from here to 'quit()'
303 """
Mark Dickinsonea1158f2009-08-06 16:06:25 +0000304 secret = bytes(password, self.encoding)
Moshe Zadkaccc2e3d2001-01-19 19:56:27 +0000305 m = self.timestamp.match(self.welcome)
306 if not m:
Tim Peters2344fae2001-01-15 00:50:52 +0000307 raise error_proto('-ERR APOP not supported by server')
Thomas Wouters477c8d52006-05-27 19:21:47 +0000308 import hashlib
Christian Heimesd3956292008-11-05 19:48:27 +0000309 digest = m.group(1)+secret
310 digest = hashlib.md5(digest).hexdigest()
Tim Peters2344fae2001-01-15 00:50:52 +0000311 return self._shortcmd('APOP %s %s' % (user, digest))
Guido van Rossum03774bb1998-04-09 13:50:55 +0000312
Guido van Rossum03774bb1998-04-09 13:50:55 +0000313
Tim Peters2344fae2001-01-15 00:50:52 +0000314 def top(self, which, howmuch):
315 """Retrieve message header of message number 'which'
316 and first 'howmuch' lines of message body.
Guido van Rossum03774bb1998-04-09 13:50:55 +0000317
Tim Peters2344fae2001-01-15 00:50:52 +0000318 Result is in form ['response', ['line', ...], octets].
319 """
320 return self._longcmd('TOP %s %s' % (which, howmuch))
Guido van Rossum03774bb1998-04-09 13:50:55 +0000321
Guido van Rossum03774bb1998-04-09 13:50:55 +0000322
Tim Peters2344fae2001-01-15 00:50:52 +0000323 def uidl(self, which=None):
324 """Return message digest (unique id) list.
Guido van Rossum03774bb1998-04-09 13:50:55 +0000325
Tim Peters2344fae2001-01-15 00:50:52 +0000326 If 'which', result contains unique id for that message
327 in the form 'response mesgnum uid', otherwise result is
328 the list ['response', ['mesgnum uid', ...], octets]
329 """
Raymond Hettinger16e3c422002-06-01 16:07:16 +0000330 if which is not None:
Tim Peters2344fae2001-01-15 00:50:52 +0000331 return self._shortcmd('UIDL %s' % which)
332 return self._longcmd('UIDL')
Guido van Rossum03774bb1998-04-09 13:50:55 +0000333
Antoine Pitrou25cee192012-11-23 20:07:39 +0100334
335 def capa(self):
336 """Return server capabilities (RFC 2449) as a dictionary
337 >>> c=poplib.POP3('localhost')
338 >>> c.capa()
339 {'IMPLEMENTATION': ['Cyrus', 'POP3', 'server', 'v2.2.12'],
340 'TOP': [], 'LOGIN-DELAY': ['0'], 'AUTH-RESP-CODE': [],
341 'EXPIRE': ['NEVER'], 'USER': [], 'STLS': [], 'PIPELINING': [],
342 'UIDL': [], 'RESP-CODES': []}
343 >>>
344
345 Really, according to RFC 2449, the cyrus folks should avoid
346 having the implementation splitted into multiple arguments...
347 """
348 def _parsecap(line):
349 lst = line.decode('ascii').split()
350 return lst[0], lst[1:]
351
352 caps = {}
353 try:
354 resp = self._longcmd('CAPA')
355 rawcaps = resp[1]
356 for capline in rawcaps:
357 capnm, capargs = _parsecap(capline)
358 caps[capnm] = capargs
359 except error_proto as _err:
360 raise error_proto('-ERR CAPA not supported by server')
361 return caps
362
Antoine Pitrou8618d742012-11-23 20:13:48 +0100363
364 def stls(self, context=None):
365 """Start a TLS session on the active connection as specified in RFC 2595.
366
367 context - a ssl.SSLContext
368 """
369 if not HAVE_SSL:
370 raise error_proto('-ERR TLS support missing')
371 if self._tls_established:
372 raise error_proto('-ERR TLS session already established')
373 caps = self.capa()
374 if not 'STLS' in caps:
375 raise error_proto('-ERR STLS not supported by server')
376 if context is None:
377 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
378 context.options |= ssl.OP_NO_SSLv2
379 resp = self._shortcmd('STLS')
380 self.sock = context.wrap_socket(self.sock)
381 self.file = self.sock.makefile('rb')
382 self._tls_established = True
383 return resp
384
385
386if HAVE_SSL:
Martin v. Löwis48440b72003-10-31 12:52:35 +0000387
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000388 class POP3_SSL(POP3):
389 """POP3 client class over SSL connection
Martin v. Löwis48440b72003-10-31 12:52:35 +0000390
Antoine Pitrou8618d742012-11-23 20:13:48 +0100391 Instantiate with: POP3_SSL(hostname, port=995, keyfile=None, certfile=None,
392 context=None)
Martin v. Löwis48440b72003-10-31 12:52:35 +0000393
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000394 hostname - the hostname of the pop3 over ssl server
395 port - port number
396 keyfile - PEM formatted file that countains your private key
397 certfile - PEM formatted certificate chain file
Antoine Pitrou8618d742012-11-23 20:13:48 +0100398 context - a ssl.SSLContext
Martin v. Löwis48440b72003-10-31 12:52:35 +0000399
Christian Heimesd3956292008-11-05 19:48:27 +0000400 See the methods of the parent class POP3 for more documentation.
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000401 """
Martin v. Löwis48440b72003-10-31 12:52:35 +0000402
Giampaolo Rodolà42382fe2010-08-17 16:09:53 +0000403 def __init__(self, host, port=POP3_SSL_PORT, keyfile=None, certfile=None,
404 timeout=socket._GLOBAL_DEFAULT_TIMEOUT, context=None):
405 if context is not None and keyfile is not None:
406 raise ValueError("context and keyfile arguments are mutually "
407 "exclusive")
408 if context is not None and certfile is not None:
409 raise ValueError("context and certfile arguments are mutually "
410 "exclusive")
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000411 self.keyfile = keyfile
412 self.certfile = certfile
Giampaolo Rodolà42382fe2010-08-17 16:09:53 +0000413 self.context = context
Christian Heimesd3956292008-11-05 19:48:27 +0000414 POP3.__init__(self, host, port, timeout)
Martin v. Löwis48440b72003-10-31 12:52:35 +0000415
Christian Heimesd3956292008-11-05 19:48:27 +0000416 def _create_socket(self, timeout):
417 sock = POP3._create_socket(self, timeout)
Giampaolo Rodolà42382fe2010-08-17 16:09:53 +0000418 if self.context is not None:
419 sock = self.context.wrap_socket(sock)
420 else:
421 sock = ssl.wrap_socket(sock, self.keyfile, self.certfile)
422 return sock
Martin v. Löwis48440b72003-10-31 12:52:35 +0000423
Antoine Pitrou8618d742012-11-23 20:13:48 +0100424 def stls(self, keyfile=None, certfile=None, context=None):
425 """The method unconditionally raises an exception since the
426 STLS command doesn't make any sense on an already established
427 SSL/TLS session.
428 """
429 raise error_proto('-ERR TLS session already established')
430
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000431 __all__.append("POP3_SSL")
Guido van Rossum03774bb1998-04-09 13:50:55 +0000432
Guido van Rossum484772d1998-04-06 18:27:27 +0000433if __name__ == "__main__":
Eric S. Raymond341f9292001-02-09 06:56:56 +0000434 import sys
435 a = POP3(sys.argv[1])
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000436 print(a.getwelcome())
Eric S. Raymond341f9292001-02-09 06:56:56 +0000437 a.user(sys.argv[2])
438 a.pass_(sys.argv[3])
Tim Peters2344fae2001-01-15 00:50:52 +0000439 a.list()
440 (numMsgs, totalSize) = a.stat()
441 for i in range(1, numMsgs + 1):
442 (header, msg, octets) = a.retr(i)
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000443 print("Message %d:" % i)
Tim Peters2344fae2001-01-15 00:50:52 +0000444 for line in msg:
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000445 print(' ' + line)
446 print('-----------------------')
Tim Peters2344fae2001-01-15 00:50:52 +0000447 a.quit()