blob: b50b0c79dba273a86d770ab288f2dc3a6f675ac2 [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
Thomas Wouters47b49bf2007-08-30 22:15:33 +000018__all__ = ["POP3","error_proto"]
Skip Montanaroc62c81e2001-02-12 02:00:42 +000019
Guido van Rossum484772d1998-04-06 18:27:27 +000020# Exception raised when an error or invalid response is received:
Guido van Rossum03774bb1998-04-09 13:50:55 +000021
22class error_proto(Exception): pass
Guido van Rossum484772d1998-04-06 18:27:27 +000023
24# Standard Port
25POP3_PORT = 110
26
Martin v. Löwis48440b72003-10-31 12:52:35 +000027# POP SSL PORT
28POP3_SSL_PORT = 995
29
Guido van Rossum03774bb1998-04-09 13:50:55 +000030# Line terminators (we always output CRLF, but accept any of CRLF, LFCR, LF)
Jeremy Hylton88d06a72007-08-29 19:08:30 +000031CR = b'\r'
32LF = b'\n'
Guido van Rossum03774bb1998-04-09 13:50:55 +000033CRLF = CR+LF
Guido van Rossum484772d1998-04-06 18:27:27 +000034
35
36class POP3:
Guido van Rossum03774bb1998-04-09 13:50:55 +000037
Tim Peters2344fae2001-01-15 00:50:52 +000038 """This class supports both the minimal and optional command sets.
39 Arguments can be strings or integers (where appropriate)
40 (e.g.: retr(1) and retr('1') both work equally well.
Guido van Rossum03774bb1998-04-09 13:50:55 +000041
Tim Peters2344fae2001-01-15 00:50:52 +000042 Minimal Command Set:
43 USER name user(name)
44 PASS string pass_(string)
45 STAT stat()
46 LIST [msg] list(msg = None)
47 RETR msg retr(msg)
48 DELE msg dele(msg)
49 NOOP noop()
50 RSET rset()
51 QUIT quit()
Guido van Rossum03774bb1998-04-09 13:50:55 +000052
Tim Peters2344fae2001-01-15 00:50:52 +000053 Optional Commands (some servers support these):
54 RPOP name rpop(name)
55 APOP name digest apop(name, digest)
56 TOP msg n top(msg, n)
57 UIDL [msg] uidl(msg = None)
Guido van Rossum03774bb1998-04-09 13:50:55 +000058
Tim Peters2344fae2001-01-15 00:50:52 +000059 Raises one exception: 'error_proto'.
Guido van Rossum03774bb1998-04-09 13:50:55 +000060
Tim Peters2344fae2001-01-15 00:50:52 +000061 Instantiate with:
62 POP3(hostname, port=110)
Guido van Rossum03774bb1998-04-09 13:50:55 +000063
Tim Peters2344fae2001-01-15 00:50:52 +000064 NB: the POP protocol locks the mailbox from user
65 authorization until QUIT, so be sure to get in, suck
66 the messages, and quit, each time you access the
67 mailbox.
Guido van Rossum03774bb1998-04-09 13:50:55 +000068
Tim Peters2344fae2001-01-15 00:50:52 +000069 POP is a line-based protocol, which means large mail
70 messages consume lots of python cycles reading them
71 line-by-line.
Guido van Rossum03774bb1998-04-09 13:50:55 +000072
Tim Peters2344fae2001-01-15 00:50:52 +000073 If it's available on your mail server, use IMAP4
74 instead, it doesn't suffer from the two problems
75 above.
76 """
Guido van Rossum03774bb1998-04-09 13:50:55 +000077
78
Guido van Rossumd8faa362007-04-27 19:54:29 +000079 def __init__(self, host, port=POP3_PORT, timeout=None):
Martin v. Löwis4eb59402001-07-26 13:37:33 +000080 self.host = host
81 self.port = port
Guido van Rossumd8faa362007-04-27 19:54:29 +000082 self.sock = socket.create_connection((host, port), timeout)
Martin v. Löwis4eb59402001-07-26 13:37:33 +000083 self.file = self.sock.makefile('rb')
84 self._debugging = 0
85 self.welcome = self._getresp()
Guido van Rossum484772d1998-04-06 18:27:27 +000086
Guido van Rossum03774bb1998-04-09 13:50:55 +000087
Tim Peters2344fae2001-01-15 00:50:52 +000088 def _putline(self, line):
Guido van Rossumbe19ed72007-02-09 05:37:30 +000089 if self._debugging > 1: print('*put*', repr(line))
Martin v. Löwise12454f2002-02-16 23:06:19 +000090 self.sock.sendall('%s%s' % (line, CRLF))
Guido van Rossum03774bb1998-04-09 13:50:55 +000091
Guido van Rossum484772d1998-04-06 18:27:27 +000092
Tim Peters2344fae2001-01-15 00:50:52 +000093 # Internal: send one command to the server (through _putline())
Guido van Rossum03774bb1998-04-09 13:50:55 +000094
Tim Peters2344fae2001-01-15 00:50:52 +000095 def _putcmd(self, line):
Guido van Rossumbe19ed72007-02-09 05:37:30 +000096 if self._debugging: print('*cmd*', repr(line))
Tim Peters2344fae2001-01-15 00:50:52 +000097 self._putline(line)
Guido van Rossum484772d1998-04-06 18:27:27 +000098
Guido van Rossum03774bb1998-04-09 13:50:55 +000099
Tim Peters2344fae2001-01-15 00:50:52 +0000100 # Internal: return one line from the server, stripping CRLF.
101 # This is where all the CPU time of this module is consumed.
102 # Raise error_proto('-ERR EOF') if the connection is closed.
Guido van Rossum03774bb1998-04-09 13:50:55 +0000103
Tim Peters2344fae2001-01-15 00:50:52 +0000104 def _getline(self):
105 line = self.file.readline()
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000106 if self._debugging > 1: print('*get*', repr(line))
Tim Peters2344fae2001-01-15 00:50:52 +0000107 if not line: raise error_proto('-ERR EOF')
108 octets = len(line)
109 # server can send any combination of CR & LF
110 # however, 'readline()' returns lines ending in LF
111 # so only possibilities are ...LF, ...CRLF, CR...LF
112 if line[-2:] == CRLF:
113 return line[:-2], octets
114 if line[0] == CR:
115 return line[1:-1], octets
116 return line[:-1], octets
Guido van Rossum03774bb1998-04-09 13:50:55 +0000117
Guido van Rossum484772d1998-04-06 18:27:27 +0000118
Tim Peters2344fae2001-01-15 00:50:52 +0000119 # Internal: get a response from the server.
120 # Raise 'error_proto' if the response doesn't start with '+'.
Guido van Rossum03774bb1998-04-09 13:50:55 +0000121
Tim Peters2344fae2001-01-15 00:50:52 +0000122 def _getresp(self):
123 resp, o = self._getline()
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000124 if self._debugging > 1: print('*resp*', repr(resp))
Tim Peters2344fae2001-01-15 00:50:52 +0000125 c = resp[:1]
Collin Winterf86f2852007-07-23 00:24:10 +0000126 if c != b'+':
Tim Peters2344fae2001-01-15 00:50:52 +0000127 raise error_proto(resp)
128 return resp
Guido van Rossum484772d1998-04-06 18:27:27 +0000129
Guido van Rossum03774bb1998-04-09 13:50:55 +0000130
Tim Peters2344fae2001-01-15 00:50:52 +0000131 # Internal: get a response plus following text from the server.
Guido van Rossum03774bb1998-04-09 13:50:55 +0000132
Tim Peters2344fae2001-01-15 00:50:52 +0000133 def _getlongresp(self):
134 resp = self._getresp()
135 list = []; octets = 0
136 line, o = self._getline()
Guido van Rossum0ec34772007-09-10 00:27:13 +0000137 while line != b'.':
138 if line[:2] == b'..':
Tim Peters2344fae2001-01-15 00:50:52 +0000139 o = o-1
140 line = line[1:]
141 octets = octets + o
142 list.append(line)
143 line, o = self._getline()
144 return resp, list, octets
Guido van Rossum03774bb1998-04-09 13:50:55 +0000145
Guido van Rossum484772d1998-04-06 18:27:27 +0000146
Tim Peters2344fae2001-01-15 00:50:52 +0000147 # Internal: send a command and get the response
Guido van Rossum03774bb1998-04-09 13:50:55 +0000148
Tim Peters2344fae2001-01-15 00:50:52 +0000149 def _shortcmd(self, line):
150 self._putcmd(line)
151 return self._getresp()
Guido van Rossum484772d1998-04-06 18:27:27 +0000152
Guido van Rossum03774bb1998-04-09 13:50:55 +0000153
Tim Peters2344fae2001-01-15 00:50:52 +0000154 # Internal: send a command and get the response plus following text
Guido van Rossum03774bb1998-04-09 13:50:55 +0000155
Tim Peters2344fae2001-01-15 00:50:52 +0000156 def _longcmd(self, line):
157 self._putcmd(line)
158 return self._getlongresp()
Guido van Rossum484772d1998-04-06 18:27:27 +0000159
Guido van Rossum03774bb1998-04-09 13:50:55 +0000160
Tim Peters2344fae2001-01-15 00:50:52 +0000161 # These can be useful:
162
163 def getwelcome(self):
164 return self.welcome
165
166
167 def set_debuglevel(self, level):
168 self._debugging = level
169
170
171 # Here are all the POP commands:
172
173 def user(self, user):
174 """Send user name, return response
Guido van Rossum484772d1998-04-06 18:27:27 +0000175
Tim Peters2344fae2001-01-15 00:50:52 +0000176 (should indicate password required).
177 """
178 return self._shortcmd('USER %s' % user)
Guido van Rossum484772d1998-04-06 18:27:27 +0000179
Guido van Rossum03774bb1998-04-09 13:50:55 +0000180
Tim Peters2344fae2001-01-15 00:50:52 +0000181 def pass_(self, pswd):
182 """Send password, return response
Guido van Rossum484772d1998-04-06 18:27:27 +0000183
Tim Peters2344fae2001-01-15 00:50:52 +0000184 (response includes message count, mailbox size).
Guido van Rossum03774bb1998-04-09 13:50:55 +0000185
Tim Peters2344fae2001-01-15 00:50:52 +0000186 NB: mailbox is locked by server from here to 'quit()'
187 """
188 return self._shortcmd('PASS %s' % pswd)
Guido van Rossum484772d1998-04-06 18:27:27 +0000189
Guido van Rossum03774bb1998-04-09 13:50:55 +0000190
Tim Peters2344fae2001-01-15 00:50:52 +0000191 def stat(self):
192 """Get mailbox status.
Guido van Rossum484772d1998-04-06 18:27:27 +0000193
Tim Peters2344fae2001-01-15 00:50:52 +0000194 Result is tuple of 2 ints (message count, mailbox size)
195 """
196 retval = self._shortcmd('STAT')
Eric S. Raymond341f9292001-02-09 06:56:56 +0000197 rets = retval.split()
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000198 if self._debugging: print('*stat*', repr(rets))
Eric S. Raymond341f9292001-02-09 06:56:56 +0000199 numMessages = int(rets[1])
200 sizeMessages = int(rets[2])
Tim Peters2344fae2001-01-15 00:50:52 +0000201 return (numMessages, sizeMessages)
Guido van Rossum03774bb1998-04-09 13:50:55 +0000202
Guido van Rossum03774bb1998-04-09 13:50:55 +0000203
Tim Peters2344fae2001-01-15 00:50:52 +0000204 def list(self, which=None):
205 """Request listing, return result.
Guido van Rossum484772d1998-04-06 18:27:27 +0000206
Tim Peters2344fae2001-01-15 00:50:52 +0000207 Result without a message number argument is in form
Georg Brandl2772c672005-08-05 21:01:58 +0000208 ['response', ['mesg_num octets', ...], octets].
Guido van Rossum484772d1998-04-06 18:27:27 +0000209
Tim Peters2344fae2001-01-15 00:50:52 +0000210 Result when a message number argument is given is a
211 single response: the "scan listing" for that message.
212 """
Raymond Hettinger16e3c422002-06-01 16:07:16 +0000213 if which is not None:
Tim Peters2344fae2001-01-15 00:50:52 +0000214 return self._shortcmd('LIST %s' % which)
215 return self._longcmd('LIST')
Guido van Rossum03774bb1998-04-09 13:50:55 +0000216
Guido van Rossum03774bb1998-04-09 13:50:55 +0000217
Tim Peters2344fae2001-01-15 00:50:52 +0000218 def retr(self, which):
219 """Retrieve whole message number 'which'.
Guido van Rossumf6ae7431998-09-02 14:42:02 +0000220
Tim Peters2344fae2001-01-15 00:50:52 +0000221 Result is in form ['response', ['line', ...], octets].
222 """
223 return self._longcmd('RETR %s' % which)
Guido van Rossum03774bb1998-04-09 13:50:55 +0000224
Guido van Rossum484772d1998-04-06 18:27:27 +0000225
Tim Peters2344fae2001-01-15 00:50:52 +0000226 def dele(self, which):
227 """Delete message number 'which'.
Guido van Rossum03774bb1998-04-09 13:50:55 +0000228
Tim Peters2344fae2001-01-15 00:50:52 +0000229 Result is 'response'.
230 """
231 return self._shortcmd('DELE %s' % which)
Guido van Rossum03774bb1998-04-09 13:50:55 +0000232
Guido van Rossum484772d1998-04-06 18:27:27 +0000233
Tim Peters2344fae2001-01-15 00:50:52 +0000234 def noop(self):
235 """Does nothing.
Guido van Rossum03774bb1998-04-09 13:50:55 +0000236
Tim Peters2344fae2001-01-15 00:50:52 +0000237 One supposes the response indicates the server is alive.
238 """
239 return self._shortcmd('NOOP')
Guido van Rossum03774bb1998-04-09 13:50:55 +0000240
Guido van Rossum484772d1998-04-06 18:27:27 +0000241
Tim Peters2344fae2001-01-15 00:50:52 +0000242 def rset(self):
243 """Not sure what this does."""
244 return self._shortcmd('RSET')
Guido van Rossum484772d1998-04-06 18:27:27 +0000245
Guido van Rossum03774bb1998-04-09 13:50:55 +0000246
Tim Peters2344fae2001-01-15 00:50:52 +0000247 def quit(self):
248 """Signoff: commit changes on server, unlock mailbox, close connection."""
249 try:
250 resp = self._shortcmd('QUIT')
Guido van Rossumb940e112007-01-10 16:19:56 +0000251 except error_proto as val:
Tim Peters2344fae2001-01-15 00:50:52 +0000252 resp = val
253 self.file.close()
254 self.sock.close()
255 del self.file, self.sock
256 return resp
Guido van Rossum484772d1998-04-06 18:27:27 +0000257
Tim Peters2344fae2001-01-15 00:50:52 +0000258 #__del__ = quit
Guido van Rossum484772d1998-04-06 18:27:27 +0000259
Guido van Rossum484772d1998-04-06 18:27:27 +0000260
Tim Peters2344fae2001-01-15 00:50:52 +0000261 # optional commands:
Guido van Rossum03774bb1998-04-09 13:50:55 +0000262
Tim Peters2344fae2001-01-15 00:50:52 +0000263 def rpop(self, user):
264 """Not sure what this does."""
265 return self._shortcmd('RPOP %s' % user)
Guido van Rossum03774bb1998-04-09 13:50:55 +0000266
Guido van Rossum03774bb1998-04-09 13:50:55 +0000267
Moshe Zadkaccc2e3d2001-01-19 19:56:27 +0000268 timestamp = re.compile(r'\+OK.*(<[^>]+>)')
Guido van Rossum03774bb1998-04-09 13:50:55 +0000269
Tim Peters2344fae2001-01-15 00:50:52 +0000270 def apop(self, user, secret):
271 """Authorisation
Guido van Rossum03774bb1998-04-09 13:50:55 +0000272
Tim Peters2344fae2001-01-15 00:50:52 +0000273 - only possible if server has supplied a timestamp in initial greeting.
Guido van Rossum03774bb1998-04-09 13:50:55 +0000274
Tim Peters2344fae2001-01-15 00:50:52 +0000275 Args:
276 user - mailbox user;
277 secret - secret shared between client and server.
Guido van Rossum03774bb1998-04-09 13:50:55 +0000278
Tim Peters2344fae2001-01-15 00:50:52 +0000279 NB: mailbox is locked by server from here to 'quit()'
280 """
Moshe Zadkaccc2e3d2001-01-19 19:56:27 +0000281 m = self.timestamp.match(self.welcome)
282 if not m:
Tim Peters2344fae2001-01-15 00:50:52 +0000283 raise error_proto('-ERR APOP not supported by server')
Thomas Wouters477c8d52006-05-27 19:21:47 +0000284 import hashlib
285 digest = hashlib.md5(m.group(1)+secret).digest()
Eric S. Raymond341f9292001-02-09 06:56:56 +0000286 digest = ''.join(map(lambda x:'%02x'%ord(x), digest))
Tim Peters2344fae2001-01-15 00:50:52 +0000287 return self._shortcmd('APOP %s %s' % (user, digest))
Guido van Rossum03774bb1998-04-09 13:50:55 +0000288
Guido van Rossum03774bb1998-04-09 13:50:55 +0000289
Tim Peters2344fae2001-01-15 00:50:52 +0000290 def top(self, which, howmuch):
291 """Retrieve message header of message number 'which'
292 and first 'howmuch' lines of message body.
Guido van Rossum03774bb1998-04-09 13:50:55 +0000293
Tim Peters2344fae2001-01-15 00:50:52 +0000294 Result is in form ['response', ['line', ...], octets].
295 """
296 return self._longcmd('TOP %s %s' % (which, howmuch))
Guido van Rossum03774bb1998-04-09 13:50:55 +0000297
Guido van Rossum03774bb1998-04-09 13:50:55 +0000298
Tim Peters2344fae2001-01-15 00:50:52 +0000299 def uidl(self, which=None):
300 """Return message digest (unique id) list.
Guido van Rossum03774bb1998-04-09 13:50:55 +0000301
Tim Peters2344fae2001-01-15 00:50:52 +0000302 If 'which', result contains unique id for that message
303 in the form 'response mesgnum uid', otherwise result is
304 the list ['response', ['mesgnum uid', ...], octets]
305 """
Raymond Hettinger16e3c422002-06-01 16:07:16 +0000306 if which is not None:
Tim Peters2344fae2001-01-15 00:50:52 +0000307 return self._shortcmd('UIDL %s' % which)
308 return self._longcmd('UIDL')
Guido van Rossum03774bb1998-04-09 13:50:55 +0000309
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000310try:
311 import ssl
312except ImportError:
313 pass
314else:
Martin v. Löwis48440b72003-10-31 12:52:35 +0000315
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000316 class POP3_SSL(POP3):
317 """POP3 client class over SSL connection
Martin v. Löwis48440b72003-10-31 12:52:35 +0000318
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000319 Instantiate with: POP3_SSL(hostname, port=995, keyfile=None, certfile=None)
Martin v. Löwis48440b72003-10-31 12:52:35 +0000320
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000321 hostname - the hostname of the pop3 over ssl server
322 port - port number
323 keyfile - PEM formatted file that countains your private key
324 certfile - PEM formatted certificate chain file
Martin v. Löwis48440b72003-10-31 12:52:35 +0000325
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000326 See the methods of the parent class POP3 for more documentation.
327 """
Martin v. Löwis48440b72003-10-31 12:52:35 +0000328
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000329 def __init__(self, host, port = POP3_SSL_PORT, keyfile = None, certfile = None):
330 self.host = host
331 self.port = port
332 self.keyfile = keyfile
333 self.certfile = certfile
334 self.buffer = ""
335 msg = "getaddrinfo returns an empty list"
336 self.sock = None
337 for res in socket.getaddrinfo(self.host, self.port, 0, socket.SOCK_STREAM):
338 af, socktype, proto, canonname, sa = res
339 try:
340 self.sock = socket.socket(af, socktype, proto)
341 self.sock.connect(sa)
342 except socket.error as msg:
343 if self.sock:
344 self.sock.close()
345 self.sock = None
346 continue
347 break
348 if not self.sock:
349 raise socket.error(msg)
350 self.file = self.sock.makefile('rb')
351 self.sslobj = ssl.sslsocket(self.sock, self.keyfile, self.certfile)
352 self._debugging = 0
353 self.welcome = self._getresp()
Martin v. Löwis48440b72003-10-31 12:52:35 +0000354
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000355 def _fillBuffer(self):
356 localbuf = self.sslobj.read()
357 if len(localbuf) == 0:
358 raise error_proto('-ERR EOF')
359 self.buffer += localbuf
360
361 def _getline(self):
362 line = ""
363 renewline = re.compile(r'.*?\n')
Martin v. Löwis48440b72003-10-31 12:52:35 +0000364 match = renewline.match(self.buffer)
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000365 while not match:
366 self._fillBuffer()
367 match = renewline.match(self.buffer)
368 line = match.group(0)
369 self.buffer = renewline.sub('' ,self.buffer, 1)
370 if self._debugging > 1: print('*get*', repr(line))
Martin v. Löwis48440b72003-10-31 12:52:35 +0000371
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000372 octets = len(line)
373 if line[-2:] == CRLF:
374 return line[:-2], octets
375 if line[0] == CR:
376 return line[1:-1], octets
377 return line[:-1], octets
Martin v. Löwis48440b72003-10-31 12:52:35 +0000378
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000379 def _putline(self, line):
380 if self._debugging > 1: print('*put*', repr(line))
381 line += CRLF
382 bytes = len(line)
383 while bytes > 0:
384 sent = self.sslobj.write(line)
385 if sent == bytes:
386 break # avoid copy
387 line = line[sent:]
388 bytes = bytes - sent
Martin v. Löwis48440b72003-10-31 12:52:35 +0000389
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000390 def quit(self):
391 """Signoff: commit changes on server, unlock mailbox, close connection."""
392 try:
393 resp = self._shortcmd('QUIT')
394 except error_proto as val:
395 resp = val
396 self.sock.close()
397 del self.sslobj, self.sock
398 return resp
Martin v. Löwis48440b72003-10-31 12:52:35 +0000399
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000400 __all__.append("POP3_SSL")
Guido van Rossum03774bb1998-04-09 13:50:55 +0000401
Guido van Rossum484772d1998-04-06 18:27:27 +0000402if __name__ == "__main__":
Eric S. Raymond341f9292001-02-09 06:56:56 +0000403 import sys
404 a = POP3(sys.argv[1])
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000405 print(a.getwelcome())
Eric S. Raymond341f9292001-02-09 06:56:56 +0000406 a.user(sys.argv[2])
407 a.pass_(sys.argv[3])
Tim Peters2344fae2001-01-15 00:50:52 +0000408 a.list()
409 (numMsgs, totalSize) = a.stat()
410 for i in range(1, numMsgs + 1):
411 (header, msg, octets) = a.retr(i)
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000412 print("Message %d:" % i)
Tim Peters2344fae2001-01-15 00:50:52 +0000413 for line in msg:
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000414 print(' ' + line)
415 print('-----------------------')
Tim Peters2344fae2001-01-15 00:50:52 +0000416 a.quit()