Patch #: Add POP3 over SSL support.

This commit is contained in:
Martin v. Löwis 2003-10-31 12:52:35 +00:00
parent 9ad853bc37
commit 48440b7c27
4 changed files with 110 additions and 3 deletions

View File

@ -13,9 +13,12 @@
\indexii{POP3}{protocol}
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
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
implementation quality of POP3 servers varies widely, and too many are
@ -31,6 +34,16 @@ created when the instance is initialized.
If \var{port} is omitted, the standard POP3 port (110) is used.
\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:
\begin{excdesc}{error_proto}
@ -143,6 +156,9 @@ otherwise result is list \code{(\var{response}, ['mesgnum uid', ...],
\var{octets})}.
\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}}

View File

@ -7,6 +7,7 @@ Based on the J. Myers POP3 draft, Jan. 96
# [heavily stealing from nntplib.py]
# Updated: Piers Lauder <piers@cs.su.oz.au> [Jul '97]
# 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)
@ -14,7 +15,7 @@ Based on the J. Myers POP3 draft, Jan. 96
import re, socket
__all__ = ["POP3","error_proto"]
__all__ = ["POP3","error_proto","POP3_SSL"]
# Exception raised when an error or invalid response is received:
@ -23,6 +24,9 @@ class error_proto(Exception): pass
# Standard Port
POP3_PORT = 110
# POP SSL PORT
POP3_SSL_PORT = 995
# Line terminators (we always output CRLF, but accept any of CRLF, LFCR, LF)
CR = '\r'
LF = '\n'
@ -317,6 +321,90 @@ class POP3:
return self._shortcmd('UIDL %s' % which)
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__":
import sys

View File

@ -562,6 +562,7 @@ Stephen Turner
Bill Tutt
Doobee R. Tzeck
Lionel Ulmer
Hector Urtubia
Frank Vercruesse
Jaap Vermeulen
Al Vezza

View File

@ -101,6 +101,8 @@ Extension modules
Library
-------
- poplib.POP3_SSL has been added.
- tmpfile.mkstemp now returns an absolute path even if dir is relative.
- urlparse is RFC 2396 compliant.