aboutsummaryrefslogtreecommitdiffstats
path: root/Mailman
diff options
context:
space:
mode:
authorYasuhito FUTATSUKI at POEM <futatuki@poem.co.jp>2021-10-15 05:39:36 +0900
committerYasuhito FUTATSUKI at POEM <futatuki@poem.co.jp>2021-10-15 05:39:36 +0900
commitd4a18da3a7dda34718f7043409f2dbc28a6e97c4 (patch)
tree0b6ce2aa91377c21584f836e650609d427e57ed6 /Mailman
parent393892351c22b83e54b95965d17ae346e5fad989 (diff)
parent6cc831d90d9e22091c05f49e54502d188f7f0712 (diff)
downloadmailman2-d4a18da3a7dda34718f7043409f2dbc28a6e97c4.tar.gz
mailman2-d4a18da3a7dda34718f7043409f2dbc28a6e97c4.tar.xz
mailman2-d4a18da3a7dda34718f7043409f2dbc28a6e97c4.zip
sync merge lp:mailman/2.1 up to 1871
Diffstat (limited to 'Mailman')
-rw-r--r--Mailman/Bouncer.py4
-rw-r--r--Mailman/Bouncers/SimpleMatch.py4
-rwxr-xr-xMailman/Defaults.py.in5
-rw-r--r--Mailman/Handlers/Scrubber.py10
-rw-r--r--Mailman/Handlers/WrapMessage.py10
-rw-r--r--Mailman/Queue/CommandRunner.py5
-rw-r--r--Mailman/Utils.py3
7 files changed, 34 insertions, 7 deletions
diff --git a/Mailman/Bouncer.py b/Mailman/Bouncer.py
index 5077f84c..909f58b0 100644
--- a/Mailman/Bouncer.py
+++ b/Mailman/Bouncer.py
@@ -226,12 +226,14 @@ class Bouncer:
if self.bounce_notify_owner_on_disable:
self.__sendAdminBounceNotice(member, msg)
- def __sendAdminBounceNotice(self, member, msg, did=_('disabled')):
+ def __sendAdminBounceNotice(self, member, msg, did=None):
# BAW: This is a bit kludgey, but we're not providing as much
# information in the new admin bounce notices as we used to (some of
# it was of dubious value). However, we'll provide empty, strange, or
# meaningless strings for the unused %()s fields so that the language
# translators don't have to provide new templates.
+ if did is None:
+ did = _('disabled')
siteowner = Utils.get_site_email(self.host_name)
text = Utils.maketext(
'bounce.txt',
diff --git a/Mailman/Bouncers/SimpleMatch.py b/Mailman/Bouncers/SimpleMatch.py
index 6de9a858..b7889d21 100644
--- a/Mailman/Bouncers/SimpleMatch.py
+++ b/Mailman/Bouncers/SimpleMatch.py
@@ -199,6 +199,10 @@ PATTERNS = [
(_c(r'wasn\'t able to deliver the following message'),
_c(r'---Below this line is a copy of the message.'),
_c(r'To: (?P<addr>[^\s@]+@[^\s@]+)')),
+ # From some unknown MTA
+ (_c(r'This is a delivery failure notification message'),
+ _c(r'The problem appears to be'),
+ _c(r'-- (?P<addr>[^\s@]+@[^\s@]+)')),
# Next one goes here...
]
diff --git a/Mailman/Defaults.py.in b/Mailman/Defaults.py.in
index fea5dcf1..765d705c 100755
--- a/Mailman/Defaults.py.in
+++ b/Mailman/Defaults.py.in
@@ -841,7 +841,10 @@ VERP_PROBES = No
# A perfect opportunity for doing VERP is the password reminders, which are
# already addressed individually to each recipient. Set this to Yes to enable
-# VERPs on all password reminders.
+# VERPs on all password reminders. However, because password reminders are
+# sent from the site list and site list bounces aren't processed but are just
+# forwarded to the site list admins, this isn't too useful. See comments at
+# lines 70-84 of Mailman/Queue/BounceRunner.py for why we don't process them.
VERP_PASSWORD_REMINDERS = No
# Another good opportunity is when regular delivery is personalized. Here
diff --git a/Mailman/Handlers/Scrubber.py b/Mailman/Handlers/Scrubber.py
index cecd11fb..a498f814 100644
--- a/Mailman/Handlers/Scrubber.py
+++ b/Mailman/Handlers/Scrubber.py
@@ -90,6 +90,9 @@ def guess_extension(ctype, ext):
if ctype.lower == 'application/octet-stream':
# For this type, all[0] is '.obj'. '.bin' is better.
return '.bin'
+ if ctype.lower == 'text/plain':
+ # For this type, all[0] is '.ksh'. '.txt' is better.
+ return '.txt'
return all and all[0]
@@ -196,8 +199,11 @@ def process(mlist, msg, msgdata=None):
format = part.get_param('format')
delsp = part.get_param('delsp')
# TK: if part is attached then check charset and scrub if none
- if part.get('content-disposition') and \
- not part.get_content_charset():
+ # MAS: Content-Disposition is not a good test for 'attached'.
+ # RFC 2183 sec. 2.10 allows Content-Disposition on the main body.
+ # Make it specifically 'attachment'.
+ if (part.get('content-disposition', '').lower() == 'attachment'
+ and not part.get_content_charset()):
omask = os.umask(002)
try:
url = save_attachment(mlist, part, dir)
diff --git a/Mailman/Handlers/WrapMessage.py b/Mailman/Handlers/WrapMessage.py
index 0ee08cb1..3aef64a2 100644
--- a/Mailman/Handlers/WrapMessage.py
+++ b/Mailman/Handlers/WrapMessage.py
@@ -63,13 +63,19 @@ def process(mlist, msg, msgdata):
# make a copy of the msg, then delete almost everything and set/copy
# what we want.
omsg = copy.deepcopy(msg)
+ # If CookHeaders didn't change the Subject: we need to keep it too.
+ # Get a fresh list.
+ keepers = list(KEEPERS)
+ if 'subject' not in [key.lower() for key in
+ msgdata.get('add_header', {}).keys()]:
+ keepers.append('subject')
for key in msg.keys():
- if key.lower() not in KEEPERS:
+ if key.lower() not in keepers:
del msg[key]
msg['MIME-Version'] = '1.0'
msg['Message-ID'] = Utils.unique_message_id(mlist)
# Add the headers from CookHeaders.
- for k, v in msgdata['add_header'].items():
+ for k, v in msgdata.get('add_header', {}).items():
msg[k] = v
# Are we including dmarc_wrapped_message_text? I.e., do we have text and
# are we wrapping because of dmarc_moderation_action?
diff --git a/Mailman/Queue/CommandRunner.py b/Mailman/Queue/CommandRunner.py
index 6ea50255..3c21065f 100644
--- a/Mailman/Queue/CommandRunner.py
+++ b/Mailman/Queue/CommandRunner.py
@@ -100,6 +100,11 @@ class Results:
# E.g the outer Content-Type: was text/html
return
body = part.get_payload(decode=True)
+ if (part.get_content_charset(None)):
+ body = unicode(body, part.get_content_charset(),
+ errors='replace').encode(
+ Utils.GetCharSet(self.msgdata['lang']),
+ errors='replace')
# text/plain parts better have string payloads
assert isinstance(body, StringType) or isinstance(body, UnicodeType)
lines = body.splitlines()
diff --git a/Mailman/Utils.py b/Mailman/Utils.py
index 2615229b..c61f7e2c 100644
--- a/Mailman/Utils.py
+++ b/Mailman/Utils.py
@@ -1380,8 +1380,9 @@ def _DMARCProhibited(mlist, email, dmarc_domain, org=False):
if len(dmarcs) > 1:
syslog('error',
"""RRset of TXT records for %s has %d v=DMARC1 entries;
- testing them all""",
+ ignoring them per RFC 7849""",
dmarc_domain, len(dmarcs))
+ return False
for entry in dmarcs:
mo = re.search(r'\bsp=(\w*)\b', entry, re.IGNORECASE)
if org and mo: