diff options
author | Guido van Rossum <guido@python.org> | 2001-09-14 16:08:44 (GMT) |
---|---|---|
committer | Guido van Rossum <guido@python.org> | 2001-09-14 16:08:44 (GMT) |
commit | f7fcf5eea62ebaa8e6820806b223c30289212d1a (patch) | |
tree | 73a1bb68ce10dcec13c1d7e84963c3d1a1d28b43 /Lib/smtplib.py | |
parent | 5f5512d246c58aab5a5290a85a8279f4b91021c4 (diff) | |
download | cpython-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-x | Lib/smtplib.py | 56 |
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. |