cpython: 6737de76487b (original) (raw)
Mercurial > cpython
changeset 70185:6737de76487b
Issue #8809: The SMTP_SSL constructor and SMTP.starttls() now support passing a `context` argument pointing to an ssl.SSLContext instance. Patch by Kasun Herath. [#8809]
Antoine Pitrou solipsis@pitrou.net | |
---|---|
date | Wed, 18 May 2011 18:03:09 +0200 |
parents | c52807b17e03 |
children | ebe93fec1558 |
files | Doc/library/smtplib.rst Lib/smtplib.py Lib/test/test_smtpnet.py Misc/NEWS |
diffstat | 4 files changed, 70 insertions(+), 9 deletions(-)[+] [-] Doc/library/smtplib.rst 17 Lib/smtplib.py 31 Lib/test/test_smtpnet.py 27 Misc/NEWS 4 |
line wrap: on
line diff
--- a/Doc/library/smtplib.rst
+++ b/Doc/library/smtplib.rst
@@ -49,7 +49,7 @@ Protocol) and :rfc:1869
(SMTP Service
Support for the :keyword:with
statement was added.
-.. class:: SMTP_SSL(host='', port=0, local_hostname=None, keyfile=None, certfile=None[, timeout])
+.. class:: SMTP_SSL(host='', port=0, local_hostname=None, keyfile=None, certfile=None[, timeout], context=None)
A :class:SMTP_SSL
instance behaves exactly the same as instances of
:class:SMTP
. :class:SMTP_SSL
should be used for situations where SSL is
@@ -57,11 +57,16 @@ Protocol) and :rfc:1869
(SMTP Service
not appropriate. If host is not specified, the local host is used. If
port is zero, the standard SMTP-over-SSL port (465) is used. keyfile
and certfile are also optional, and can contain a PEM formatted private key
- and certificate chain file for the SSL connection. context also optional, can contain
- a SSLContext, and is an alternative to keyfile and certfile; If it is specified both
- keyfile and certfile must be None. The optional timeout parameter specifies a timeout in seconds for blocking operations like the connection attempt (if not specified, the global default timeout setting will be used).
- .. versionchanged:: 3.3
*context* was added.[](#l1.25)
+
.. class:: LMTP(host='', port=LMTP_PORT, local_hostname=None)
@@ -256,7 +261,7 @@ An :class:SMTP
instance has the follow
No suitable authentication method was found.
-.. method:: SMTP.starttls(keyfile=None, certfile=None)
+.. method:: SMTP.starttls(keyfile=None, certfile=None, context=None)
Put the SMTP connection in TLS (Transport Layer Security) mode. All SMTP
commands that follow will be encrypted. You should then call :meth:ehlo
@@ -265,6 +270,9 @@ An :class:SMTP
instance has the follow
If keyfile and certfile are provided, these are passed to the :mod:socket
module's :func:ssl
function.
- Optional context parameter is a :class:
ssl.SSLContext
object; This is an alternative to - using a keyfile and a certfile and if specified both keyfile and certfile should be None.
+
If there has been no previous
EHLO
orHELO
command this session, this method tries ESMTPEHLO
first.
@@ -277,6 +285,9 @@ An :class:SMTP
instance has the follow
:exc:RuntimeError
SSL/TLS support is not available to your Python interpreter.
+ .. method:: SMTP.sendmail(from_addr, to_addrs, msg, mail_options=[], rcpt_options=[])
--- a/Lib/smtplib.py +++ b/Lib/smtplib.py @@ -635,7 +635,7 @@ class SMTP: # We could not login sucessfully. Return result of last attempt. raise SMTPAuthenticationError(code, resp)
- def starttls(self, keyfile=None, certfile=None, context=None): """Puts the connection to the SMTP server into TLS mode.
If there has been no previous EHLO or HELO command this session, this @@ -659,7 +659,16 @@ class SMTP: if resp == 220: if not _have_ssl: raise RuntimeError("No SSL support included in this Python")
self.sock = ssl.wrap_socket(self.sock, keyfile, certfile)[](#l2.16)
if context is not None and keyfile is not None:[](#l2.17)
raise ValueError("context and keyfile arguments are mutually "[](#l2.18)
"exclusive")[](#l2.19)
if context is not None and certfile is not None:[](#l2.20)
raise ValueError("context and certfile arguments are mutually "[](#l2.21)
"exclusive")[](#l2.22)
if context is not None:[](#l2.23)
self.sock = context.wrap_socket(self.sock)[](#l2.24)
else:[](#l2.25)
self.sock = ssl.wrap_socket(self.sock, keyfile, certfile)[](#l2.26) self.file = SSLFakeFile(self.sock)[](#l2.27) # RFC 3207:[](#l2.28) # The client MUST discard any knowledge obtained from[](#l2.29)
@@ -815,23 +824,35 @@ if _have_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.[](#l2.34)
certificate chain file for the SSL connection. context also optional, can contain[](#l2.35)
a SSLContext, and is an alternative to keyfile and certfile; If it is specified both[](#l2.36)
keyfile and certfile must be None.[](#l2.37) """[](#l2.38)
default_port = SMTP_SSL_PORT def init(self, host='', port=0, local_hostname=None, keyfile=None, certfile=None,
timeout=socket._GLOBAL_DEFAULT_TIMEOUT):[](#l2.44)
timeout=socket._GLOBAL_DEFAULT_TIMEOUT, context=None):[](#l2.45)
if context is not None and keyfile is not None:[](#l2.46)
raise ValueError("context and keyfile arguments are mutually "[](#l2.47)
"exclusive")[](#l2.48)
if context is not None and certfile is not None:[](#l2.49)
raise ValueError("context and certfile arguments are mutually "[](#l2.50)
"exclusive")[](#l2.51) self.keyfile = keyfile[](#l2.52) self.certfile = certfile[](#l2.53)
self.context = context[](#l2.54) SMTP.__init__(self, host, port, local_hostname, timeout)[](#l2.55)
def _get_socket(self, host, port, timeout): if self.debuglevel > 0: print('connect:', (host, port), file=stderr) new_socket = socket.create_connection((host, port), timeout)
new_socket = ssl.wrap_socket(new_socket, self.keyfile, self.certfile)[](#l2.61)
if self.context is not None:[](#l2.62)
new_socket = self.context.wrap_socket(new_socket)[](#l2.63)
else:[](#l2.64)
new_socket = ssl.wrap_socket(new_socket, self.keyfile, self.certfile)[](#l2.65) self.file = SSLFakeFile(new_socket)[](#l2.66) return new_socket[](#l2.67)
--- a/Lib/test/test_smtpnet.py +++ b/Lib/test/test_smtpnet.py @@ -3,12 +3,29 @@ import unittest from test import support import smtplib +import ssl support.requires("network") + +class SmtpTest(unittest.TestCase):
- def test_connect_starttls(self):
support.get_attribute(smtplib, 'SMTP_SSL')[](#l3.18)
with support.transient_internet(self.testServer):[](#l3.19)
server = smtplib.SMTP(self.testServer, self.remotePort)[](#l3.20)
server.starttls(context=self.context)[](#l3.21)
server.ehlo()[](#l3.22)
server.quit()[](#l3.23)
+ + class SmtpSSLTest(unittest.TestCase): testServer = 'smtp.gmail.com' remotePort = 465
def test_connect(self): support.get_attribute(smtplib, 'SMTP_SSL') @@ -24,8 +41,16 @@ class SmtpSSLTest(unittest.TestCase): server.ehlo() server.quit()
- def test_connect_using_sslcontext(self):
support.get_attribute(smtplib, 'SMTP_SSL')[](#l3.38)
with support.transient_internet(self.testServer):[](#l3.39)
server = smtplib.SMTP_SSL(self.testServer, self.remotePort, context=self.context)[](#l3.40)
server.ehlo()[](#l3.41)
server.quit()[](#l3.42)
if name == "main": test_main()
--- a/Misc/NEWS +++ b/Misc/NEWS @@ -153,6 +153,10 @@ Core and Builtins Library ------- +- Issue #8809: The SMTP_SSL constructor and SMTP.starttls() now support