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

kentontaylor pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/allura.git

commit c1062c9aef1303327890cb9b92117ea505754efe
Author: Dave Brondsema <dbronds...@slashdotmedia.com>
AuthorDate: Tue Mar 12 10:32:37 2024 -0400

    encode emails when the body has long lines.  [#8533] erroneously removed 
handling of it.  This is a better solution than before too
---
 Allura/allura/lib/mail_util.py    |  5 +++++
 Allura/allura/tests/test_tasks.py | 31 +++++++++++++++++++------------
 2 files changed, 24 insertions(+), 12 deletions(-)

diff --git a/Allura/allura/lib/mail_util.py b/Allura/allura/lib/mail_util.py
index 24f1eb8c6..285c12d73 100644
--- a/Allura/allura/lib/mail_util.py
+++ b/Allura/allura/lib/mail_util.py
@@ -194,6 +194,11 @@ def encode_email_part(content, content_type):
         # simplest email - plain ascii
         encoded_content = content.encode('ascii')
         encoding = 'ascii'
+        for line in encoded_content.splitlines():
+            if len(line) > MAX_MAIL_LINE_OCTETS:
+                # force base64 content-encoding to make lines shorter
+                encoding = 'utf-8'
+                break
     except Exception:
         # utf8 will get base64 encoded so we only do it if ascii fails
         encoded_content = content.encode('utf-8')
diff --git a/Allura/allura/tests/test_tasks.py 
b/Allura/allura/tests/test_tasks.py
index 56ab38f55..54e936ec6 100644
--- a/Allura/allura/tests/test_tasks.py
+++ b/Allura/allura/tests/test_tasks.py
@@ -14,7 +14,8 @@
 #       KIND, either express or implied.  See the License for the
 #       specific language governing permissions and limitations
 #       under the License.
-
+import email.parser
+import email.iterators
 import operator
 import shutil
 from textwrap import dedent
@@ -28,6 +29,7 @@ import pkg_resources
 import tg
 import mock
 from tg import tmpl_context as c, app_globals as g
+import pytest
 
 from ming.odm import FieldProperty, Mapper
 from ming.odm import ThreadLocalODMSession
@@ -464,29 +466,34 @@ class TestMailTasks:
             return_path, rcpts, body = _client.sendmail.call_args[0]
             assert 'From: "Test Admin" <test-admin@users.localhost>' in body
 
-    def test_send_email_long_lines_use_quoted_printable(self):
+    @pytest.mark.parametrize('bodychars', [
+        '0123456789',  # plain ascii is handled different since it doesn't 
necessarily need to be encoded
+        'Громады стро ',
+    ])
+    def test_send_email_long_lines(self, bodychars):
         with mock.patch.object(mail_tasks.smtp_client, '_client') as _client:
             mail_tasks.sendsimplemail(
                 fromaddr='"По" <f...@bar.com>',
                 toaddr='b...@blah.com',
-                text=('0123456789' * 100) + '\n\n' + ('Громады стро ' * 100),
+                text=bodychars * 100,
                 reply_to=g.noreply,
                 subject='123451234512345' * 100,
                 references=['f...@example.com'] * 100,  # needs to handle 
really long headers as well
                 message_id=h.gen_message_id())
             return_path, rcpts, body = _client.sendmail.call_args[0]
-            body = body.split(email_policy.linesep)
+            body_lines = body.split(email_policy.linesep)
 
-            for line in body:
+            for line in body_lines:
                 assert len(line) <= MAX_MAIL_LINE_OCTETS
 
-            bodystr = ''.join(body)
-            # plain text
-            assert b64encode(b'012345678901234567890123').decode('utf8') in 
bodystr
-            assert b64encode('Громады стро '.encode('utf8')).decode('utf8') in 
bodystr
-            # html
-            assert b64encode(b'<div 
class="markdown_content"><p>012345678901234567890123').decode('utf8') in bodystr
-            assert b64encode('<p>Громады стро '.encode('utf8')).decode('utf8') 
in bodystr
+            msg = email.parser.Parser().parsestr(body)
+            plain_subpart = next(email.iterators.typed_subpart_iterator(msg, 
'text', 'plain'))
+            plain = plain_subpart.get_payload(decode=True).decode('utf-8')
+            html_subpart = next(email.iterators.typed_subpart_iterator(msg, 
'text', 'html')).get_payload(decode=True)
+            html = html_subpart.decode('utf-8')
+
+            assert (bodychars + bodychars) in plain
+            assert f'<div class="markdown_content"><p>{bodychars}{bodychars}' 
in html
 
     @td.with_wiki
     def test_receive_email_ok(self):

Reply via email to