diff options
author | 2018-09-08 02:20:27 +0100 | |
---|---|---|
committer | 2018-09-08 02:20:27 +0100 | |
commit | eb6ab73f93c8b883a8d75a83560e2b4c59170d95 (patch) | |
tree | 8f26cf42c7bef651024feb3676c001857a228d55 /Lib | |
parent | [3.6] bpo-34007: Skip traceback tests if the Program Counter is not available... (diff) | |
download | cpython-eb6ab73f93c8b883a8d75a83560e2b4c59170d95.tar.gz cpython-eb6ab73f93c8b883a8d75a83560e2b4c59170d95.tar.bz2 cpython-eb6ab73f93c8b883a8d75a83560e2b4c59170d95.zip |
[3.6] bpo-34246: Use no mutable default args in smtplib (GH-8554) (#9112)
Some methods of the SMTP class use mutable default arguments. Specially
`send_message` is affected as it mutates one of the args by appending items
to it, which has side effects on further calls..
(cherry picked from commit d5fbe9b1a3d65ceeb9159c5ba999ee966a945f76)
Co-authored-by: Pablo Aguiar <scorphus@gmail.com>
Diffstat (limited to 'Lib')
-rwxr-xr-x | Lib/smtplib.py | 12 | ||||
-rw-r--r-- | Lib/test/test_smtplib.py | 32 |
2 files changed, 38 insertions, 6 deletions
diff --git a/Lib/smtplib.py b/Lib/smtplib.py index b679875fd2c..048c6bfb067 100755 --- a/Lib/smtplib.py +++ b/Lib/smtplib.py @@ -513,7 +513,7 @@ class SMTP: """SMTP 'noop' command -- doesn't do anything :>""" return self.docmd("noop") - def mail(self, sender, options=[]): + def mail(self, sender, options=()): """SMTP 'mail' command -- begins mail xfer session. This method may raise the following exceptions: @@ -534,7 +534,7 @@ class SMTP: self.putcmd("mail", "FROM:%s%s" % (quoteaddr(sender), optionlist)) return self.getreply() - def rcpt(self, recip, options=[]): + def rcpt(self, recip, options=()): """SMTP 'rcpt' command -- indicates 1 recipient for this mail.""" optionlist = '' if options and self.does_esmtp: @@ -785,8 +785,8 @@ class SMTP: raise SMTPResponseException(resp, reply) return (resp, reply) - def sendmail(self, from_addr, to_addrs, msg, mail_options=[], - rcpt_options=[]): + def sendmail(self, from_addr, to_addrs, msg, mail_options=(), + rcpt_options=()): """This command performs an entire mail transaction. The arguments are: @@ -890,7 +890,7 @@ class SMTP: return senderrs def send_message(self, msg, from_addr=None, to_addrs=None, - mail_options=[], rcpt_options={}): + mail_options=(), rcpt_options=()): """Converts message to a bytestring and passes it to sendmail. The arguments are as for sendmail, except that msg is an @@ -958,7 +958,7 @@ class SMTP: if international: g = email.generator.BytesGenerator( bytesmsg, policy=msg.policy.clone(utf8=True)) - mail_options += ['SMTPUTF8', 'BODY=8BITMIME'] + mail_options = (*mail_options, 'SMTPUTF8', 'BODY=8BITMIME') else: g = email.generator.BytesGenerator(bytesmsg) g.flatten(msg_copy, linesep='\r\n') diff --git a/Lib/test/test_smtplib.py b/Lib/test/test_smtplib.py index 79b3bd43687..18110191dc3 100644 --- a/Lib/test/test_smtplib.py +++ b/Lib/test/test_smtplib.py @@ -18,6 +18,11 @@ import textwrap import unittest from test import support, mock_socket +from unittest.mock import Mock + +HOST = "localhost" +HOSTv4 = "127.0.0.1" +HOSTv6 = "::1" try: import threading @@ -569,6 +574,33 @@ class NonConnectingTests(unittest.TestCase): "localhost:bogus") +class DefaultArgumentsTests(unittest.TestCase): + + def setUp(self): + self.msg = EmailMessage() + self.msg['From'] = 'Páolo <főo@bar.com>' + self.smtp = smtplib.SMTP() + self.smtp.ehlo = Mock(return_value=(200, 'OK')) + self.smtp.has_extn, self.smtp.sendmail = Mock(), Mock() + + def testSendMessage(self): + expected_mail_options = ('SMTPUTF8', 'BODY=8BITMIME') + self.smtp.send_message(self.msg) + self.smtp.send_message(self.msg) + self.assertEqual(self.smtp.sendmail.call_args_list[0][0][3], + expected_mail_options) + self.assertEqual(self.smtp.sendmail.call_args_list[1][0][3], + expected_mail_options) + + def testSendMessageWithMailOptions(self): + mail_options = ['STARTTLS'] + expected_mail_options = ('STARTTLS', 'SMTPUTF8', 'BODY=8BITMIME') + self.smtp.send_message(self.msg, None, None, mail_options) + self.assertEqual(mail_options, ['STARTTLS']) + self.assertEqual(self.smtp.sendmail.call_args_list[0][0][3], + expected_mail_options) + + # test response of client to a non-successful HELO message @unittest.skipUnless(threading, 'Threading required for this test.') class BadHELOServerTests(unittest.TestCase): |