You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@allura.apache.org by br...@apache.org on 2020/08/27 20:35:26 UTC

[allura] 01/16: [#8375] various mail formatting/encoding fixes for py3

This is an automated email from the ASF dual-hosted git repository.

brondsem pushed a commit to branch db/8375
in repository https://gitbox.apache.org/repos/asf/allura.git

commit d32ccf8ba17a357783262a7cbbd0926f01dcc6b2
Author: Dave Brondsema <da...@brondsema.net>
AuthorDate: Mon Aug 24 17:38:51 2020 -0400

    [#8375] various mail formatting/encoding fixes for py3
---
 Allura/allura/app.py                                |  2 +-
 Allura/allura/lib/mail_util.py                      |  2 +-
 Allura/allura/model/auth.py                         |  4 +++-
 Allura/allura/tests/functional/test_user_profile.py |  2 +-
 Allura/allura/tests/test_mail_util.py               |  2 +-
 Allura/allura/tests/test_tasks.py                   | 21 ++++++++++-----------
 .../forgediscussion/tests/functional/test_forum.py  |  3 +++
 7 files changed, 20 insertions(+), 16 deletions(-)

diff --git a/Allura/allura/app.py b/Allura/allura/app.py
index ef751ef..fb59e52 100644
--- a/Allura/allura/app.py
+++ b/Allura/allura/app.py
@@ -736,7 +736,7 @@ class Application(object):
                 thread_id=thd._id,
                 post_id=message_id)
         else:
-            text = message['payload'] or '--no text body--'
+            text = six.ensure_text(message['payload']) or '--no text body--'
             post = thd.post(
                 message_id=message_id,
                 parent_id=parent_id,
diff --git a/Allura/allura/lib/mail_util.py b/Allura/allura/lib/mail_util.py
index 9d61333..3c417b4 100644
--- a/Allura/allura/lib/mail_util.py
+++ b/Allura/allura/lib/mail_util.py
@@ -201,7 +201,7 @@ def encode_email_part(content, content_type):
             # switch to Quoted-Printable encoding to avoid too-long lines
             # we could always Quoted-Printabl, but it makes the output a little messier and less human-readable
             # the particular order of all these operations seems to be very important for everything to end up right
-            msg = MIMEText(None, content_type)
+            msg = MIMEText('', content_type)
             msg.replace_header('content-transfer-encoding', 'quoted-printable')
             cs = email.charset.Charset('utf-8')
             cs.header_encoding = email.charset.QP
diff --git a/Allura/allura/model/auth.py b/Allura/allura/model/auth.py
index 10c6550..65e47dc 100644
--- a/Allura/allura/model/auth.py
+++ b/Allura/allura/model/auth.py
@@ -20,6 +20,7 @@ from __future__ import absolute_import
 import logging
 import calendar
 
+import six
 from markupsafe import Markup
 from six.moves.urllib.parse import urlparse
 from email import header
@@ -791,7 +792,8 @@ class User(MappedClass, ActivityNode, ActivityObject, SearchIndexable):
 
     def email_address_header(self):
         h = header.Header()
-        h.append('"%s" ' % self.get_pref('display_name'))
+        h.append('"%s"%s' % (self.get_pref('display_name'),
+                             ' ' if six.PY2 else ''))  # py2 needs explicit space for unicode/text_type cast of Header
         h.append('<%s>' % self.get_pref('email_address'))
         return h
 
diff --git a/Allura/allura/tests/functional/test_user_profile.py b/Allura/allura/tests/functional/test_user_profile.py
index 96162ca..4583da3 100644
--- a/Allura/allura/tests/functional/test_user_profile.py
+++ b/Allura/allura/tests/functional/test_user_profile.py
@@ -115,7 +115,7 @@ class TestUserProfile(TestController):
         response = self.app.get(
             '/u/test-user/profile/send_message', status=200)
         assert 'you currently have user messages disabled' not in response
-        assert '<b>From:</b> &#34;Test Admin&#34; &lt;test-admin@users.localhost&gt;' in response
+        response.mustcontain('<b>From:</b> &#34;Test Admin&#34; &lt;test-admin@users.localhost&gt;')
 
         self.app.post('/u/test-user/profile/send_user_message',
                       params={'subject': 'test subject',
diff --git a/Allura/allura/tests/test_mail_util.py b/Allura/allura/tests/test_mail_util.py
index 3c107be..7391aec 100644
--- a/Allura/allura/tests/test_mail_util.py
+++ b/Allura/allura/tests/test_mail_util.py
@@ -210,7 +210,7 @@ Content-Type: text/html; charset="utf-8"
         for part in msg2['parts']:
             if part['payload'] is None:
                 continue
-            assert isinstance(part['payload'], six.text_type)
+            assert isinstance(part['payload'], six.text_type), type(part['payload'])
 
 
 class TestHeader(object):
diff --git a/Allura/allura/tests/test_tasks.py b/Allura/allura/tests/test_tasks.py
index 6c82b52..bacf6c1 100644
--- a/Allura/allura/tests/test_tasks.py
+++ b/Allura/allura/tests/test_tasks.py
@@ -23,6 +23,8 @@ import operator
 import shutil
 import sys
 import unittest
+
+import six
 from base64 import b64encode
 import logging
 import pkg_resources
@@ -143,9 +145,6 @@ class TestEventTasks(unittest.TestCase):
         assert M.MonQTask.query.get(task_name='allura.tasks.event_tasks.event', args=['my_event4'])
 
     def test_compound_error(self):
-        '''test_compound_exception -- make sure our multi-exception return works
-        OK
-        '''
         t = raise_exc.post()
         with LogCapture(level=logging.ERROR) as l, \
                 mock.patch.dict(tg.config, {'monq.raise_errors': False}):  # match normal non-test behavior
@@ -153,8 +152,8 @@ class TestEventTasks(unittest.TestCase):
         # l.check() would be nice, but string is too detailed to check
         assert_equal(l.records[0].name, 'allura.model.monq_model')
         msg = l.records[0].getMessage()
-        assert_in("AssertionError('assert 0',)", msg)
-        assert_in("AssertionError('assert 5',)", msg)
+        assert_in("AssertionError('assert 0'", msg)
+        assert_in("AssertionError('assert 5'", msg)
         assert_in(' on job <MonQTask ', msg)
         assert_in(' (error) P:10 allura.tests.test_tasks.raise_exc ', msg)
         for x in range(10):
@@ -297,16 +296,16 @@ class TestMailTasks(unittest.TestCase):
             assert_in('Reply-To: %s' % g.noreply, body)
 
             # The address portion must not be encoded, only the name portion can be.
-            # Also it is apparently not necessary to have the double-quote separators present
-            # when the name portion is encoded.  That is, the encoding below is
-            # just По and not "По"
-            assert_in('From: =?utf-8?b?0J/Qvg==?= <fo...@bar.com>', body)
+            # Also py2 and py3 vary in handling of double-quote separators when the name portion is encoded
+            unquoted_cyrillic_No = '=?utf-8?b?0J/Qvg==?='  # По
+            quoted_cyrillic_No = '=?utf-8?b?ItCf0L4i?='  # "По"
+            assert ('From: {} <fo...@bar.com>'.format(quoted_cyrillic_No) in body or
+                    'From: {} <fo...@bar.com>'.format(unquoted_cyrillic_No) in body), body
             assert_in(
                 'Subject: =?utf-8?b?0J/QviDQvtC20LjQstC70ZHQvdC90YvQvCDQsdC10YDQtdCz0LDQvA==?=', body)
             assert_in('Content-Type: text/plain; charset="utf-8"', body)
             assert_in('Content-Transfer-Encoding: base64', body)
-            assert_in(
-                b64encode('Громады стройные теснятся'.encode('utf-8')), body)
+            assert_in(six.ensure_text(b64encode('Громады стройные теснятся'.encode('utf-8'))), body)
 
     def test_send_email_with_disabled_user(self):
         c.user = M.User.by_username('test-admin')
diff --git a/ForgeDiscussion/forgediscussion/tests/functional/test_forum.py b/ForgeDiscussion/forgediscussion/tests/functional/test_forum.py
index 657262a..a1d2614 100644
--- a/ForgeDiscussion/forgediscussion/tests/functional/test_forum.py
+++ b/ForgeDiscussion/forgediscussion/tests/functional/test_forum.py
@@ -212,12 +212,15 @@ class TestForumMessageHandling(TestController):
         assert_equal(FM.ForumPost.query.find().count(), 3)
 
     def test_attach(self):
+        # runs handle_artifact_message() with filename field
         self._post('testforum', 'Attachment Thread', 'This is text attachment',
                    message_id='test.attach.100@domain.net',
                    filename='test.txt',
                    content_type='text/plain')
+        # runs handle_artifact_message() where there's no post with given message_id yet
         self._post('testforum', 'Test Thread', b'Nothing here',
                    message_id='test.attach.100@domain.net')
+        # runs handle_artifact_message() where there IS a post with given message_id
         self._post('testforum', 'Attachment Thread', 'This is binary ¶¬¡™£¢¢•º™™¶'.encode('utf-8'),
                    message_id='test.attach.100@domain.net',
                    content_type='text/plain')