summaryrefslogtreecommitdiff
path: root/mailman/pipeline
diff options
context:
space:
mode:
Diffstat (limited to 'mailman/pipeline')
-rw-r--r--mailman/pipeline/__init__.py2
-rw-r--r--mailman/pipeline/acknowledge.py6
-rw-r--r--mailman/pipeline/after_delivery.py2
-rw-r--r--mailman/pipeline/avoid_duplicates.py6
-rw-r--r--mailman/pipeline/calculate_recipients.py12
-rw-r--r--mailman/pipeline/cleanse.py6
-rw-r--r--mailman/pipeline/cleanse_dkim.py2
-rw-r--r--mailman/pipeline/cook_headers.py21
-rw-r--r--mailman/pipeline/decorate.py29
-rw-r--r--mailman/pipeline/docs/archives.txt10
-rw-r--r--mailman/pipeline/docs/digests.txt57
-rw-r--r--mailman/pipeline/docs/nntp.txt9
-rw-r--r--mailman/pipeline/docs/to-outgoing.txt13
-rw-r--r--mailman/pipeline/file_recipients.py2
-rw-r--r--mailman/pipeline/mime_delete.py21
-rw-r--r--mailman/pipeline/moderate.py8
-rw-r--r--mailman/pipeline/owner_recipients.py11
-rw-r--r--mailman/pipeline/replybot.py10
-rw-r--r--mailman/pipeline/scrubber.py2
-rw-r--r--mailman/pipeline/tagger.py18
-rw-r--r--mailman/pipeline/to_archive.py2
-rw-r--r--mailman/pipeline/to_digest.py14
-rw-r--r--mailman/pipeline/to_outgoing.py2
-rw-r--r--mailman/pipeline/to_usenet.py6
24 files changed, 172 insertions, 99 deletions
diff --git a/mailman/pipeline/__init__.py b/mailman/pipeline/__init__.py
index d6e1b0129..f73061874 100644
--- a/mailman/pipeline/__init__.py
+++ b/mailman/pipeline/__init__.py
@@ -17,6 +17,8 @@
"""The built in set of pipeline handlers."""
+from __future__ import absolute_import, unicode_literals
+
__metaclass__ = type
__all__ = [
'initialize',
diff --git a/mailman/pipeline/acknowledge.py b/mailman/pipeline/acknowledge.py
index f1bd585f6..de520df65 100644
--- a/mailman/pipeline/acknowledge.py
+++ b/mailman/pipeline/acknowledge.py
@@ -20,8 +20,12 @@
This only happens if the sender has set their AcknowledgePosts attribute.
"""
+from __future__ import absolute_import, unicode_literals
+
__metaclass__ = type
-__all__ = ['Acknowledge']
+__all__ = [
+ 'Acknowledge',
+ ]
from zope.interface import implements
diff --git a/mailman/pipeline/after_delivery.py b/mailman/pipeline/after_delivery.py
index d19d4a541..4626ba292 100644
--- a/mailman/pipeline/after_delivery.py
+++ b/mailman/pipeline/after_delivery.py
@@ -17,6 +17,8 @@
"""Perform some bookkeeping after a successful post."""
+from __future__ import absolute_import, unicode_literals
+
__metaclass__ = type
__all__ = [
'AfterDelivery',
diff --git a/mailman/pipeline/avoid_duplicates.py b/mailman/pipeline/avoid_duplicates.py
index 10c047004..0458e117c 100644
--- a/mailman/pipeline/avoid_duplicates.py
+++ b/mailman/pipeline/avoid_duplicates.py
@@ -23,8 +23,12 @@ has already received a copy, we either drop the message, add a duplicate
warning header, or pass it through, depending on the user's preferences.
"""
+from __future__ import absolute_import, unicode_literals
+
__metaclass__ = type
-__all__ = ['AvoidDuplicates']
+__all__ = [
+ 'AvoidDuplicates',
+ ]
from email.Utils import getaddresses, formataddr
diff --git a/mailman/pipeline/calculate_recipients.py b/mailman/pipeline/calculate_recipients.py
index 9385c64e8..9837c1e6b 100644
--- a/mailman/pipeline/calculate_recipients.py
+++ b/mailman/pipeline/calculate_recipients.py
@@ -23,8 +23,12 @@ on the `recips' attribute of the message. This attribute is used by the
SendmailDeliver and BulkDeliver modules.
"""
+from __future__ import absolute_import, unicode_literals
+
__metaclass__ = type
-__all__ = ['CalculateRecipients']
+__all__ = [
+ 'CalculateRecipients',
+ ]
from zope.interface import implements
@@ -83,7 +87,7 @@ class CalculateRecipients:
Your urgent message to the %(realname)s mailing list was not authorized for
delivery. The original message as received by Mailman is attached.
""")
- raise errors.RejectMessage, Utils.wrap(text)
+ raise errors.RejectMessage(Utils.wrap(text))
# Calculate the regular recipients of the message
recips = set(member.address.address
for member in mlist.regular_members.members
@@ -133,8 +137,8 @@ def do_topic_filters(mlist, msg, msgdata, recips):
# The user did not select any topics of interest, so he gets
# this message by default.
continue
- if not mlist.getMemberOption(user,
- config.ReceiveNonmatchingTopics):
+ if not mlist.getMemberOption(
+ user, config.ReceiveNonmatchingTopics):
# The user has interest in some topics, but elects not to
# receive message that match no topics, so zap him.
zaprecips.append(user)
diff --git a/mailman/pipeline/cleanse.py b/mailman/pipeline/cleanse.py
index 28c660bdc..330f415c2 100644
--- a/mailman/pipeline/cleanse.py
+++ b/mailman/pipeline/cleanse.py
@@ -17,8 +17,12 @@
"""Cleanse certain headers from all messages."""
+from __future__ import absolute_import, unicode_literals
+
__metaclass__ = type
-__all__ = ['Cleanse']
+__all__ = [
+ 'Cleanse',
+ ]
import logging
diff --git a/mailman/pipeline/cleanse_dkim.py b/mailman/pipeline/cleanse_dkim.py
index 774fa78cf..38623079c 100644
--- a/mailman/pipeline/cleanse_dkim.py
+++ b/mailman/pipeline/cleanse_dkim.py
@@ -25,6 +25,8 @@ and it will also give the MTA the opportunity to regenerate valid keys
originating at the Mailman server for the outgoing message.
"""
+from __future__ import absolute_import, unicode_literals
+
__metaclass__ = type
__all__ = [
'CleanseDKIM',
diff --git a/mailman/pipeline/cook_headers.py b/mailman/pipeline/cook_headers.py
index 88051970e..529d7ce5d 100644
--- a/mailman/pipeline/cook_headers.py
+++ b/mailman/pipeline/cook_headers.py
@@ -17,6 +17,8 @@
"""Cook a message's headers."""
+from __future__ import absolute_import, unicode_literals
+
__metaclass__ = type
__all__ = [
'CookHeaders',
@@ -178,7 +180,7 @@ def process(mlist, msg, msgdata):
if msgdata.get('_nolist') or not mlist.include_rfc2369_headers:
return
# This will act like an email address for purposes of formataddr()
- listid = '%s.%s' % (mlist.list_name, mlist.host_name)
+ listid = '{0}.{1}'.format(mlist.list_name, mlist.host_name)
cset = Utils.GetCharSet(mlist.preferred_language)
if mlist.description:
# Don't wrap the header since here we just want to get it properly RFC
@@ -187,7 +189,7 @@ def process(mlist, msg, msgdata):
listid_h = formataddr((str(i18ndesc), listid))
else:
# without desc we need to ensure the MUST brackets
- listid_h = '<%s>' % listid
+ listid_h = '<{0}>'.format(listid)
# We always add a List-ID: header.
del msg['list-id']
msg['List-Id'] = listid_h
@@ -195,7 +197,7 @@ def process(mlist, msg, msgdata):
# "X-List-Administrivia: yes" header. For all others (i.e. those coming
# from list posts), we add a bunch of other RFC 2369 headers.
requestaddr = mlist.request_address
- subfieldfmt = '<%s>, <mailto:%s>'
+ subfieldfmt = '<{0}>, <mailto:{1}>'
listinfo = mlist.script_url('listinfo')
headers = {}
# XXX reduced_list_headers used to suppress List-Help, List-Subject, and
@@ -203,20 +205,21 @@ def process(mlist, msg, msgdata):
# any more, so always add those three headers (others will still be
# suppressed).
headers.update({
- 'List-Help' : '<mailto:%s?subject=help>' % requestaddr,
- 'List-Unsubscribe': subfieldfmt % (listinfo, mlist.leave_address),
- 'List-Subscribe' : subfieldfmt % (listinfo, mlist.join_address),
+ 'List-Help' : '<mailto:{0}?subject=help>'.format(requestaddr),
+ 'List-Unsubscribe': subfieldfmt.format(listinfo, mlist.leave_address),
+ 'List-Subscribe' : subfieldfmt.format(listinfo, mlist.join_address),
})
if msgdata.get('reduced_list_headers'):
headers['X-List-Administrivia'] = 'yes'
else:
# List-Post: is controlled by a separate attribute
if mlist.include_list_post_header:
- headers['List-Post'] = '<mailto:%s>' % mlist.posting_address
+ headers['List-Post'] = '<mailto:{0}>'.format(mlist.posting_address)
# Add RFC 2369 and 5064 archiving headers, if archiving is enabled.
if mlist.archive:
for archiver in config.archivers:
- headers['List-Archive'] = '<%s>' % archiver.list_url(mlist)
+ headers['List-Archive'] = '<{0}>'.format(
+ archiver.list_url(mlist))
permalink = archiver.permalink(mlist, msg)
if permalink is not None:
headers['Archived-At'] = permalink
@@ -333,7 +336,7 @@ def ch_oneline(headerstr):
cset = 'utf-8'
h = make_header(d)
ustr = unicode(h)
- oneline = u''.join(ustr.splitlines())
+ oneline = ''.join(ustr.splitlines())
return oneline.encode(cset, 'replace'), cset
except (LookupError, UnicodeError, ValueError, HeaderParseError):
# possibly charset problem. return with undecoded string in one line.
diff --git a/mailman/pipeline/decorate.py b/mailman/pipeline/decorate.py
index bf9fbea80..82851fbf1 100644
--- a/mailman/pipeline/decorate.py
+++ b/mailman/pipeline/decorate.py
@@ -17,15 +17,18 @@
"""Decorate a message by sticking the header and footer around it."""
+from __future__ import absolute_import, unicode_literals
+
__metaclass__ = type
-__all__ = ['Decorate']
+__all__ = [
+ 'Decorate',
+ ]
import re
import logging
from email.MIMEText import MIMEText
-from string import Template
from zope.interface import implements
from mailman import Utils
@@ -33,6 +36,7 @@ from mailman.Message import Message
from mailman.config import config
from mailman.i18n import _
from mailman.interfaces.handler import IHandler
+from mailman.utilities.string import expand
log = logging.getLogger('mailman.error')
@@ -197,17 +201,18 @@ def decorate(mlist, template, extradict=None):
# Create a dictionary which includes the default set of interpolation
# variables allowed in headers and footers. These will be augmented by
# any key/value pairs in the extradict.
- d = dict(real_name = mlist.real_name,
- list_name = mlist.list_name,
- fqdn_listname = mlist.fqdn_listname,
- host_name = mlist.host_name,
- listinfo_page = mlist.script_url('listinfo'),
- description = mlist.description,
- info = mlist.info,
- )
+ substitutions = dict(
+ real_name = mlist.real_name,
+ list_name = mlist.list_name,
+ fqdn_listname = mlist.fqdn_listname,
+ host_name = mlist.host_name,
+ listinfo_page = mlist.script_url('listinfo'),
+ description = mlist.description,
+ info = mlist.info,
+ )
if extradict is not None:
- d.update(extradict)
- text = Template(template).safe_substitute(d)
+ substitutions.update(extradict)
+ text = expand(template, substitutions)
# Turn any \r\n line endings into just \n
return re.sub(r' *\r?\n', r'\n', text)
diff --git a/mailman/pipeline/docs/archives.txt b/mailman/pipeline/docs/archives.txt
index d81f6e27b..d90228525 100644
--- a/mailman/pipeline/docs/archives.txt
+++ b/mailman/pipeline/docs/archives.txt
@@ -105,8 +105,9 @@ But if the value is 'yes', then the message will be archived.
<BLANKLINE>
A message of great import.
<BLANKLINE>
- >>> sorted(qdata.items())
- [('_parsemsg', False), ('received_time', ...), ('version', 3)]
+ >>> dump_msgdata(qdata)
+ _parsemsg: False
+ version : 3
Without either archiving header, and all other things being the same, the
message will get archived.
@@ -127,5 +128,6 @@ message will get archived.
<BLANKLINE>
A message of great import.
<BLANKLINE>
- >>> sorted(qdata.items())
- [('_parsemsg', False), ('received_time', ...), ('version', 3)]
+ >>> dump_msgdata(qdata)
+ _parsemsg: False
+ version : 3
diff --git a/mailman/pipeline/docs/digests.txt b/mailman/pipeline/docs/digests.txt
index e94f9912f..cb939f7ca 100644
--- a/mailman/pipeline/docs/digests.txt
+++ b/mailman/pipeline/docs/digests.txt
@@ -254,12 +254,14 @@ digest and an RFC 1153 plain text digest. The size threshold is in KB.
<BLANKLINE>
--...
--...
- >>> sorted(mimedata.items())
- [('_parsemsg', False),
- ('isdigest', True),
- ('listname', u'_xtest@example.com'),
- ('received_time', ...),
- ('recips', set([])), ('version', 3)]
+ >>> dump_msgdata(mimedata)
+ _parsemsg: False
+ isdigest : True
+ listname : _xtest@example.com
+ recips : set([])
+ version : 3
+
+
>>> print rfc1153msg.as_string()
From: _xtest-request@example.com
Subject: XTest Digest, Vol 2, Issue 10
@@ -389,12 +391,12 @@ digest and an RFC 1153 plain text digest. The size threshold is in KB.
End of XTest Digest, Vol 2, Issue 10
************************************
<BLANKLINE>
- >>> sorted(rfc1153data.items())
- [('_parsemsg', False),
- ('isdigest', True),
- ('listname', u'_xtest@example.com'),
- ('received_time', ...),
- ('recips', set([])), ('version', 3)]
+ >>> dump_msgdata(rfc1153data)
+ _parsemsg: False
+ isdigest : True
+ listname : _xtest@example.com
+ recips : set([])
+ version : 3
Internationalized digests
@@ -505,12 +507,13 @@ Set the digest threshold to zero so that the digests will be sent immediately.
<BLANKLINE>
--...
--...
- >>> sorted(mimedata.items())
- [('_parsemsg', False),
- ('isdigest', True),
- ('listname', u'_xtest@example.com'),
- ('received_time', ...),
- ('recips', set([])), ('version', 3)]
+ >>> dump_msgdata(mimedata)
+ _parsemsg: False
+ isdigest : True
+ listname : _xtest@example.com
+ recips : set([])
+ version : 3
+
>>> print rfc1153msg.as_string()
From: _xtest-request@example.com
Subject: Groupe XTest, Vol. 2, Parution 11
@@ -524,15 +527,9 @@ Set the digest threshold to zero so that the digests will be sent immediately.
<BLANKLINE>
...
<BLANKLINE>
- >>> sorted(rfc1153data.items())
- [('_parsemsg', False),
- ('isdigest', True),
- ('listname', u'_xtest@example.com'),
- ('received_time', ...),
- ('recips', set([])), ('version', 3)]
-
-
-Clean up
---------
-
- >>> config.DEFAULT_SERVER_LANGUAGE = u'en'
+ >>> dump_msgdata(rfc1153data)
+ _parsemsg: False
+ isdigest : True
+ listname : _xtest@example.com
+ recips : set([])
+ version : 3
diff --git a/mailman/pipeline/docs/nntp.txt b/mailman/pipeline/docs/nntp.txt
index 0120de394..3f48be1da 100644
--- a/mailman/pipeline/docs/nntp.txt
+++ b/mailman/pipeline/docs/nntp.txt
@@ -59,8 +59,7 @@ messages are gated to.
<BLANKLINE>
Something of great import.
<BLANKLINE>
- >>> sorted(msgdata.items())
- [('_parsemsg', False),
- ('listname', u'_xtest@example.com'),
- ('received_time', ...),
- ('version', 3)]
+ >>> dump_msgdata(msgdata)
+ _parsemsg: False
+ listname : _xtest@example.com
+ version : 3
diff --git a/mailman/pipeline/docs/to-outgoing.txt b/mailman/pipeline/docs/to-outgoing.txt
index 6142d86c7..5305db19f 100644
--- a/mailman/pipeline/docs/to-outgoing.txt
+++ b/mailman/pipeline/docs/to-outgoing.txt
@@ -51,12 +51,13 @@ additional key set: the mailing list name.
Subject: Here is a message
<BLANKLINE>
Something of great import.
- >>> sorted(qmsgdata.items())
- [('_parsemsg', False),
- ('bar', 2), ('foo', 1),
- ('listname', u'_xtest@example.com'),
- ('received_time', ...),
- ('verp', True), ('version', 3)]
+ >>> dump_msgdata(qmsgdata)
+ _parsemsg: False
+ bar : 2
+ foo : 1
+ listname : _xtest@example.com
+ verp : True
+ version : 3
>>> queue_size()
0
diff --git a/mailman/pipeline/file_recipients.py b/mailman/pipeline/file_recipients.py
index f356e2e18..89d10d783 100644
--- a/mailman/pipeline/file_recipients.py
+++ b/mailman/pipeline/file_recipients.py
@@ -17,6 +17,8 @@
"""Get the normal delivery recipients from a Sendmail style :include: file."""
+from __future__ import absolute_import, unicode_literals
+
__metaclass__ = type
__all__ = [
'FileRecipients',
diff --git a/mailman/pipeline/mime_delete.py b/mailman/pipeline/mime_delete.py
index c7e27bd5f..3c4e4154f 100644
--- a/mailman/pipeline/mime_delete.py
+++ b/mailman/pipeline/mime_delete.py
@@ -24,8 +24,12 @@ wrapping only single sections after other processing are replaced by their
contents.
"""
+from __future__ import absolute_import, unicode_literals
+
__metaclass__ = type
-__all__ = ['MIMEDelete']
+__all__ = [
+ 'MIMEDelete',
+ ]
import os
@@ -118,7 +122,7 @@ def process(mlist, msg, msgdata):
reset_payload(msg, useful)
changedp = 1
if changedp:
- msg['X-Content-Filtered-By'] = 'Mailman/MimeDel %s' % VERSION
+ msg['X-Content-Filtered-By'] = 'Mailman/MimeDel {0}'.format(VERSION)
@@ -146,7 +150,7 @@ def reset_payload(msg, subpart):
def filter_parts(msg, filtertypes, passtypes, filterexts, passexts):
# Look at all the message's subparts, and recursively filter
if not msg.is_multipart():
- return 1
+ return True
payload = msg.get_payload()
prelen = len(payload)
newpayload = []
@@ -176,8 +180,8 @@ def filter_parts(msg, filtertypes, passtypes, filterexts, passexts):
msg.set_payload(newpayload)
if postlen == 0 and prelen > 0:
# We threw away everything
- return 0
- return 1
+ return False
+ return True
@@ -199,12 +203,12 @@ def collapse_multipart_alternatives(msg):
def to_plaintext(msg):
- changedp = 0
+ changedp = False
for subpart in typed_subpart_iterator(msg, 'text', 'html'):
filename = tempfile.mktemp('.html')
fp = open(filename, 'w')
try:
- fp.write(subpart.get_payload(decode=1))
+ fp.write(subpart.get_payload(decode=True))
fp.close()
cmd = os.popen(config.HTML_TO_PLAIN_TEXT_COMMAND %
{'filename': filename})
@@ -222,7 +226,7 @@ def to_plaintext(msg):
del subpart['content-transfer-encoding']
subpart.set_payload(plaintext)
subpart.set_type('text/plain')
- changedp = 1
+ changedp = True
return changedp
@@ -251,6 +255,7 @@ are receiving the only remaining copy of the discarded message.
# Most cases also discard the message
raise errors.DiscardMessage
+
def get_file_ext(m):
"""
Get filename extension. Caution: some virus don't put filename
diff --git a/mailman/pipeline/moderate.py b/mailman/pipeline/moderate.py
index ec0a555d8..0b38c3a5a 100644
--- a/mailman/pipeline/moderate.py
+++ b/mailman/pipeline/moderate.py
@@ -17,6 +17,14 @@
"""Posting moderation filter."""
+from __future__ import absolute_import, unicode_literals
+
+__metaclass__ = type
+__all__ = [
+ 'process',
+ ]
+
+
import re
from email.MIMEMessage import MIMEMessage
diff --git a/mailman/pipeline/owner_recipients.py b/mailman/pipeline/owner_recipients.py
index 046cac50c..ceb6ae0a1 100644
--- a/mailman/pipeline/owner_recipients.py
+++ b/mailman/pipeline/owner_recipients.py
@@ -17,11 +17,18 @@
"""Calculate the list owner recipients (includes moderators)."""
+from __future__ import absolute_import, unicode_literals
+
+__metaclass__ = type
+__all__ = [
+ 'process',
+ ]
+
def process(mlist, msg, msgdata):
# The recipients are the owner and the moderator
msgdata['recips'] = mlist.owner + mlist.moderator
# Don't decorate these messages with the header/footers
- msgdata['nodecorate'] = 1
- msgdata['personalize'] = 0
+ msgdata['nodecorate'] = True
+ msgdata['personalize'] = False
diff --git a/mailman/pipeline/replybot.py b/mailman/pipeline/replybot.py
index ee0894d12..e24777774 100644
--- a/mailman/pipeline/replybot.py
+++ b/mailman/pipeline/replybot.py
@@ -17,21 +17,25 @@
"""Handler for auto-responses."""
+from __future__ import absolute_import, unicode_literals
+
__metaclass__ = type
-__all__ = ['Replybot']
+__all__ = [
+ 'Replybot',
+ ]
import time
import logging
import datetime
-from string import Template
from zope.interface import implements
from mailman import Message
from mailman import Utils
from mailman.i18n import _
from mailman.interfaces.handler import IHandler
+from mailman.utilities.string import expand
log = logging.getLogger('mailman.error')
@@ -97,7 +101,7 @@ def process(mlist, msg, msgdata):
else:
rtext = mlist.autoresponse_postings_text
# Interpolation and Wrap the response text.
- text = Utils.wrap(Template(rtext).safe_substitute(d))
+ text = Utils.wrap(expand(rtext, d))
outmsg = Message.UserNotification(sender, mlist.bounces_address,
subject, text, mlist.preferred_language)
outmsg['X-Mailer'] = _('The Mailman Replybot')
diff --git a/mailman/pipeline/scrubber.py b/mailman/pipeline/scrubber.py
index f7ffd51e1..fa9c8577f 100644
--- a/mailman/pipeline/scrubber.py
+++ b/mailman/pipeline/scrubber.py
@@ -17,6 +17,8 @@
"""Cleanse a message for archiving."""
+from __future__ import absolute_import, unicode_literals
+
__metaclass__ = type
__all__ = [
'Scrubber',
diff --git a/mailman/pipeline/tagger.py b/mailman/pipeline/tagger.py
index db4bb13b9..9a0acc1e3 100644
--- a/mailman/pipeline/tagger.py
+++ b/mailman/pipeline/tagger.py
@@ -17,8 +17,12 @@
"""Extract topics from the original mail message."""
+from __future__ import absolute_import, unicode_literals
+
__metaclass__ = type
-__all__ = ['Tagger']
+__all__ = [
+ 'Tagger',
+ ]
import re
@@ -35,7 +39,7 @@ from mailman.interfaces.handler import IHandler
OR = '|'
CRNL = '\r\n'
-EMPTYSTRING = ''
+EMPTYBYTES = b''
NLTAB = '\n\t'
@@ -69,8 +73,10 @@ def process(mlist, msg, msgdata):
hits[name] = 1
break
if hits:
- msgdata['topichits'] = hits.keys()
- msg['X-Topics'] = NLTAB.join(hits.keys())
+ # Sort the keys and make them available both in the message metadata
+ # and in a message header.
+ msgdata['topichits'] = sorted(hits)
+ msg['X-Topics'] = NLTAB.join(sorted(hits))
@@ -97,7 +103,7 @@ def scanbody(msg, numlines=None):
reader = list(email.Iterators.body_line_iterator(msg))
while numlines is None or lineno < numlines:
try:
- line = reader.pop(0)
+ line = bytes(reader.pop(0))
except IndexError:
break
# Blank lines don't count
@@ -108,7 +114,7 @@ def scanbody(msg, numlines=None):
# Concatenate those body text lines with newlines, and then create a new
# message object from those lines.
p = _ForgivingParser()
- msg = p.parsestr(EMPTYSTRING.join(lines))
+ msg = p.parsestr(EMPTYBYTES.join(lines))
return msg.get_all('subject', []) + msg.get_all('keywords', [])
diff --git a/mailman/pipeline/to_archive.py b/mailman/pipeline/to_archive.py
index 15f4c856e..7f1702fe9 100644
--- a/mailman/pipeline/to_archive.py
+++ b/mailman/pipeline/to_archive.py
@@ -17,6 +17,8 @@
"""Add the message to the archives."""
+from __future__ import absolute_import, unicode_literals
+
__metaclass__ = type
__all__ = [
'ToArchive',
diff --git a/mailman/pipeline/to_digest.py b/mailman/pipeline/to_digest.py
index e56c4a109..df2684986 100644
--- a/mailman/pipeline/to_digest.py
+++ b/mailman/pipeline/to_digest.py
@@ -25,6 +25,8 @@
# directory and the DigestRunner will craft the MIME, rfc1153, and
# (eventually) URL-subject linked digests from the mbox.
+from __future__ import absolute_import, unicode_literals
+
__metaclass__ = type
__all__ = [
'ToDigest',
@@ -243,9 +245,9 @@ def send_i18n_digests(mlist, mboxfp):
if not username:
username = addresses[0][1]
if username:
- username = ' (%s)' % username
+ username = ' ({0})'.format(username)
# Put count and Wrap the toc subject line
- wrapped = Utils.wrap('%2d. %s' % (msgcount, subject), 65)
+ wrapped = Utils.wrap('{0:2}. {1}'.format(msgcount, subject), 65)
slines = wrapped.split('\n')
# See if the user's name can fit on the last line
if len(slines[-1]) + len(username) > 70:
@@ -326,8 +328,8 @@ def send_i18n_digests(mlist, mboxfp):
# Honor the default setting
for h in config.digests.plain_digest_keep_headers.split():
if msg[h]:
- uh = Utils.wrap('%s: %s' % (h, Utils.oneline(msg[h],
- in_unicode=True)))
+ uh = Utils.wrap('{0}: {1}'.format(
+ h, Utils.oneline(msg[h], in_unicode=True)))
uh = '\n\t'.join(uh.split('\n'))
print >> plainmsg, uh
print >> plainmsg
@@ -402,8 +404,8 @@ def send_i18n_digests(mlist, mboxfp):
mimerecips.add(email_address)
else:
raise AssertionError(
- 'Digest member "%s" unexpected delivery mode: %s' %
- (email_address, member.delivery_mode))
+ 'Digest member "{0}" unexpected delivery mode: {1}'.format(
+ email_address, member.delivery_mode))
# Zap this since we're now delivering the last digest to these folks.
mlist.one_last_digest.clear()
# MIME
diff --git a/mailman/pipeline/to_outgoing.py b/mailman/pipeline/to_outgoing.py
index 9ff7ab88a..ff27593c4 100644
--- a/mailman/pipeline/to_outgoing.py
+++ b/mailman/pipeline/to_outgoing.py
@@ -22,6 +22,8 @@ posted to the list membership. Anything else that needs to go out to some
recipient should just be placed in the out queue directly.
"""
+from __future__ import absolute_import, unicode_literals
+
__metaclass__ = type
__all__ = [
'ToOutgoing',
diff --git a/mailman/pipeline/to_usenet.py b/mailman/pipeline/to_usenet.py
index a635b65b3..220374348 100644
--- a/mailman/pipeline/to_usenet.py
+++ b/mailman/pipeline/to_usenet.py
@@ -17,8 +17,12 @@
"""Move the message to the mail->news queue."""
+from __future__ import absolute_import, unicode_literals
+
__metaclass__ = type
-__all__ = ['ToUsenet']
+__all__ = [
+ 'ToUsenet',
+ ]
import logging