bpo-39259: smtp.SMTP/SMTP_SSL now reject timeout = 0 (GH-17958)

This commit is contained in:
Dong-hee Na 2020-01-14 16:49:59 +09:00 committed by Victor Stinner
parent 2de064e630
commit 62e3973395
5 changed files with 29 additions and 7 deletions

View file

@ -70,6 +70,9 @@ Protocol) and :rfc:`1869` (SMTP Service Extensions).
.. versionadded:: 3.5
The SMTPUTF8 extension (:rfc:`6531`) is now supported.
.. versionchanged:: 3.9
If the *timeout* parameter is set to be zero, it will raise a
:class:`ValueError` to prevent the creation of a non-blocking socket
.. class:: SMTP_SSL(host='', port=0, local_hostname=None, keyfile=None, \
certfile=None [, timeout], context=None, \
@ -108,6 +111,9 @@ Protocol) and :rfc:`1869` (SMTP Service Extensions).
:func:`ssl.create_default_context` select the system's trusted CA
certificates for you.
.. versionchanged:: 3.9
If the *timeout* parameter is set to be zero, it will raise a
:class:`ValueError` to prevent the creation of a non-blocking socket
.. class:: LMTP(host='', port=LMTP_PORT, local_hostname=None, source_address=None)

View file

@ -259,6 +259,13 @@ now raises :exc:`ImportError` instead of :exc:`ValueError` for invalid relative
import attempts.
(Contributed by Ngalim Siregar in :issue:`37444`.)
smtplib
-------
:class:`~smtplib.SMTP` and :class:`~smtplib.SMTP_SSL` now raise a :class:`ValueError`
if the given timeout for their constructor is zero to prevent the creation of
a non-blocking socket. (Contributed by Dong-hee Na in :issue:`39259`.)
signal
------

View file

@ -303,6 +303,8 @@ def _print_debug(self, *args):
def _get_socket(self, host, port, timeout):
# This makes it simpler for SMTP_SSL to use the SMTP connect code
# and just alter the socket connection bit.
if timeout is not None and not timeout:
raise ValueError('Non-blocking socket (timeout=0) is not supported')
if self.debuglevel > 0:
self._print_debug('connect: to', (host, port), self.source_address)
return socket.create_connection((host, port), timeout,
@ -1030,13 +1032,12 @@ def __init__(self, host='', port=0, local_hostname=None,
keyfile=keyfile)
self.context = context
SMTP.__init__(self, host, port, local_hostname, timeout,
source_address)
source_address)
def _get_socket(self, host, port, timeout):
if self.debuglevel > 0:
self._print_debug('connect:', (host, port))
new_socket = socket.create_connection((host, port), timeout,
self.source_address)
new_socket = super()._get_socket(host, port, timeout)
new_socket = self.context.wrap_socket(new_socket,
server_hostname=self._host)
return new_socket
@ -1065,15 +1066,15 @@ class LMTP(SMTP):
ehlo_msg = "lhlo"
def __init__(self, host='', port=LMTP_PORT, local_hostname=None,
source_address=None):
source_address=None):
"""Initialize a new instance."""
SMTP.__init__(self, host, port, local_hostname=local_hostname,
source_address=source_address)
super().__init__(host, port, local_hostname=local_hostname,
source_address=source_address)
def connect(self, host='localhost', port=0, source_address=None):
"""Connect to the LMTP daemon, on either a Unix or a TCP socket."""
if host[0] != '/':
return SMTP.connect(self, host, port, source_address=source_address)
return super().connect(host, port, source_address=source_address)
# Handle Unix-domain sockets.
try:

View file

@ -122,6 +122,11 @@ def testTimeoutNone(self):
self.assertIsNone(smtp.sock.gettimeout())
smtp.close()
def testTimeoutZero(self):
mock_socket.reply_with(b"220 Hola mundo")
with self.assertRaises(ValueError):
smtplib.SMTP(HOST, self.port, timeout=0)
def testTimeoutValue(self):
mock_socket.reply_with(b"220 Hola mundo")
smtp = smtplib.SMTP(HOST, self.port, timeout=30)

View file

@ -0,0 +1,3 @@
:class:`~smtplib.SMTP` and :class:`~smtplib.SMTP_SSL` now raise a
:class:`ValueError` if the given timeout for their constructor is zero to
prevent the creation of a non-blocking socket. Patch by Dong-hee Na.