diff -r c43362d35d8d Lib/smtpd.py --- a/Lib/smtpd.py Fri Jul 04 17:00:25 2014 -0700 +++ b/Lib/smtpd.py Wed Jul 16 21:53:15 2014 +0200 @@ -303,7 +303,15 @@ elif limit: self.num_bytes += len(data) if self._decode_data: - self.received_lines.append(str(data, 'utf-8')) + try: + self.received_lines.append(str(data, 'utf-8')) + except UnicodeDecodeError: + self.push('451 Internal server error: Unsuccessfully tried to' + ' decode input. Decoding should be disabled by the' + ' administrator (possible in Python 3.5 or later, ' + ' see' + ' https://docs.python.org/3.5/library/smtpd.html)') + self.smtp_state = self.COMMAND else: self.received_lines.append(data) diff -r c43362d35d8d Lib/test/test_smtpd.py --- a/Lib/test/test_smtpd.py Fri Jul 04 17:00:25 2014 -0700 +++ b/Lib/test/test_smtpd.py Wed Jul 16 21:53:15 2014 +0200 @@ -647,6 +647,20 @@ b'utf8 enriched text: \xc5\xbc\xc5\xba\xc4\x87\n' b'and some plain ascii') + def test_non_utf8_8bit_data(self): + # test for issue 19806. + self.write_line(b'HELO example') + self.write_line(b'MAIL From:eggs@example') + self.write_line(b'RCPT To:spam@example') + self.write_line(b'DATA') + self.write_line(b'undecodable bytes: \xc5\x00\xc4\xff\xd0') + self.write_line(b'and some plain ascii') + self.write_line(b'.') + self.assertEqual( + self.channel.received_data, + b'undecodable bytes: \xc5\x00\xc4\xff\xd0\n' + b'and some plain ascii') + class SMTPDChannelWithDecodeDataTrue(unittest.TestCase): @@ -691,6 +705,24 @@ self.channel.received_data, 'utf8 enriched text: żźć\nand some plain ascii') + def test_non_utf8_8bit_data(self): + # test for issue 19806. + self.write_line(b'HELO example') + self.write_line(b'MAIL From:eggs@example') + self.write_line(b'RCPT To:spam@example') + self.write_line(b'DATA') + self.write_line(b'undecodable bytes: \xc5\x00\xc4\xff\xd0\n') + self.assertEqual( + self.channel.socket.last, + b'451 Internal server error: Unsuccessfully tried to' + b' decode input. Decoding should be disabled by the' + b' administrator (possible in Python 3.5 or later, ' + b' see' + b' https://docs.python.org/3.5/library/smtpd.html)\r\n' + ) + self.assertEqual(self.channel.received_data, '') + self.assertEqual(self.channel.smtp_state, self.channel.COMMAND) + if __name__ == "__main__": unittest.main()