diff -r c43362d35d8d Lib/smtpd.py --- a/Lib/smtpd.py Fri Jul 04 17:00:25 2014 -0700 +++ b/Lib/smtpd.py Wed Jul 09 17:27:09 2014 +0200 @@ -303,7 +303,12 @@ 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('555 Error: This server accepts UTF-8 decodable data' + ' only.') + 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 09 17:27:09 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,20 @@ 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'555 Error: This server accepts UTF-8 decodable data only.\r\n' + ) + self.assertEqual(self.channel.received_data, '') + self.assertEqual(self.channel.smtp_state, self.channel.COMMAND) + if __name__ == "__main__": unittest.main()