]> granicus.if.org Git - python/commitdiff
#28047: Fix calculation of base64 line length.
authorR David Murray <rdmurray@bitdance.com>
Fri, 9 Sep 2016 19:00:09 +0000 (15:00 -0400)
committerR David Murray <rdmurray@bitdance.com>
Fri, 9 Sep 2016 19:00:09 +0000 (15:00 -0400)
This is buggy in the old email code as well, but it doesn't affect anything
there because only the default line length is ever used there.

Lib/email/contentmanager.py
Lib/test/test_email/__init__.py
Lib/test/test_email/test_inversion.py
Misc/NEWS

index d3636529b6d7fd91f53cd3101ed7109968299d70..b98ce27184f3062eb5d36b96659ae4cedd3b32a6 100644 (file)
@@ -126,12 +126,13 @@ def _finalize_set(msg, disposition, filename, cid, params):
             msg.set_param(key, value)
 
 
-# XXX: This is a cleaned-up version of base64mime.body_encode.  It would
-# be nice to drop both this and quoprimime.body_encode in favor of
-# enhanced binascii routines that accepted a max_line_length parameter.
+# XXX: This is a cleaned-up version of base64mime.body_encode (including a bug
+# fix in the calculation of unencoded_bytes_per_line).  It would be nice to
+# drop both this and quoprimime.body_encode in favor of enhanced binascii
+# routines that accepted a max_line_length parameter.
 def _encode_base64(data, max_line_length):
     encoded_lines = []
-    unencoded_bytes_per_line = max_line_length * 3 // 4
+    unencoded_bytes_per_line = max_line_length // 4 * 3
     for i in range(0, len(data), unencoded_bytes_per_line):
         thisline = data[i:i+unencoded_bytes_per_line]
         encoded_lines.append(binascii.b2a_base64(thisline).decode('ascii'))
index d2f7d319342991241afad9d4b9d50c9f94bf6c9e..d4a03ee071f908184300743d42a6daee79b06c63 100644 (file)
@@ -121,6 +121,10 @@ def parameterize(cls):
     Note: if and only if the generated test name is a valid identifier can it
     be used to select the test individually from the unittest command line.
 
+    The values in the params dict can be a single value, a tuple, or a
+    dict.  If a single value of a tuple, it is passed to the test function
+    as positional arguments.  If a dict, it is a passed via **kw.
+
     """
     paramdicts = {}
     testers = collections.defaultdict(list)
@@ -149,8 +153,12 @@ def parameterize(cls):
             if name.startswith(paramsname):
                 testnameroot = 'test_' + name[len(paramsname):]
                 for paramname, params in paramsdict.items():
-                    test = (lambda self, name=name, params=params:
-                                    getattr(self, name)(*params))
+                    if hasattr(params, 'keys'):
+                        test = (lambda self, name=name, params=params:
+                                    getattr(self, name)(**params))
+                    else:
+                        test = (lambda self, name=name, params=params:
+                                        getattr(self, name)(*params))
                     testname = testnameroot + '_' + paramname
                     test.__name__ = testname
                     testfuncs[testname] = test
index f36e33d43197fb90fcbe69bc297a4a3cc826300b..8e8d67641b894366a5d210299e035c411d1ee771 100644 (file)
@@ -7,6 +7,7 @@ producing RFC valid messages.
 import io
 import unittest
 from email import policy, message_from_bytes
+from email.message import EmailMessage
 from email.generator import BytesGenerator
 from test.test_email import TestEmailBase, parameterize
 
@@ -23,7 +24,10 @@ def dedent(bstr):
 
 
 @parameterize
-class TestInversion(TestEmailBase, unittest.TestCase):
+class TestInversion(TestEmailBase):
+
+    policy = policy.default
+    message = EmailMessage
 
     def msg_as_input(self, msg):
         m = message_from_bytes(msg, policy=policy.SMTP)
@@ -44,6 +48,23 @@ class TestInversion(TestEmailBase, unittest.TestCase):
 
             }
 
+    payload_params = {
+        'plain_text': dict(payload='This is a test\n'*20),
+        'base64_text': dict(payload=(('xy a'*40+'\n')*5), cte='base64'),
+        'qp_text': dict(payload=(('xy a'*40+'\n')*5), cte='quoted-printable'),
+        }
+
+    def payload_as_body(self, payload, **kw):
+        msg = self._make_message()
+        msg['From'] = 'foo'
+        msg['To'] = 'bar'
+        msg['Subject'] = 'payload round trip test'
+        msg.set_content(payload, **kw)
+        b = bytes(msg)
+        msg2 = message_from_bytes(b, policy=self.policy)
+        self.assertEqual(bytes(msg2), b)
+        self.assertEqual(msg2.get_content(), payload)
+
 
 if __name__ == '__main__':
     unittest.main()
index 1922432e0d06b569ec56d13631381cd2a1aaa67b..86d499b29f49dae0a8582520bd26fa915d7c4faa 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -62,6 +62,9 @@ Core and Builtins
 Library
 -------
 
+- Issue #28047: Fixed calculation of line length used for the base64 CTE
+  in the new email policies.
+
 - Issue #27445: Don't pass str(_charset) to MIMEText.set_payload().
   Patch by Claude Paroz.