diff options
Diffstat (limited to 'mailman/pipeline')
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 |
