Commit 48440b7c authored by Martin v. Löwis's avatar Martin v. Löwis

Patch #: Add POP3 over SSL support.

parent 9ad853bc
...@@ -13,9 +13,12 @@ ...@@ -13,9 +13,12 @@
\indexii{POP3}{protocol} \indexii{POP3}{protocol}
This module defines a class, \class{POP3}, which encapsulates a This module defines a class, \class{POP3}, which encapsulates a
connection to an POP3 server and implements the protocol as defined in connection to a POP3 server and implements the protocol as defined in
\rfc{1725}. The \class{POP3} class supports both the minimal and \rfc{1725}. The \class{POP3} class supports both the minimal and
optional command sets. optional command sets. Additionally, this module provides a class
\class{POP3_SSL}, which provides support for connecting to POP3
servers that use SSL as an underlying protocol layer.
Note that POP3, though widely supported, is obsolescent. The Note that POP3, though widely supported, is obsolescent. The
implementation quality of POP3 servers varies widely, and too many are implementation quality of POP3 servers varies widely, and too many are
...@@ -31,6 +34,16 @@ created when the instance is initialized. ...@@ -31,6 +34,16 @@ created when the instance is initialized.
If \var{port} is omitted, the standard POP3 port (110) is used. If \var{port} is omitted, the standard POP3 port (110) is used.
\end{classdesc} \end{classdesc}
\begin{classdesc}{POP3_SSL}{host\optional{, port\optional{, keyfile\optional{, certfile}}}}
This is a subclass of \class{POP3} that connects to the server over an
SSL encrypted socket. If \var{port} is not specified, 995, the
standard POP3-over-SSL port is used. \var{keyfile} and \var{certfile}
are also optional - they can contain a PEM formatted private key and
certificate chain file for the SSL connection.
\versionadded{2.4}
\end{classdesc}
One exception is defined as an attribute of the \module{poplib} module: One exception is defined as an attribute of the \module{poplib} module:
\begin{excdesc}{error_proto} \begin{excdesc}{error_proto}
...@@ -143,6 +156,9 @@ otherwise result is list \code{(\var{response}, ['mesgnum uid', ...], ...@@ -143,6 +156,9 @@ otherwise result is list \code{(\var{response}, ['mesgnum uid', ...],
\var{octets})}. \var{octets})}.
\end{methoddesc} \end{methoddesc}
Instances of \class{POP3_SSL} have no additional methods. The
interface of this subclass is identical to its parent.
\subsection{POP3 Example \label{pop3-example}} \subsection{POP3 Example \label{pop3-example}}
......
...@@ -7,6 +7,7 @@ Based on the J. Myers POP3 draft, Jan. 96 ...@@ -7,6 +7,7 @@ Based on the J. Myers POP3 draft, Jan. 96
# [heavily stealing from nntplib.py] # [heavily stealing from nntplib.py]
# Updated: Piers Lauder <piers@cs.su.oz.au> [Jul '97] # Updated: Piers Lauder <piers@cs.su.oz.au> [Jul '97]
# String method conversion and test jig improvements by ESR, February 2001. # String method conversion and test jig improvements by ESR, February 2001.
# Added the POP3_SSL class. Methods loosely based on IMAP_SSL. Hector Urtubia <urtubia@mrbook.org> Aug 2003
# Example (see the test function at the end of this file) # Example (see the test function at the end of this file)
...@@ -14,7 +15,7 @@ Based on the J. Myers POP3 draft, Jan. 96 ...@@ -14,7 +15,7 @@ Based on the J. Myers POP3 draft, Jan. 96
import re, socket import re, socket
__all__ = ["POP3","error_proto"] __all__ = ["POP3","error_proto","POP3_SSL"]
# Exception raised when an error or invalid response is received: # Exception raised when an error or invalid response is received:
...@@ -23,6 +24,9 @@ class error_proto(Exception): pass ...@@ -23,6 +24,9 @@ class error_proto(Exception): pass
# Standard Port # Standard Port
POP3_PORT = 110 POP3_PORT = 110
# POP SSL PORT
POP3_SSL_PORT = 995
# Line terminators (we always output CRLF, but accept any of CRLF, LFCR, LF) # Line terminators (we always output CRLF, but accept any of CRLF, LFCR, LF)
CR = '\r' CR = '\r'
LF = '\n' LF = '\n'
...@@ -317,6 +321,90 @@ class POP3: ...@@ -317,6 +321,90 @@ class POP3:
return self._shortcmd('UIDL %s' % which) return self._shortcmd('UIDL %s' % which)
return self._longcmd('UIDL') return self._longcmd('UIDL')
class POP3_SSL(POP3):
"""POP3 client class over SSL connection
Instantiate with: POP3_SSL(hostname, port=995, keyfile=None, certfile=None)
hostname - the hostname of the pop3 over ssl server
port - port number
keyfile - PEM formatted file that countains your private key
certfile - PEM formatted certificate chain file
See the methods of the parent class POP3 for more documentation.
"""
def __init__(self, host, port = POP3_SSL_PORT, keyfile = None, certfile = None):
self.host = host
self.port = port
self.keyfile = keyfile
self.certfile = certfile
self.buffer = ""
msg = "getaddrinfo returns an empty list"
self.sock = None
for res in socket.getaddrinfo(self.host, self.port, 0, socket.SOCK_STREAM):
af, socktype, proto, canonname, sa = res
try:
self.sock = socket.socket(af, socktype, proto)
self.sock.connect(sa)
except socket.error, msg:
if self.sock:
self.sock.close()
self.sock = None
continue
break
if not self.sock:
raise socket.error, msg
self.file = self.sock.makefile('rb')
self.sslobj = socket.ssl(self.sock, self.keyfile, self.certfile)
self._debugging = 0
self.welcome = self._getresp()
def _fillBuffer(self):
localbuf = self.sslobj.read()
if len(localbuf) == 0:
raise error_proto('-ERR EOF')
self.buffer += localbuf
def _getline(self):
line = ""
renewline = re.compile(r'.*?\n')
match = renewline.match(self.buffer)
while not match:
self._fillBuffer()
match = renewline.match(self.buffer)
line = match.group(0)
self.buffer = renewline.sub('' ,self.buffer, 1)
if self._debugging > 1: print '*get*', `line`
octets = len(line)
if line[-2:] == CRLF:
return line[:-2], octets
if line[0] == CR:
return line[1:-1], octets
return line[:-1], octets
def _putline(self, line):
if self._debugging > 1: print '*put*', `line`
line += CRLF
bytes = len(line)
while bytes > 0:
sent = self.sslobj.write(line)
if sent == bytes:
break # avoid copy
line = line[sent:]
bytes = bytes - sent
def quit(self):
"""Signoff: commit changes on server, unlock mailbox, close connection."""
try:
resp = self._shortcmd('QUIT')
except error_proto, val:
resp = val
self.sock.close()
del self.sslobj, self.sock
return resp
if __name__ == "__main__": if __name__ == "__main__":
import sys import sys
......
...@@ -562,6 +562,7 @@ Stephen Turner ...@@ -562,6 +562,7 @@ Stephen Turner
Bill Tutt Bill Tutt
Doobee R. Tzeck Doobee R. Tzeck
Lionel Ulmer Lionel Ulmer
Hector Urtubia
Frank Vercruesse Frank Vercruesse
Jaap Vermeulen Jaap Vermeulen
Al Vezza Al Vezza
......
...@@ -101,6 +101,8 @@ Extension modules ...@@ -101,6 +101,8 @@ Extension modules
Library Library
------- -------
- poplib.POP3_SSL has been added.
- tmpfile.mkstemp now returns an absolute path even if dir is relative. - tmpfile.mkstemp now returns an absolute path even if dir is relative.
- urlparse is RFC 2396 compliant. - urlparse is RFC 2396 compliant.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment