diff -r fe532dccf8f6 Lib/smtplib.py --- a/Lib/smtplib.py Mon Apr 14 10:30:43 2014 -0400 +++ b/Lib/smtplib.py Mon Apr 14 20:47:53 2014 +0530 @@ -478,6 +478,15 @@ """SMTP 'rset' command -- resets session.""" return self.docmd("rset") + def _rset(self): + """Internal 'rset' command which ignores any SMTPServerDisconnected error. + To be used internally in the library. + """ + try: + self.rset() + except SMTPServerDisconnected: + pass + def noop(self): """SMTP 'noop' command -- doesn't do anything :>""" return self.docmd("noop") @@ -762,7 +771,7 @@ if code == 421: self.close() else: - self.rset() + self._rset() raise SMTPSenderRefused(code, resp, from_addr) senderrs = {} if isinstance(to_addrs, str): @@ -776,14 +785,14 @@ 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 diff -r fe532dccf8f6 Lib/test/test_smtplib.py --- a/Lib/test/test_smtplib.py Mon Apr 14 10:30:43 2014 -0400 +++ b/Lib/test/test_smtplib.py Mon Apr 14 20:47:53 2014 +0530 @@ -619,6 +619,7 @@ 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 @@ 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 @@ #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)