#1672568: email now registers defects for base64 payload format errors.

Which also means that it is now producing *something* for any base64
payload, which is what leads to the couple of older test changes in
test_email.  This is a slightly backward incompatible behavior change,
but the new behavior is so much more useful than the old (you can now
*reliably* detect errors, and any program that was detecting errors by
sniffing for a base64 return from get_payload(decode=True) and then doing
its own error-recovery decode will just get the error-recovery decode
right away).  So this seems to me to be worth the small risk inherent
in this behavior change.

This patch also refactors the defect tests into a separate test file,
since they are no longer just parser tests.
diff --git a/Lib/test/test_email/test_email.py b/Lib/test/test_email/test_email.py
index c04952c..5131b65 100644
--- a/Lib/test/test_email/test_email.py
+++ b/Lib/test/test_email/test_email.py
@@ -513,6 +513,7 @@
         eq(msg.values(), ['One Hundred', 'Twenty', 'Three', 'Eleven'])
         self.assertRaises(KeyError, msg.replace_header, 'Fourth', 'Missing')
 
+    # test_defect_handling:test_invalid_chars_in_base64_payload
     def test_broken_base64_payload(self):
         x = 'AwDp0P7//y6LwKEAcPa/6Q=9'
         msg = Message()
@@ -520,7 +521,10 @@
         msg['content-transfer-encoding'] = 'base64'
         msg.set_payload(x)
         self.assertEqual(msg.get_payload(decode=True),
-                         bytes(x, 'raw-unicode-escape'))
+                         (b'\x03\x00\xe9\xd0\xfe\xff\xff.\x8b\xc0'
+                          b'\xa1\x00p\xf6\xbf\xe9\x0f'))
+        self.assertIsInstance(msg.defects[0],
+                              errors.InvalidBase64CharactersDefect)
 
     def test_broken_unicode_payload(self):
         # This test improves coverage but is not a compliance test.
@@ -1815,7 +1819,7 @@
         eq(msg.get_content_maintype(), 'text')
         eq(msg.get_content_subtype(), 'plain')
 
-    # test_parser.TestMessageDefectDetectionBase
+    # test_defect_handling
     def test_same_boundary_inner_outer(self):
         unless = self.assertTrue
         msg = self._msgobj('msg_15.txt')
@@ -1826,7 +1830,7 @@
         unless(isinstance(inner.defects[0],
                           errors.StartBoundaryNotFoundDefect))
 
-    # test_parser.TestMessageDefectDetectionBase
+    # test_defect_handling
     def test_multipart_no_boundary(self):
         unless = self.assertTrue
         msg = self._msgobj('msg_25.txt')
@@ -1860,7 +1864,7 @@
         --===============3344438784458119861==--
         """)
 
-    # test_parser.TestMessageDefectDetectionBase
+    # test_defect_handling
     def test_multipart_invalid_cte(self):
         msg = self._str_msg(
             self.multipart_msg.format("\nContent-Transfer-Encoding: base64"))
@@ -1868,12 +1872,12 @@
         self.assertIsInstance(msg.defects[0],
             errors.InvalidMultipartContentTransferEncodingDefect)
 
-    # test_parser.TestMessageDefectDetectionBase
+    # test_defect_handling
     def test_multipart_no_cte_no_defect(self):
         msg = self._str_msg(self.multipart_msg.format(''))
         self.assertEqual(len(msg.defects), 0)
 
-    # test_parser.TestMessageDefectDetectionBase
+    # test_defect_handling
     def test_multipart_valid_cte_no_defect(self):
         for cte in ('7bit', '8bit', 'BINary'):
             msg = self._str_msg(
@@ -1930,7 +1934,7 @@
 counter to RFC 2822, there's no separating newline here
 """)
 
-    # test_parser.TestMessageDefectDetectionBase
+    # test_defect_handling
     def test_lying_multipart(self):
         unless = self.assertTrue
         msg = self._msgobj('msg_41.txt')
@@ -1941,7 +1945,7 @@
         unless(isinstance(msg.defects[1],
                           errors.MultipartInvariantViolationDefect))
 
-    # test_parser.TestMessageDefectDetectionBase
+    # test_defect_handling
     def test_missing_start_boundary(self):
         outer = self._msgobj('msg_42.txt')
         # The message structure is:
@@ -1957,7 +1961,7 @@
         self.assertTrue(isinstance(bad.defects[0],
                                    errors.StartBoundaryNotFoundDefect))
 
-    # test_parser.TestMessageDefectDetectionBase
+    # test_defect_handling
     def test_first_line_is_continuation_header(self):
         eq = self.assertEqual
         m = ' Line 1\nSubject: test\n\nbody'
@@ -3271,15 +3275,19 @@
         self.assertEqual(msg.get_payload(decode=True),
                         'pöstál\n'.encode('utf-8'))
 
+    # test_defect_handling:test_invalid_chars_in_base64_payload
     def test_8bit_in_base64_body(self):
-        # Sticking an 8bit byte in a base64 block makes it undecodable by
-        # normal means, so the block is returned undecoded, but as bytes.
+        # If we get 8bit bytes in a base64 body, we can just ignore them
+        # as being outside the base64 alphabet and decode anyway.  But
+        # we register a defect.
         m = self.bodytest_msg.format(charset='utf-8',
                                      cte='base64',
                                      bodyline='cMO2c3RhbAá=').encode('utf-8')
         msg = email.message_from_bytes(m)
         self.assertEqual(msg.get_payload(decode=True),
-                         'cMO2c3RhbAá=\n'.encode('utf-8'))
+                         'pöstal'.encode('utf-8'))
+        self.assertIsInstance(msg.defects[0],
+                              errors.InvalidBase64CharactersDefect)
 
     def test_8bit_in_uuencode_body(self):
         # Sticking an 8bit byte in a uuencode block makes it undecodable by