summaryrefslogtreecommitdiffstats
path: root/Lib/smtplib.py
diff options
context:
space:
mode:
authorGuido van Rossum <guido@python.org>2001-09-14 16:08:44 (GMT)
committerGuido van Rossum <guido@python.org>2001-09-14 16:08:44 (GMT)
commitf7fcf5eea62ebaa8e6820806b223c30289212d1a (patch)
tree73a1bb68ce10dcec13c1d7e84963c3d1a1d28b43 /Lib/smtplib.py
parent5f5512d246c58aab5a5290a85a8279f4b91021c4 (diff)
downloadcpython-f7fcf5eea62ebaa8e6820806b223c30289212d1a.zip
cpython-f7fcf5eea62ebaa8e6820806b223c30289212d1a.tar.gz
cpython-f7fcf5eea62ebaa8e6820806b223c30289212d1a.tar.bz2
SF patch #461413 (Gerhard Häring): Add STARTTLS feature to smtplib
This patch adds the features from RFC 2487 (Secure SMTP over TLS) to the smtplib module: - A starttls() function - Wrapper classes that simulate enough of sockets and files for smtplib, but really wrap a SSLObject - reset the list of known SMTP extensions at each call of ehlo(). This should have been the case anyway.
Diffstat (limited to 'Lib/smtplib.py')
-rwxr-xr-xLib/smtplib.py56
1 files changed, 54 insertions, 2 deletions
diff --git a/Lib/smtplib.py b/Lib/smtplib.py
index d64fa20..30f9398 100755
--- a/Lib/smtplib.py
+++ b/Lib/smtplib.py
@@ -2,8 +2,8 @@
'''SMTP/ESMTP client class.
-This should follow RFC 821 (SMTP), RFC 1869 (ESMTP) and RFC 2554 (SMTP
-Authentication).
+This should follow RFC 821 (SMTP), RFC 1869 (ESMTP), RFC 2554 (SMTP
+Authentication) and RFC 2487 (Secure SMTP over TLS).
Notes:
@@ -124,6 +124,41 @@ class SMTPAuthenticationError(SMTPResponseException):
combination provided.
"""
+class SSLFakeSocket:
+ """A fake socket object that really wraps a SSLObject.
+
+ It only supports what is needed in smtplib.
+ """
+ def __init__(self, realsock, sslobj):
+ self.realsock = realsock
+ self.sslobj = sslobj
+
+ def send(self, str):
+ self.sslobj.write(str)
+ return len(str)
+
+ def close(self):
+ self.realsock.close()
+
+class SSLFakeFile:
+ """A fake file like object that really wraps a SSLObject.
+
+ It only supports what is needed in smtplib.
+ """
+ def __init__( self, sslobj):
+ self.sslobj = sslobj
+
+ def readline(self):
+ str = ""
+ chr = None
+ while chr != "\n":
+ chr = self.sslobj.read(1)
+ str += chr
+ return str
+
+ def close(self):
+ pass
+
def quoteaddr(addr):
"""Quote a subset of the email addresses defined by RFC 821.
@@ -333,6 +368,7 @@ class SMTP:
Hostname to send for this command defaults to the FQDN of the local
host.
"""
+ self.esmtp_features = {}
if name:
self.putcmd("ehlo", name)
else:
@@ -506,6 +542,22 @@ class SMTP:
raise SMTPAuthenticationError(code, resp)
return (code, resp)
+ def starttls(self, keyfile = None, certfile = None):
+ """Puts the connection to the SMTP server into TLS mode.
+
+ If the server supports TLS, this will encrypt the rest of the SMTP
+ session. If you provide the keyfile and certfile parameters,
+ the identity of the SMTP server and client can be checked. This,
+ however, depends on whether the socket module really checks the
+ certificates.
+ """
+ (resp, reply) = self.docmd("STARTTLS")
+ if resp == 220:
+ sslobj = socket.ssl(self.sock, keyfile, certfile)
+ self.sock = SSLFakeSocket(self.sock, sslobj)
+ self.file = SSLFakeFile(sslobj)
+ return (resp, reply)
+
def sendmail(self, from_addr, to_addrs, msg, mail_options=[],
rcpt_options=[]):
"""This command performs an entire mail transaction.