mirror of https://github.com/python/cpython
Merge #17498: Defer SMTPServerDisconnected errors until the next command.
This commit is contained in:
commit
4d8eee9705
|
@ -478,6 +478,18 @@ class SMTP:
|
|||
"""SMTP 'rset' command -- resets session."""
|
||||
return self.docmd("rset")
|
||||
|
||||
def _rset(self):
|
||||
"""Internal 'rset' command which ignores any SMTPServerDisconnected error.
|
||||
|
||||
Used internally in the library, since the server disconnected error
|
||||
should appear to the application when the *next* command is issued, if
|
||||
we are doing an internal "safety" reset.
|
||||
"""
|
||||
try:
|
||||
self.rset()
|
||||
except SMTPServerDisconnected:
|
||||
pass
|
||||
|
||||
def noop(self):
|
||||
"""SMTP 'noop' command -- doesn't do anything :>"""
|
||||
return self.docmd("noop")
|
||||
|
@ -762,7 +774,7 @@ class SMTP:
|
|||
if code == 421:
|
||||
self.close()
|
||||
else:
|
||||
self.rset()
|
||||
self._rset()
|
||||
raise SMTPSenderRefused(code, resp, from_addr)
|
||||
senderrs = {}
|
||||
if isinstance(to_addrs, str):
|
||||
|
@ -776,14 +788,14 @@ class SMTP:
|
|||
raise SMTPRecipientsRefused(senderrs)
|
||||
if len(senderrs) == len(to_addrs):
|
||||
# the server refused all our recipients
|
||||
self.rset()
|
||||
self._rset()
|
||||
raise SMTPRecipientsRefused(senderrs)
|
||||
(code, resp) = self.data(msg)
|
||||
if code != 250:
|
||||
if code == 421:
|
||||
self.close()
|
||||
else:
|
||||
self.rset()
|
||||
self._rset()
|
||||
raise SMTPDataError(code, resp)
|
||||
#if we got here then somebody got our mail
|
||||
return senderrs
|
||||
|
|
|
@ -619,6 +619,7 @@ class SimSMTPChannel(smtpd.SMTPChannel):
|
|||
data_response = None
|
||||
rcpt_count = 0
|
||||
rset_count = 0
|
||||
disconnect = 0
|
||||
|
||||
def __init__(self, extra_features, *args, **kw):
|
||||
self._extrafeatures = ''.join(
|
||||
|
@ -684,6 +685,8 @@ class SimSMTPChannel(smtpd.SMTPChannel):
|
|||
super().smtp_MAIL(arg)
|
||||
else:
|
||||
self.push(self.mail_response)
|
||||
if self.disconnect:
|
||||
self.close_when_done()
|
||||
|
||||
def smtp_RCPT(self, arg):
|
||||
if self.rcpt_response is None:
|
||||
|
@ -875,6 +878,16 @@ class SMTPSimTests(unittest.TestCase):
|
|||
#TODO: add tests for correct AUTH method fallback now that the
|
||||
#test infrastructure can support it.
|
||||
|
||||
# Issue 17498: make sure _rset does not raise SMTPServerDisconnected exception
|
||||
def test__rest_from_mail_cmd(self):
|
||||
smtp = smtplib.SMTP(HOST, self.port, local_hostname='localhost', timeout=15)
|
||||
smtp.noop()
|
||||
self.serv._SMTPchannel.mail_response = '451 Requested action aborted'
|
||||
self.serv._SMTPchannel.disconnect = True
|
||||
with self.assertRaises(smtplib.SMTPSenderRefused):
|
||||
smtp.sendmail('John', 'Sally', 'test message')
|
||||
self.assertIsNone(smtp.sock)
|
||||
|
||||
# Issue 5713: make sure close, not rset, is called if we get a 421 error
|
||||
def test_421_from_mail_cmd(self):
|
||||
smtp = smtplib.SMTP(HOST, self.port, local_hostname='localhost', timeout=15)
|
||||
|
|
|
@ -46,6 +46,11 @@ Core and Builtins
|
|||
Library
|
||||
-------
|
||||
|
||||
- Issue #17498: Some SMTP servers disconnect after certain errors, violating
|
||||
strict RFC conformance. Instead of losing the error code when we issue the
|
||||
subsequent RSET, smtplib now returns the error code and defers raising the
|
||||
SMTPServerDisconnected error until the next command is issued.
|
||||
|
||||
- Issue #17826: setting an iterable side_effect on a mock function created by
|
||||
create_autospec now works. Patch by Kushal Das.
|
||||
|
||||
|
|
Loading…
Reference in New Issue