You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@allura.apache.org by di...@apache.org on 2021/12/16 17:30:40 UTC
[allura] 01/01: fix email headers being longer than SMTP limit
This is an automated email from the ASF dual-hosted git repository.
dill0wn pushed a commit to branch dw/smtp_line_length
in repository https://gitbox.apache.org/repos/asf/allura.git
commit ac7e02c01b7a643157f8fb62aa384b0d3cdd1aab
Author: Dillon Walls <di...@slashdotmedia.com>
AuthorDate: Thu Dec 16 17:30:33 2021 +0000
fix email headers being longer than SMTP limit
---
Allura/allura/lib/mail_util.py | 27 +++++++++++++++++++++------
Allura/allura/tests/test_tasks.py | 6 ++++--
2 files changed, 25 insertions(+), 8 deletions(-)
diff --git a/Allura/allura/lib/mail_util.py b/Allura/allura/lib/mail_util.py
index 9b50e46..36a3b19 100644
--- a/Allura/allura/lib/mail_util.py
+++ b/Allura/allura/lib/mail_util.py
@@ -17,6 +17,7 @@
from __future__ import unicode_literals
from __future__ import absolute_import
+from __future__ import annotations
import re
import logging
import smtplib
@@ -24,6 +25,7 @@ import email.parser
from six.moves.email_mime_multipart import MIMEMultipart
from six.moves.email_mime_text import MIMEText
from email import header
+import typing
import six
import tg
@@ -37,6 +39,9 @@ from allura.lib import exceptions as exc
from allura.lib import helpers as h
from six.moves import map
+if typing.TYPE_CHECKING:
+ from email.message import EmailMessage
+
log = logging.getLogger(__name__)
RE_MESSAGE_ID = re.compile(r'<(?:[^>]*/)?([^>]*)>')
@@ -47,6 +52,9 @@ config = ConfigProxy(
)
EMAIL_VALIDATOR = fev.Email(not_empty=True)
+# http://www.jebriggs.com/blog/2010/07/smtp-maximum-line-lengths/
+MAX_MAIL_LINE_OCTETS = 998 # RFC 1000 - len(CRLF)
+
def Header(text, *more_text):
'''Helper to make sure we encode headers properly'''
@@ -190,10 +198,6 @@ def identify_sender(peer, email_address, headers, msg):
return M.User.anonymous()
-# http://www.jebriggs.com/blog/2010/07/smtp-maximum-line-lengths/
-MAX_MAIL_LINE_OCTETS = 990
-
-
def encode_email_part(content, content_type):
try:
# simplest email - plain ascii
@@ -264,7 +268,7 @@ class SMTPClient(object):
self._client = None
def sendmail(
- self, addrs, fromaddr, reply_to, subject, message_id, in_reply_to, message,
+ self, addrs, fromaddr, reply_to, subject, message_id, in_reply_to, message: EmailMessage,
sender=None, references=None, cc=None, to=None):
if not addrs:
return
@@ -291,7 +295,18 @@ class SMTPClient(object):
if references:
references = ['<%s>' % r for r in aslist(references)]
message['References'] = Header(*references)
- content = message.as_string()
+
+ # Kind of Hacky, but...
+ # Certain headers, like 'References' can become very long when sent via reply
+ # from deep inside a ticket thread. message.as_string allows you to pass a
+ # maxheaderlen which splits long lines for you to fit inside your exim constraints.
+ # HOWEVER, that flag doesn't take the header name length into account. So, this
+ # somewhat hacky code approximates the longest 'Header-Name: ' prefix and makes sure
+ # the line octet length takes that into account.
+ longest_header_len = max(len(h[0]) for h in message._headers)
+ max_header_len = MAX_MAIL_LINE_OCTETS - (2 + longest_header_len)
+
+ content = message.as_string(maxheaderlen=max_header_len)
smtp_addrs = list(map(_parse_smtp_addr, addrs))
smtp_addrs = [a for a in smtp_addrs if isvalid(a)]
if not smtp_addrs:
diff --git a/Allura/allura/tests/test_tasks.py b/Allura/allura/tests/test_tasks.py
index 7c73399..6ac5691 100644
--- a/Allura/allura/tests/test_tasks.py
+++ b/Allura/allura/tests/test_tasks.py
@@ -34,7 +34,7 @@ import mock
from tg import tmpl_context as c, app_globals as g
from datadiff.tools import assert_equal
-from nose.tools import assert_in, assert_less
+from nose.tools import assert_in, assert_less, assert_less_equal
from ming.orm import FieldProperty, Mapper
from ming.orm import ThreadLocalORMSession
from testfixtures import LogCapture
@@ -46,6 +46,7 @@ from allura.command.taskd import TaskdCommand
from allura.lib import helpers as h
from allura.lib import search
from allura.lib.exceptions import CompoundError
+from allura.lib.mail_util import MAX_MAIL_LINE_OCTETS
from allura.tasks import event_tasks
from allura.tasks import index_tasks
from allura.tasks import mail_tasks
@@ -475,12 +476,13 @@ class TestMailTasks(unittest.TestCase):
text=('0123456789' * 100) + '\n\n' + ('Громады стро ' * 100),
reply_to=g.noreply,
subject='По оживлённым берегам',
+ references=['foo@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('\n')
for line in body:
- assert_less(len(line), 991)
+ assert_less_equal(len(line), MAX_MAIL_LINE_OCTETS)
# plain text
assert_in('012345678901234567890123456789012345678901234567890123456789012345678901234=', body)