Skip to content

Commit c1062c9

Browse files
committed
encode emails when the body has long lines. [#8533] erroneously removed handling of it. This is a better solution than before too
1 parent d44e0aa commit c1062c9

File tree

2 files changed

+24
-12
lines changed

2 files changed

+24
-12
lines changed

Allura/allura/lib/mail_util.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,11 @@ def encode_email_part(content, content_type):
194194
# simplest email - plain ascii
195195
encoded_content = content.encode('ascii')
196196
encoding = 'ascii'
197+
for line in encoded_content.splitlines():
198+
if len(line) > MAX_MAIL_LINE_OCTETS:
199+
# force base64 content-encoding to make lines shorter
200+
encoding = 'utf-8'
201+
break
197202
except Exception:
198203
# utf8 will get base64 encoded so we only do it if ascii fails
199204
encoded_content = content.encode('utf-8')

Allura/allura/tests/test_tasks.py

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@
1414
# KIND, either express or implied. See the License for the
1515
# specific language governing permissions and limitations
1616
# under the License.
17-
17+
import email.parser
18+
import email.iterators
1819
import operator
1920
import shutil
2021
from textwrap import dedent
@@ -28,6 +29,7 @@
2829
import tg
2930
import mock
3031
from tg import tmpl_context as c, app_globals as g
32+
import pytest
3133

3234
from ming.odm import FieldProperty, Mapper
3335
from ming.odm import ThreadLocalODMSession
@@ -464,29 +466,34 @@ def test_fromaddr_objectid_not_str(self):
464466
return_path, rcpts, body = _client.sendmail.call_args[0]
465467
assert 'From: "Test Admin" <test-admin@users.localhost>' in body
466468

467-
def test_send_email_long_lines_use_quoted_printable(self):
469+
@pytest.mark.parametrize('bodychars', [
470+
'0123456789', # plain ascii is handled different since it doesn't necessarily need to be encoded
471+
'Громады стро ',
472+
])
473+
def test_send_email_long_lines(self, bodychars):
468474
with mock.patch.object(mail_tasks.smtp_client, '_client') as _client:
469475
mail_tasks.sendsimplemail(
470476
fromaddr='"По" <foo@bar.com>',
471477
toaddr='blah@blah.com',
472-
text=('0123456789' * 100) + '\n\n' + ('Громады стро ' * 100),
478+
text=bodychars * 100,
473479
reply_to=g.noreply,
474480
subject='123451234512345' * 100,
475481
references=['foo@example.com'] * 100, # needs to handle really long headers as well
476482
message_id=h.gen_message_id())
477483
return_path, rcpts, body = _client.sendmail.call_args[0]
478-
body = body.split(email_policy.linesep)
484+
body_lines = body.split(email_policy.linesep)
479485

480-
for line in body:
486+
for line in body_lines:
481487
assert len(line) <= MAX_MAIL_LINE_OCTETS
482488

483-
bodystr = ''.join(body)
484-
# plain text
485-
assert b64encode(b'012345678901234567890123').decode('utf8') in bodystr
486-
assert b64encode('Громады стро '.encode('utf8')).decode('utf8') in bodystr
487-
# html
488-
assert b64encode(b'<div class="markdown_content"><p>012345678901234567890123').decode('utf8') in bodystr
489-
assert b64encode('<p>Громады стро '.encode('utf8')).decode('utf8') in bodystr
489+
msg = email.parser.Parser().parsestr(body)
490+
plain_subpart = next(email.iterators.typed_subpart_iterator(msg, 'text', 'plain'))
491+
plain = plain_subpart.get_payload(decode=True).decode('utf-8')
492+
html_subpart = next(email.iterators.typed_subpart_iterator(msg, 'text', 'html')).get_payload(decode=True)
493+
html = html_subpart.decode('utf-8')
494+
495+
assert (bodychars + bodychars) in plain
496+
assert f'<div class="markdown_content"><p>{bodychars}{bodychars}' in html
490497

491498
@td.with_wiki
492499
def test_receive_email_ok(self):

0 commit comments

Comments
 (0)