From: Martin v. Löwis Date: Fri, 27 Oct 2006 07:13:28 +0000 (+0000) Subject: Patch #1567274: Support SMTP over TLS. X-Git-Tag: v2.6a1~2531 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=ee82c0e6b727515b54ce2f1dfff2e6ff330f88f1;p=python Patch #1567274: Support SMTP over TLS. --- diff --git a/Doc/lib/libsmtplib.tex b/Doc/lib/libsmtplib.tex index 2f87bc483b..9943d9f285 100644 --- a/Doc/lib/libsmtplib.tex +++ b/Doc/lib/libsmtplib.tex @@ -28,6 +28,18 @@ For normal use, you should only require the initialization/connect, included below. \end{classdesc} +\begin{classdesc}{SMTP_SSL}{\optional{host\optional{, port\optional{, + local_hostname\optional{, + keyfile\optional{, + certfile}}}}}} +A \class{SMTP_SSL} instance behaves exactly the same as instance \class{SMTP}. +\class{SMTP_SSL} should be used for the situations where SSL is required from +the beginning of the connection and \method{starttls()} is not appropriate. +If host is not specified, the local host is used. If port is +omitted, the standard SMTP-over-SSL port (465) is used. keyfile and certfile +are also optional - they can contain a PEM formatted private key and +certificate chain file for the SSL connection. +\end{classdesc} A nice selection of exceptions is defined as well: diff --git a/Lib/smtplib.py b/Lib/smtplib.py index 9c8c4fa48c..7a677aa793 100755 --- a/Lib/smtplib.py +++ b/Lib/smtplib.py @@ -52,9 +52,10 @@ from sys import stderr __all__ = ["SMTPException","SMTPServerDisconnected","SMTPResponseException", "SMTPSenderRefused","SMTPRecipientsRefused","SMTPDataError", "SMTPConnectError","SMTPHeloError","SMTPAuthenticationError", - "quoteaddr","quotedata","SMTP"] + "quoteaddr","quotedata","SMTP","SMTP_SSL"] SMTP_PORT = 25 +SMTP_SSL_PORT = 465 CRLF="\r\n" OLDSTYLE_AUTH = re.compile(r"auth=(.*)", re.I) @@ -240,6 +241,7 @@ class SMTP: """ self.esmtp_features = {} + self.default_port = SMTP_PORT if host: (code, msg) = self.connect(host, port) if code != 220: @@ -271,6 +273,13 @@ class SMTP: """ self.debuglevel = debuglevel + def _get_socket(self,af, socktype, proto,sa): + # This makes it simpler for SMTP_SSL to use the SMTP connect code + # and just alter the socket connection bit. + self.sock = socket.socket(af, socktype, proto) + if self.debuglevel > 0: print>>stderr, 'connect:', (host, port) + self.sock.connect(sa) + def connect(self, host='localhost', port = 0): """Connect to a host on a given port. @@ -289,16 +298,14 @@ class SMTP: try: port = int(port) except ValueError: raise socket.error, "nonnumeric port" - if not port: port = SMTP_PORT + if not port: port = self.default_port if self.debuglevel > 0: print>>stderr, 'connect:', (host, port) msg = "getaddrinfo returns an empty list" self.sock = None for res in socket.getaddrinfo(host, port, 0, socket.SOCK_STREAM): af, socktype, proto, canonname, sa = res try: - self.sock = socket.socket(af, socktype, proto) - if self.debuglevel > 0: print>>stderr, 'connect:', sa - self.sock.connect(sa) + self._get_socket(af,socktype,proto,sa) except socket.error, msg: if self.debuglevel > 0: print>>stderr, 'connect fail:', msg if self.sock: @@ -716,6 +723,28 @@ class SMTP: self.docmd("quit") self.close() +class SMTP_SSL(SMTP): + """ This is a subclass derived from SMTP that connects over an SSL encrypted + socket (to use this class you need a socket module that was compiled with SSL + support). If host is not specified, '' (the local host) is used. If port is + omitted, the standard SMTP-over-SSL port (465) is used. keyfile and certfile + are also optional - they can contain a PEM formatted private key and + certificate chain file for the SSL connection. + """ + def __init__(self, host = '', port = 0, local_hostname = None, + keyfile = None, certfile = None): + self.keyfile = keyfile + self.certfile = certfile + SMTP.__init__(self,host,port,local_hostname) + self.default_port = SMTP_SSL_PORT + + def _get_socket(self,af, socktype, proto,sa): + self.sock = socket.socket(af, socktype, proto) + if self.debuglevel > 0: print>>stderr, 'connect:', (host, port) + self.sock.connect(sa) + sslobj = socket.ssl(self.sock, self.keyfile, self.certfile) + self.sock = SSLFakeSocket(self.sock, sslobj) + self.file = SSLFakeFile(sslobj) # Test the sendmail method, which tests most of the others. # Note: This always sends to localhost. diff --git a/Misc/ACKS b/Misc/ACKS index 2e507640b8..d5d7675bc2 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -613,6 +613,7 @@ William Tanksley Christian Tanzer Steven Taschuk Amy Taylor +Monty Taylor Tobias Thelen Robin Thomas Eric Tiedemann diff --git a/Misc/NEWS b/Misc/NEWS index 219bbcf9c6..ab3bf3f8db 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -84,6 +84,8 @@ Core and builtins Library ------- +- Patch #1567274: Support SMTP over TLS. + - Patch #1560695: Add .note.GNU-stack to ctypes' sysv.S so that ctypes isn't considered as requiring executable stacks.