blob: 1224eacbefc6143cbf4c46a8743a613b6f1f5372 [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
Brett Cannoncd171c82013-07-04 17:43:24 -040023except ImportError:
Antoine Pitrou8618d742012-11-23 20:13:48 +010024 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
Georg Brandl7e27abb2013-10-27 07:23:53 +010043# maximal line length when calling readline(). This is to prevent
Berker Peksagf23530f2014-10-19 18:04:38 +030044# reading arbitrary length lines. RFC 1939 limits POP3 line length to
Georg Brandl7e27abb2013-10-27 07:23:53 +010045# 512 characters, including CRLF. We have selected 2048 just to be on
46# the safe side.
47_MAXLINE = 2048
48
Guido van Rossum484772d1998-04-06 18:27:27 +000049
50class POP3:
Guido van Rossum03774bb1998-04-09 13:50:55 +000051
Tim Peters2344fae2001-01-15 00:50:52 +000052 """This class supports both the minimal and optional command sets.
53 Arguments can be strings or integers (where appropriate)
54 (e.g.: retr(1) and retr('1') both work equally well.
Guido van Rossum03774bb1998-04-09 13:50:55 +000055
Tim Peters2344fae2001-01-15 00:50:52 +000056 Minimal Command Set:
57 USER name user(name)
58 PASS string pass_(string)
59 STAT stat()
60 LIST [msg] list(msg = None)
61 RETR msg retr(msg)
62 DELE msg dele(msg)
63 NOOP noop()
64 RSET rset()
65 QUIT quit()
Guido van Rossum03774bb1998-04-09 13:50:55 +000066
Tim Peters2344fae2001-01-15 00:50:52 +000067 Optional Commands (some servers support these):
68 RPOP name rpop(name)
69 APOP name digest apop(name, digest)
70 TOP msg n top(msg, n)
71 UIDL [msg] uidl(msg = None)
Antoine Pitrou25cee192012-11-23 20:07:39 +010072 CAPA capa()
Antoine Pitrou8618d742012-11-23 20:13:48 +010073 STLS stls()
Guido van Rossum03774bb1998-04-09 13:50:55 +000074
Tim Peters2344fae2001-01-15 00:50:52 +000075 Raises one exception: 'error_proto'.
Guido van Rossum03774bb1998-04-09 13:50:55 +000076
Tim Peters2344fae2001-01-15 00:50:52 +000077 Instantiate with:
78 POP3(hostname, port=110)
Guido van Rossum03774bb1998-04-09 13:50:55 +000079
Tim Peters2344fae2001-01-15 00:50:52 +000080 NB: the POP protocol locks the mailbox from user
81 authorization until QUIT, so be sure to get in, suck
82 the messages, and quit, each time you access the
83 mailbox.
Guido van Rossum03774bb1998-04-09 13:50:55 +000084
Tim Peters2344fae2001-01-15 00:50:52 +000085 POP is a line-based protocol, which means large mail
86 messages consume lots of python cycles reading them
87 line-by-line.
Guido van Rossum03774bb1998-04-09 13:50:55 +000088
Tim Peters2344fae2001-01-15 00:50:52 +000089 If it's available on your mail server, use IMAP4
90 instead, it doesn't suffer from the two problems
91 above.
92 """
Guido van Rossum03774bb1998-04-09 13:50:55 +000093
Christian Heimesd3956292008-11-05 19:48:27 +000094 encoding = 'UTF-8'
Guido van Rossum03774bb1998-04-09 13:50:55 +000095
Georg Brandlf78e02b2008-06-10 17:40:04 +000096 def __init__(self, host, port=POP3_PORT,
97 timeout=socket._GLOBAL_DEFAULT_TIMEOUT):
Martin v. Löwis4eb59402001-07-26 13:37:33 +000098 self.host = host
99 self.port = port
Antoine Pitrou8618d742012-11-23 20:13:48 +0100100 self._tls_established = False
Christian Heimesd3956292008-11-05 19:48:27 +0000101 self.sock = self._create_socket(timeout)
Martin v. Löwis4eb59402001-07-26 13:37:33 +0000102 self.file = self.sock.makefile('rb')
103 self._debugging = 0
104 self.welcome = self._getresp()
Guido van Rossum484772d1998-04-06 18:27:27 +0000105
Christian Heimesd3956292008-11-05 19:48:27 +0000106 def _create_socket(self, timeout):
107 return socket.create_connection((self.host, self.port), timeout)
Guido van Rossum03774bb1998-04-09 13:50:55 +0000108
Tim Peters2344fae2001-01-15 00:50:52 +0000109 def _putline(self, line):
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000110 if self._debugging > 1: print('*put*', repr(line))
Christian Heimesd3956292008-11-05 19:48:27 +0000111 self.sock.sendall(line + CRLF)
Guido van Rossum03774bb1998-04-09 13:50:55 +0000112
Guido van Rossum484772d1998-04-06 18:27:27 +0000113
Tim Peters2344fae2001-01-15 00:50:52 +0000114 # Internal: send one command to the server (through _putline())
Guido van Rossum03774bb1998-04-09 13:50:55 +0000115
Tim Peters2344fae2001-01-15 00:50:52 +0000116 def _putcmd(self, line):
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000117 if self._debugging: print('*cmd*', repr(line))
Christian Heimesd3956292008-11-05 19:48:27 +0000118 line = bytes(line, self.encoding)
Tim Peters2344fae2001-01-15 00:50:52 +0000119 self._putline(line)
Guido van Rossum484772d1998-04-06 18:27:27 +0000120
Guido van Rossum03774bb1998-04-09 13:50:55 +0000121
Tim Peters2344fae2001-01-15 00:50:52 +0000122 # Internal: return one line from the server, stripping CRLF.
123 # This is where all the CPU time of this module is consumed.
124 # Raise error_proto('-ERR EOF') if the connection is closed.
Guido van Rossum03774bb1998-04-09 13:50:55 +0000125
Tim Peters2344fae2001-01-15 00:50:52 +0000126 def _getline(self):
Georg Brandl7e27abb2013-10-27 07:23:53 +0100127 line = self.file.readline(_MAXLINE + 1)
128 if len(line) > _MAXLINE:
129 raise error_proto('line too long')
130
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000131 if self._debugging > 1: print('*get*', repr(line))
Tim Peters2344fae2001-01-15 00:50:52 +0000132 if not line: raise error_proto('-ERR EOF')
133 octets = len(line)
134 # server can send any combination of CR & LF
135 # however, 'readline()' returns lines ending in LF
136 # so only possibilities are ...LF, ...CRLF, CR...LF
137 if line[-2:] == CRLF:
138 return line[:-2], octets
Serhiy Storchaka74a49ac2015-03-20 16:46:19 +0200139 if line[:1] == CR:
Tim Peters2344fae2001-01-15 00:50:52 +0000140 return line[1:-1], octets
141 return line[:-1], octets
Guido van Rossum03774bb1998-04-09 13:50:55 +0000142
Guido van Rossum484772d1998-04-06 18:27:27 +0000143
Tim Peters2344fae2001-01-15 00:50:52 +0000144 # Internal: get a response from the server.
145 # Raise 'error_proto' if the response doesn't start with '+'.
Guido van Rossum03774bb1998-04-09 13:50:55 +0000146
Tim Peters2344fae2001-01-15 00:50:52 +0000147 def _getresp(self):
148 resp, o = self._getline()
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000149 if self._debugging > 1: print('*resp*', repr(resp))
Christian Heimesd3956292008-11-05 19:48:27 +0000150 if not resp.startswith(b'+'):
Tim Peters2344fae2001-01-15 00:50:52 +0000151 raise error_proto(resp)
152 return resp
Guido van Rossum484772d1998-04-06 18:27:27 +0000153
Guido van Rossum03774bb1998-04-09 13:50:55 +0000154
Tim Peters2344fae2001-01-15 00:50:52 +0000155 # Internal: get a response plus following text from the server.
Guido van Rossum03774bb1998-04-09 13:50:55 +0000156
Tim Peters2344fae2001-01-15 00:50:52 +0000157 def _getlongresp(self):
158 resp = self._getresp()
159 list = []; octets = 0
160 line, o = self._getline()
Guido van Rossum0ec34772007-09-10 00:27:13 +0000161 while line != b'.':
Christian Heimesd3956292008-11-05 19:48:27 +0000162 if line.startswith(b'..'):
Tim Peters2344fae2001-01-15 00:50:52 +0000163 o = o-1
164 line = line[1:]
165 octets = octets + o
166 list.append(line)
167 line, o = self._getline()
168 return resp, list, octets
Guido van Rossum03774bb1998-04-09 13:50:55 +0000169
Guido van Rossum484772d1998-04-06 18:27:27 +0000170
Tim Peters2344fae2001-01-15 00:50:52 +0000171 # Internal: send a command and get the response
Guido van Rossum03774bb1998-04-09 13:50:55 +0000172
Tim Peters2344fae2001-01-15 00:50:52 +0000173 def _shortcmd(self, line):
174 self._putcmd(line)
175 return self._getresp()
Guido van Rossum484772d1998-04-06 18:27:27 +0000176
Guido van Rossum03774bb1998-04-09 13:50:55 +0000177
Tim Peters2344fae2001-01-15 00:50:52 +0000178 # Internal: send a command and get the response plus following text
Guido van Rossum03774bb1998-04-09 13:50:55 +0000179
Tim Peters2344fae2001-01-15 00:50:52 +0000180 def _longcmd(self, line):
181 self._putcmd(line)
182 return self._getlongresp()
Guido van Rossum484772d1998-04-06 18:27:27 +0000183
Guido van Rossum03774bb1998-04-09 13:50:55 +0000184
Tim Peters2344fae2001-01-15 00:50:52 +0000185 # These can be useful:
186
187 def getwelcome(self):
188 return self.welcome
189
190
191 def set_debuglevel(self, level):
192 self._debugging = level
193
194
195 # Here are all the POP commands:
196
197 def user(self, user):
198 """Send user name, return response
Guido van Rossum484772d1998-04-06 18:27:27 +0000199
Tim Peters2344fae2001-01-15 00:50:52 +0000200 (should indicate password required).
201 """
202 return self._shortcmd('USER %s' % user)
Guido van Rossum484772d1998-04-06 18:27:27 +0000203
Guido van Rossum03774bb1998-04-09 13:50:55 +0000204
Tim Peters2344fae2001-01-15 00:50:52 +0000205 def pass_(self, pswd):
206 """Send password, return response
Guido van Rossum484772d1998-04-06 18:27:27 +0000207
Tim Peters2344fae2001-01-15 00:50:52 +0000208 (response includes message count, mailbox size).
Guido van Rossum03774bb1998-04-09 13:50:55 +0000209
Tim Peters2344fae2001-01-15 00:50:52 +0000210 NB: mailbox is locked by server from here to 'quit()'
211 """
212 return self._shortcmd('PASS %s' % pswd)
Guido van Rossum484772d1998-04-06 18:27:27 +0000213
Guido van Rossum03774bb1998-04-09 13:50:55 +0000214
Tim Peters2344fae2001-01-15 00:50:52 +0000215 def stat(self):
216 """Get mailbox status.
Guido van Rossum484772d1998-04-06 18:27:27 +0000217
Tim Peters2344fae2001-01-15 00:50:52 +0000218 Result is tuple of 2 ints (message count, mailbox size)
219 """
220 retval = self._shortcmd('STAT')
Eric S. Raymond341f9292001-02-09 06:56:56 +0000221 rets = retval.split()
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000222 if self._debugging: print('*stat*', repr(rets))
Eric S. Raymond341f9292001-02-09 06:56:56 +0000223 numMessages = int(rets[1])
224 sizeMessages = int(rets[2])
Tim Peters2344fae2001-01-15 00:50:52 +0000225 return (numMessages, sizeMessages)
Guido van Rossum03774bb1998-04-09 13:50:55 +0000226
Guido van Rossum03774bb1998-04-09 13:50:55 +0000227
Tim Peters2344fae2001-01-15 00:50:52 +0000228 def list(self, which=None):
229 """Request listing, return result.
Guido van Rossum484772d1998-04-06 18:27:27 +0000230
Tim Peters2344fae2001-01-15 00:50:52 +0000231 Result without a message number argument is in form
Georg Brandl2772c672005-08-05 21:01:58 +0000232 ['response', ['mesg_num octets', ...], octets].
Guido van Rossum484772d1998-04-06 18:27:27 +0000233
Tim Peters2344fae2001-01-15 00:50:52 +0000234 Result when a message number argument is given is a
235 single response: the "scan listing" for that message.
236 """
Raymond Hettinger16e3c422002-06-01 16:07:16 +0000237 if which is not None:
Tim Peters2344fae2001-01-15 00:50:52 +0000238 return self._shortcmd('LIST %s' % which)
239 return self._longcmd('LIST')
Guido van Rossum03774bb1998-04-09 13:50:55 +0000240
Guido van Rossum03774bb1998-04-09 13:50:55 +0000241
Tim Peters2344fae2001-01-15 00:50:52 +0000242 def retr(self, which):
243 """Retrieve whole message number 'which'.
Guido van Rossumf6ae7431998-09-02 14:42:02 +0000244
Tim Peters2344fae2001-01-15 00:50:52 +0000245 Result is in form ['response', ['line', ...], octets].
246 """
247 return self._longcmd('RETR %s' % which)
Guido van Rossum03774bb1998-04-09 13:50:55 +0000248
Guido van Rossum484772d1998-04-06 18:27:27 +0000249
Tim Peters2344fae2001-01-15 00:50:52 +0000250 def dele(self, which):
251 """Delete message number 'which'.
Guido van Rossum03774bb1998-04-09 13:50:55 +0000252
Tim Peters2344fae2001-01-15 00:50:52 +0000253 Result is 'response'.
254 """
255 return self._shortcmd('DELE %s' % which)
Guido van Rossum03774bb1998-04-09 13:50:55 +0000256
Guido van Rossum484772d1998-04-06 18:27:27 +0000257
Tim Peters2344fae2001-01-15 00:50:52 +0000258 def noop(self):
259 """Does nothing.
Guido van Rossum03774bb1998-04-09 13:50:55 +0000260
Tim Peters2344fae2001-01-15 00:50:52 +0000261 One supposes the response indicates the server is alive.
262 """
263 return self._shortcmd('NOOP')
Guido van Rossum03774bb1998-04-09 13:50:55 +0000264
Guido van Rossum484772d1998-04-06 18:27:27 +0000265
Tim Peters2344fae2001-01-15 00:50:52 +0000266 def rset(self):
Benjamin Petersona37cfc62008-05-26 13:48:34 +0000267 """Unmark all messages marked for deletion."""
Tim Peters2344fae2001-01-15 00:50:52 +0000268 return self._shortcmd('RSET')
Guido van Rossum484772d1998-04-06 18:27:27 +0000269
Guido van Rossum03774bb1998-04-09 13:50:55 +0000270
Tim Peters2344fae2001-01-15 00:50:52 +0000271 def quit(self):
272 """Signoff: commit changes on server, unlock mailbox, close connection."""
Giampaolo Rodolà95bcb932011-02-25 22:28:24 +0000273 resp = self._shortcmd('QUIT')
274 self.close()
Tim Peters2344fae2001-01-15 00:50:52 +0000275 return resp
Guido van Rossum484772d1998-04-06 18:27:27 +0000276
Giampaolo Rodolà95bcb932011-02-25 22:28:24 +0000277 def close(self):
278 """Close the connection without assuming anything about it."""
279 if self.file is not None:
280 self.file.close()
281 if self.sock is not None:
Antoine Pitroud89824b2012-11-23 20:04:45 +0100282 try:
283 self.sock.shutdown(socket.SHUT_RDWR)
Andrew Svetlov0832af62012-12-18 23:10:48 +0200284 except OSError as e:
Antoine Pitroud89824b2012-11-23 20:04:45 +0100285 # The server might already have closed the connection
286 if e.errno != errno.ENOTCONN:
287 raise
288 finally:
289 self.sock.close()
Giampaolo Rodolà95bcb932011-02-25 22:28:24 +0000290 self.file = self.sock = None
291
Tim Peters2344fae2001-01-15 00:50:52 +0000292 #__del__ = quit
Guido van Rossum484772d1998-04-06 18:27:27 +0000293
Guido van Rossum484772d1998-04-06 18:27:27 +0000294
Tim Peters2344fae2001-01-15 00:50:52 +0000295 # optional commands:
Guido van Rossum03774bb1998-04-09 13:50:55 +0000296
Tim Peters2344fae2001-01-15 00:50:52 +0000297 def rpop(self, user):
298 """Not sure what this does."""
299 return self._shortcmd('RPOP %s' % user)
Guido van Rossum03774bb1998-04-09 13:50:55 +0000300
Guido van Rossum03774bb1998-04-09 13:50:55 +0000301
Christian Heimesd3956292008-11-05 19:48:27 +0000302 timestamp = re.compile(br'\+OK.*(<[^>]+>)')
Guido van Rossum03774bb1998-04-09 13:50:55 +0000303
Christian Heimesd3956292008-11-05 19:48:27 +0000304 def apop(self, user, password):
Tim Peters2344fae2001-01-15 00:50:52 +0000305 """Authorisation
Guido van Rossum03774bb1998-04-09 13:50:55 +0000306
Tim Peters2344fae2001-01-15 00:50:52 +0000307 - only possible if server has supplied a timestamp in initial greeting.
Guido van Rossum03774bb1998-04-09 13:50:55 +0000308
Tim Peters2344fae2001-01-15 00:50:52 +0000309 Args:
Christian Heimesd3956292008-11-05 19:48:27 +0000310 user - mailbox user;
311 password - mailbox password.
Guido van Rossum03774bb1998-04-09 13:50:55 +0000312
Tim Peters2344fae2001-01-15 00:50:52 +0000313 NB: mailbox is locked by server from here to 'quit()'
314 """
Mark Dickinsonea1158f2009-08-06 16:06:25 +0000315 secret = bytes(password, self.encoding)
Moshe Zadkaccc2e3d2001-01-19 19:56:27 +0000316 m = self.timestamp.match(self.welcome)
317 if not m:
Tim Peters2344fae2001-01-15 00:50:52 +0000318 raise error_proto('-ERR APOP not supported by server')
Thomas Wouters477c8d52006-05-27 19:21:47 +0000319 import hashlib
Christian Heimesd3956292008-11-05 19:48:27 +0000320 digest = m.group(1)+secret
321 digest = hashlib.md5(digest).hexdigest()
Tim Peters2344fae2001-01-15 00:50:52 +0000322 return self._shortcmd('APOP %s %s' % (user, digest))
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 top(self, which, howmuch):
326 """Retrieve message header of message number 'which'
327 and first 'howmuch' lines of message body.
Guido van Rossum03774bb1998-04-09 13:50:55 +0000328
Tim Peters2344fae2001-01-15 00:50:52 +0000329 Result is in form ['response', ['line', ...], octets].
330 """
331 return self._longcmd('TOP %s %s' % (which, howmuch))
Guido van Rossum03774bb1998-04-09 13:50:55 +0000332
Guido van Rossum03774bb1998-04-09 13:50:55 +0000333
Tim Peters2344fae2001-01-15 00:50:52 +0000334 def uidl(self, which=None):
335 """Return message digest (unique id) list.
Guido van Rossum03774bb1998-04-09 13:50:55 +0000336
Tim Peters2344fae2001-01-15 00:50:52 +0000337 If 'which', result contains unique id for that message
338 in the form 'response mesgnum uid', otherwise result is
339 the list ['response', ['mesgnum uid', ...], octets]
340 """
Raymond Hettinger16e3c422002-06-01 16:07:16 +0000341 if which is not None:
Tim Peters2344fae2001-01-15 00:50:52 +0000342 return self._shortcmd('UIDL %s' % which)
343 return self._longcmd('UIDL')
Guido van Rossum03774bb1998-04-09 13:50:55 +0000344
Antoine Pitrou25cee192012-11-23 20:07:39 +0100345
346 def capa(self):
347 """Return server capabilities (RFC 2449) as a dictionary
348 >>> c=poplib.POP3('localhost')
349 >>> c.capa()
350 {'IMPLEMENTATION': ['Cyrus', 'POP3', 'server', 'v2.2.12'],
351 'TOP': [], 'LOGIN-DELAY': ['0'], 'AUTH-RESP-CODE': [],
352 'EXPIRE': ['NEVER'], 'USER': [], 'STLS': [], 'PIPELINING': [],
353 'UIDL': [], 'RESP-CODES': []}
354 >>>
355
356 Really, according to RFC 2449, the cyrus folks should avoid
Ezio Melotti9a3777e2013-08-17 15:53:55 +0300357 having the implementation split into multiple arguments...
Antoine Pitrou25cee192012-11-23 20:07:39 +0100358 """
359 def _parsecap(line):
360 lst = line.decode('ascii').split()
361 return lst[0], lst[1:]
362
363 caps = {}
364 try:
365 resp = self._longcmd('CAPA')
366 rawcaps = resp[1]
367 for capline in rawcaps:
368 capnm, capargs = _parsecap(capline)
369 caps[capnm] = capargs
370 except error_proto as _err:
371 raise error_proto('-ERR CAPA not supported by server')
372 return caps
373
Antoine Pitrou8618d742012-11-23 20:13:48 +0100374
375 def stls(self, context=None):
376 """Start a TLS session on the active connection as specified in RFC 2595.
377
378 context - a ssl.SSLContext
379 """
380 if not HAVE_SSL:
381 raise error_proto('-ERR TLS support missing')
382 if self._tls_established:
383 raise error_proto('-ERR TLS session already established')
384 caps = self.capa()
385 if not 'STLS' in caps:
386 raise error_proto('-ERR STLS not supported by server')
387 if context is None:
Christian Heimes67986f92013-11-23 22:43:47 +0100388 context = ssl._create_stdlib_context()
Antoine Pitrou8618d742012-11-23 20:13:48 +0100389 resp = self._shortcmd('STLS')
Christian Heimes1bc70682013-12-02 20:10:50 +0100390 self.sock = context.wrap_socket(self.sock,
Benjamin Peterson7243b572014-11-23 17:04:34 -0600391 server_hostname=self.host)
Antoine Pitrou8618d742012-11-23 20:13:48 +0100392 self.file = self.sock.makefile('rb')
393 self._tls_established = True
394 return resp
395
396
397if HAVE_SSL:
Martin v. Löwis48440b72003-10-31 12:52:35 +0000398
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000399 class POP3_SSL(POP3):
400 """POP3 client class over SSL connection
Martin v. Löwis48440b72003-10-31 12:52:35 +0000401
Antoine Pitrou8618d742012-11-23 20:13:48 +0100402 Instantiate with: POP3_SSL(hostname, port=995, keyfile=None, certfile=None,
403 context=None)
Martin v. Löwis48440b72003-10-31 12:52:35 +0000404
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000405 hostname - the hostname of the pop3 over ssl server
406 port - port number
Ezio Melotti30b9d5d2013-08-17 15:50:46 +0300407 keyfile - PEM formatted file that contains your private key
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000408 certfile - PEM formatted certificate chain file
Antoine Pitrou8618d742012-11-23 20:13:48 +0100409 context - a ssl.SSLContext
Martin v. Löwis48440b72003-10-31 12:52:35 +0000410
Christian Heimesd3956292008-11-05 19:48:27 +0000411 See the methods of the parent class POP3 for more documentation.
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000412 """
Martin v. Löwis48440b72003-10-31 12:52:35 +0000413
Giampaolo Rodolà42382fe2010-08-17 16:09:53 +0000414 def __init__(self, host, port=POP3_SSL_PORT, keyfile=None, certfile=None,
415 timeout=socket._GLOBAL_DEFAULT_TIMEOUT, context=None):
416 if context is not None and keyfile is not None:
417 raise ValueError("context and keyfile arguments are mutually "
418 "exclusive")
419 if context is not None and certfile is not None:
420 raise ValueError("context and certfile arguments are mutually "
421 "exclusive")
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000422 self.keyfile = keyfile
423 self.certfile = certfile
Christian Heimes67986f92013-11-23 22:43:47 +0100424 if context is None:
425 context = ssl._create_stdlib_context(certfile=certfile,
426 keyfile=keyfile)
Giampaolo Rodolà42382fe2010-08-17 16:09:53 +0000427 self.context = context
Christian Heimesd3956292008-11-05 19:48:27 +0000428 POP3.__init__(self, host, port, timeout)
Martin v. Löwis48440b72003-10-31 12:52:35 +0000429
Christian Heimesd3956292008-11-05 19:48:27 +0000430 def _create_socket(self, timeout):
431 sock = POP3._create_socket(self, timeout)
Christian Heimes1bc70682013-12-02 20:10:50 +0100432 sock = self.context.wrap_socket(sock,
Benjamin Peterson7243b572014-11-23 17:04:34 -0600433 server_hostname=self.host)
Giampaolo Rodolà42382fe2010-08-17 16:09:53 +0000434 return sock
Martin v. Löwis48440b72003-10-31 12:52:35 +0000435
Antoine Pitrou8618d742012-11-23 20:13:48 +0100436 def stls(self, keyfile=None, certfile=None, context=None):
437 """The method unconditionally raises an exception since the
438 STLS command doesn't make any sense on an already established
439 SSL/TLS session.
440 """
441 raise error_proto('-ERR TLS session already established')
442
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000443 __all__.append("POP3_SSL")
Guido van Rossum03774bb1998-04-09 13:50:55 +0000444
Guido van Rossum484772d1998-04-06 18:27:27 +0000445if __name__ == "__main__":
Eric S. Raymond341f9292001-02-09 06:56:56 +0000446 import sys
447 a = POP3(sys.argv[1])
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000448 print(a.getwelcome())
Eric S. Raymond341f9292001-02-09 06:56:56 +0000449 a.user(sys.argv[2])
450 a.pass_(sys.argv[3])
Tim Peters2344fae2001-01-15 00:50:52 +0000451 a.list()
452 (numMsgs, totalSize) = a.stat()
453 for i in range(1, numMsgs + 1):
454 (header, msg, octets) = a.retr(i)
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000455 print("Message %d:" % i)
Tim Peters2344fae2001-01-15 00:50:52 +0000456 for line in msg:
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000457 print(' ' + line)
458 print('-----------------------')
Tim Peters2344fae2001-01-15 00:50:52 +0000459 a.quit()