aiosmtpd
aiosmtpd copied to clipboard
Allow setting ssl_handshake_timeout on a Controller
The 60 seconds default timeout in sslproto.SSLProto for the SSL handshake to complete is longer than necessary for many scenarios (e.g. testing against a local SMTP server) with aiosmtpd.
If a client does not complete the SSL handshake the current behaviour is that the connection will close after the ssl_handshake_timeout of 60 seconds on python 3.7 and later. This raises a smtplib.SMTPServerDisconnected exception. The following test (which assumes that it is included in test_smtps.py) is an example of triggering this using the smtplib.SMTP client (which never completes the handshake):
# in ./aiosmtpd/tests/test_smtps.py
@pytest.mark.skipif(sys.version_info < (3, 7),
reason="SSL timeout implemented implemented with 3.7")
def test_SSL_timeout(self, ssl_controller):
with pytest.raises(SMTPServerDisconnected) as ex,\
SMTP(*Global.SrvAddr) as smtp_client:
# smtplib.SMTP does not support opporutnistic SSL so the SSL
# handshake never completes. On Python 3.6 and earlier this means
# that the connection will hang.
smtp_client.helo("example.com")
assert "Connection unexpectedly closed" in str(ex)
To partially mitigate the effect of this the ssl_handshake_timeout parameter on the loop.create_server() can be set to a shorter time in environments that don't need the full minute to complete. Unfortunately this is available only as of python 3.7; I have been unable to find a reasonable solution that would work for python 3.6.
My proposal is:
- Add a parameter to the
Controllerclasses for thessl_handshake_timeoutthat is passed toloop.create_server()if using python 3.7 or later. - Use the same timeout for STARTTLS on python 3.7 or later.
- Warn on python 3.6 (or earlier for completeness even if not supported) that this has no effect.
- Do not add an argument for the SSL handshake timeout to the CLI until python 3.6 support is dropped from aiosmtpd at some point in the future.