#22215: have the smtplib 'quit' command reset the state.

Without this reset, starttls would fail if a connect/starttls was done after a
quit, because smtplib assumed the existing value of emspt_features was
accurate, but it gets reset when starttls completes (and the new value does
not contain the starttls capability, since tls is already started at that
point).  (There may be additional places where this lack of reset was an
issue as well.)

Patch by Milan Oberkirch.
This commit is contained in:
R David Murray 2014-08-30 16:51:59 -04:00
parent a64b92edd3
commit 0cff49fcf9
3 changed files with 23 additions and 0 deletions

View File

@ -866,6 +866,10 @@ class SMTP:
def quit(self): def quit(self):
"""Terminate the SMTP session.""" """Terminate the SMTP session."""
res = self.docmd("quit") res = self.docmd("quit")
# A new EHLO is required after reconnecting with connect()
self.ehlo_resp = self.helo_resp = None
self.esmtp_features = {}
self.does_esmtp = False
self.close() self.close()
return res return res

View File

@ -858,6 +858,21 @@ class SMTPSimTests(unittest.TestCase):
self.assertIn(sim_auth_login_password, str(err)) self.assertIn(sim_auth_login_password, str(err))
smtp.close() smtp.close()
def test_quit_resets_greeting(self):
smtp = smtplib.SMTP(HOST, self.port,
local_hostname='localhost',
timeout=15)
code, message = smtp.ehlo()
self.assertEqual(code, 250)
self.assertIn('size', smtp.esmtp_features)
smtp.quit()
self.assertNotIn('size', smtp.esmtp_features)
smtp.connect(HOST, self.port)
self.assertNotIn('size', smtp.esmtp_features)
smtp.ehlo_or_helo_if_needed()
self.assertIn('size', smtp.esmtp_features)
smtp.quit()
def test_with_statement(self): def test_with_statement(self):
with smtplib.SMTP(HOST, self.port) as smtp: with smtplib.SMTP(HOST, self.port) as smtp:
code, message = smtp.noop() code, message = smtp.noop()

View File

@ -27,6 +27,10 @@ Core and Builtins
Library Library
------- -------
- Issue #22216: smtplib now resets its state more completely after a quit. The
most obvious consequence of the previous behavior was a STARTTLS failure
during a connect/starttls/quit/connect/starttls sequence.
- Issue #22185: Fix an occasional RuntimeError in threading.Condition.wait() - Issue #22185: Fix an occasional RuntimeError in threading.Condition.wait()
caused by mutation of the waiters queue without holding the lock. Patch caused by mutation of the waiters queue without holding the lock. Patch
by Doug Zongker. by Doug Zongker.