diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/mailman/app/moderator.py | 13 | ||||
| -rw-r--r-- | src/mailman/app/tests/test_moderation.py | 106 | ||||
| -rw-r--r-- | src/mailman/bin/master.py | 1 | ||||
| -rw-r--r-- | src/mailman/chains/moderation.py | 2 | ||||
| -rw-r--r-- | src/mailman/core/pipelines.py | 7 | ||||
| -rw-r--r-- | src/mailman/docs/NEWS.rst | 4 | ||||
| -rw-r--r-- | src/mailman/runners/outgoing.py | 3 |
7 files changed, 130 insertions, 6 deletions
diff --git a/src/mailman/app/moderator.py b/src/mailman/app/moderator.py index 0ba6f492a..d2c6600ad 100644 --- a/src/mailman/app/moderator.py +++ b/src/mailman/app/moderator.py @@ -30,9 +30,10 @@ __all__ = [ 'hold_unsubscription', ] + +import time import logging -from datetime import datetime from email.utils import formataddr, formatdate, getaddresses, make_msgid from zope.component import getUtility @@ -49,6 +50,7 @@ from mailman.interfaces.member import ( AlreadySubscribedError, DeliveryMode, NotAMemberError) from mailman.interfaces.messages import IMessageStore from mailman.interfaces.requests import IRequests, RequestType +from mailman.utilities.datetime import now from mailman.utilities.i18n import make @@ -96,7 +98,7 @@ def hold_message(mlist, msg, msgdata=None, reason=None): msgdata['_mod_sender'] = msg.sender msgdata['_mod_subject'] = msg.get('subject', _('(no subject)')) msgdata['_mod_reason'] = reason - msgdata['_mod_hold_date'] = datetime.now().isoformat() + msgdata['_mod_hold_date'] = now().isoformat() # Now hold this request. We'll use the message_id as the key. requestsdb = getUtility(IRequests).get_list_requests(mlist) request_id = requestsdb.hold_request( @@ -146,12 +148,13 @@ def handle_message(mlist, id, action, # Queue the file for delivery. Trying to deliver the message directly # here can lead to a huge delay in web turnaround. Log the moderation # and add a header. - msg['X-Mailman-Approved-At'] = formatdate(localtime=True) + msg['X-Mailman-Approved-At'] = formatdate( + time.mktime(now().timetuple()), localtime=True) vlog.info('held message approved, message-id: %s', msg.get('message-id', 'n/a')) # Stick the message back in the incoming queue for further # processing. - config.switchboards['in'].enqueue(msg, _metadata=msgdata) + config.switchboards['pipeline'].enqueue(msg, _metadata=msgdata) else: raise AssertionError('Unexpected action: {0}'.format(action)) # Forward the message. @@ -195,7 +198,7 @@ def handle_message(mlist, id, action, def hold_subscription(mlist, address, realname, password, mode, language): - data = dict(when=datetime.now().isoformat(), + data = dict(when=now().isoformat(), address=address, realname=realname, password=password, diff --git a/src/mailman/app/tests/test_moderation.py b/src/mailman/app/tests/test_moderation.py new file mode 100644 index 000000000..59e9f3643 --- /dev/null +++ b/src/mailman/app/tests/test_moderation.py @@ -0,0 +1,106 @@ +# Copyright (C) 2011 by the Free Software Foundation, Inc. +# +# This file is part of GNU Mailman. +# +# GNU Mailman is free software: you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free +# Software Foundation, either version 3 of the License, or (at your option) +# any later version. +# +# GNU Mailman is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +# more details. +# +# You should have received a copy of the GNU General Public License along with +# GNU Mailman. If not, see <http://www.gnu.org/licenses/>. + +"""Moderation tests.""" + +from __future__ import absolute_import, unicode_literals + +__metaclass__ = type +__all__ = [ + 'test_suite', + ] + + +import unittest + +from mailman.app.lifecycle import create_list +from mailman.app.moderator import handle_message, hold_message +from mailman.interfaces.action import Action +from mailman.runners.incoming import IncomingRunner +from mailman.runners.outgoing import OutgoingRunner +from mailman.runners.pipeline import PipelineRunner +from mailman.testing.helpers import ( + make_testable_runner, specialized_message_from_string) +from mailman.testing.layers import SMTPLayer + + + +class TestModeration(unittest.TestCase): + """Test moderation functionality.""" + + layer = SMTPLayer + + def setUp(self): + self._mlist = create_list('test@example.com') + self._msg = specialized_message_from_string("""\ +From: anne@example.com +To: test@example.com +Subject: hold me +Message-ID: <alpha> + +""") + self._in = make_testable_runner(IncomingRunner, 'in') + self._pipeline = make_testable_runner(PipelineRunner, 'pipeline') + self._out = make_testable_runner(OutgoingRunner, 'out') + + def test_accepted_message_gets_posted(self): + # A message that is accepted by the moderator should get posted to the + # mailing list. LP: #827697 + msgdata = dict(listname='test@example.com', + recipients=['bart@example.com']) + request_id = hold_message(self._mlist, self._msg, msgdata) + handle_message(self._mlist, request_id, Action.accept) + self._in.run() + self._pipeline.run() + self._out.run() + messages = list(SMTPLayer.smtpd.messages) + self.assertEqual(len(messages), 1) + message = messages[0] + # Delete variable headers which can't be compared. + self.assertTrue('x-mailman-version' in message) + del message['x-mailman-version'] + self.assertTrue('x-peer' in message) + del message['x-peer'] + self.assertEqual(message.as_string(), """\ +From: anne@example.com +To: test@example.com +Message-ID: <alpha> +X-Mailman-Approved-At: Mon, 01 Aug 2005 07:49:23 -0400 +Subject: [Test] hold me +X-BeenThere: test@example.com +Precedence: list +List-Id: <test.example.com> +X-Message-ID-Hash: XZ3DGG4V37BZTTLXNUX4NABB4DNQHTCP +List-Post: <mailto:test@example.com> +List-Subscribe: <http://lists.example.com/listinfo/test@example.com>, + <mailto:test-join@example.com> +Archived-At: http://lists.example.com/archives/XZ3DGG4V37BZTTLXNUX4NABB4DNQHTCP +List-Unsubscribe: <http://lists.example.com/listinfo/test@example.com>, + <mailto:test-leave@example.com> +List-Archive: <http://lists.example.com/archives/test@example.com> +List-Help: <mailto:test-request@example.com?subject=help> +X-MailFrom: test-bounces@example.com +X-RcptTo: bart@example.com + +""") + + + +def test_suite(): + suite = unittest.TestSuite() + suite.addTest(unittest.makeSuite(TestModeration)) + return suite diff --git a/src/mailman/bin/master.py b/src/mailman/bin/master.py index d982b385f..d910b491d 100644 --- a/src/mailman/bin/master.py +++ b/src/mailman/bin/master.py @@ -21,6 +21,7 @@ from __future__ import absolute_import, unicode_literals __metaclass__ = type __all__ = [ + 'Loop', 'main', ] diff --git a/src/mailman/chains/moderation.py b/src/mailman/chains/moderation.py index d6104fd66..fcba31f82 100644 --- a/src/mailman/chains/moderation.py +++ b/src/mailman/chains/moderation.py @@ -71,7 +71,7 @@ class ModerationChain: # moderation.py rule for details. This is stored in the metadata as a # string so that it can be stored in the pending table. action = Action[msgdata.get('moderation_action')] - # defer and accept are not valid moderation actions. + # defer is not a valid moderation action. jump_chain = { Action.accept: 'accept', Action.discard: 'discard', diff --git a/src/mailman/core/pipelines.py b/src/mailman/core/pipelines.py index 15adca501..7efc8e329 100644 --- a/src/mailman/core/pipelines.py +++ b/src/mailman/core/pipelines.py @@ -26,6 +26,8 @@ __all__ = [ ] +import logging + from zope.interface import implements from zope.interface.verify import verifyObject @@ -35,6 +37,8 @@ from mailman.core.i18n import _ from mailman.interfaces.handler import IHandler from mailman.interfaces.pipeline import IPipeline +log = logging.getLogger('mailman.debug') + def process(mlist, msg, msgdata, pipeline_name='built-in'): @@ -45,8 +49,11 @@ def process(mlist, msg, msgdata, pipeline_name='built-in'): :param msgdata: The message metadata dictionary. :param pipeline_name: The name of the pipeline to process through. """ + message_id = msg.get('message-id', 'n/a') pipeline = config.pipelines[pipeline_name] for handler in pipeline: + log.debug('[pipeline] processing {0}: {1}'.format( + handler.name, message_id)) handler.process(mlist, msg, msgdata) diff --git a/src/mailman/docs/NEWS.rst b/src/mailman/docs/NEWS.rst index c2fa66905..3b98381aa 100644 --- a/src/mailman/docs/NEWS.rst +++ b/src/mailman/docs/NEWS.rst @@ -64,6 +64,10 @@ Testing * Handle SIGTERM in the REST server so that the test suite always shuts down correctly. (LP: #770328) +Other bugs +---------- + * Moderating a message with Action.accept now sends the message. (LP: #827697) + 3.0 alpha 7 -- "Mission" ======================== diff --git a/src/mailman/runners/outgoing.py b/src/mailman/runners/outgoing.py index 65d8928a6..e771d8be3 100644 --- a/src/mailman/runners/outgoing.py +++ b/src/mailman/runners/outgoing.py @@ -41,6 +41,7 @@ DEAL_WITH_PERMFAILURES_EVERY = 10 log = logging.getLogger('mailman.error') smtp_log = logging.getLogger('mailman.smtp') +debug_log = logging.getLogger('mailman.debug') @@ -86,6 +87,8 @@ class OutgoingRunner(Runner): # VERP every 'interval' number of times. msgdata['verp'] = (mlist.post_id % interval == 0) try: + debug_log.debug('[outgoing] {0}: {1}'.format( + self._func, msg.get('message-id', 'n/a'))) self._func(mlist, msg, msgdata) self._logged = False except socket.error: |
