summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBarry Warsaw2012-03-22 22:38:49 -0400
committerBarry Warsaw2012-03-22 22:38:49 -0400
commit1317dadb98e422a05342009d85ab1adfb79f86f2 (patch)
tree7d1781cdfb376b4c021b4789e4a7ce0d5c1322f2
parentaa2d0ad067adfd2515ed3c256cd0bca296058479 (diff)
downloadmailman-1317dadb98e422a05342009d85ab1adfb79f86f2.tar.gz
mailman-1317dadb98e422a05342009d85ab1adfb79f86f2.tar.zst
mailman-1317dadb98e422a05342009d85ab1adfb79f86f2.zip
-rw-r--r--src/mailman/database/schema/postgres.sql2
-rw-r--r--src/mailman/database/schema/sqlite.sql2
-rw-r--r--src/mailman/interfaces/mailinglist.py20
-rw-r--r--src/mailman/model/mailinglist.py2
-rw-r--r--src/mailman/runners/incoming.py5
-rw-r--r--src/mailman/runners/tests/test_incoming.py94
6 files changed, 123 insertions, 2 deletions
diff --git a/src/mailman/database/schema/postgres.sql b/src/mailman/database/schema/postgres.sql
index bd7ef3f6b..2e9ba249f 100644
--- a/src/mailman/database/schema/postgres.sql
+++ b/src/mailman/database/schema/postgres.sql
@@ -84,6 +84,8 @@ CREATE TABLE mailinglist (
nondigestable BOOLEAN,
nonmember_rejection_notice TEXT,
obscure_addresses BOOLEAN,
+ owner_chain TEXT,
+ owner_pipeline TEXT,
personalize INTEGER,
post_id INTEGER,
posting_chain TEXT,
diff --git a/src/mailman/database/schema/sqlite.sql b/src/mailman/database/schema/sqlite.sql
index 37b6ed8f2..e6211bf53 100644
--- a/src/mailman/database/schema/sqlite.sql
+++ b/src/mailman/database/schema/sqlite.sql
@@ -180,6 +180,8 @@ CREATE TABLE mailinglist (
nondigestable BOOLEAN,
nonmember_rejection_notice TEXT,
obscure_addresses BOOLEAN,
+ owner_chain TEXT,
+ owner_pipeline TEXT,
personalize INTEGER,
post_id INTEGER,
posting_chain TEXT,
diff --git a/src/mailman/interfaces/mailinglist.py b/src/mailman/interfaces/mailinglist.py
index d92bae464..bced070d3 100644
--- a/src/mailman/interfaces/mailinglist.py
+++ b/src/mailman/interfaces/mailinglist.py
@@ -382,7 +382,7 @@ class IMailingList(Interface):
# Processing.
posting_chain = Attribute(
- """This mailing list's moderation chain.
+ """This mailing list's posting moderation chain.
When messages are posted to a mailing list, it first goes through a
moderation chain to determine whether the message will be accepted.
@@ -397,6 +397,24 @@ class IMailingList(Interface):
This attribute names a pipeline for postings, which must exist.
""")
+ owner_chain = Attribute(
+ """This mailing list's owner moderation chain.
+
+ When messages are posted to the owners of a mailing list, it first
+ goes through a moderation chain to determine whether the message will
+ be accepted. This attribute names a chain for postings, which must
+ exist.
+ """)
+
+ owner_pipeline = Attribute(
+ """This mailing list's owner posting pipeline.
+
+ Every mailing list has a processing pipeline that messages flow
+ through once they've been accepted for posting to the owners of a
+ mailing list. This attribute names a pipeline for postings, which
+ must exist.
+ """)
+
data_path = Attribute(
"""The file system path to list-specific data.
diff --git a/src/mailman/model/mailinglist.py b/src/mailman/model/mailinglist.py
index 76f88caa7..e397d59d6 100644
--- a/src/mailman/model/mailinglist.py
+++ b/src/mailman/model/mailinglist.py
@@ -168,6 +168,8 @@ class MailingList(Model):
nondigestable = Bool()
nonmember_rejection_notice = Unicode()
obscure_addresses = Bool()
+ owner_chain = Unicode()
+ owner_pipeline = Unicode()
personalize = Enum(Personalization)
post_id = Int()
posting_chain = Unicode()
diff --git a/src/mailman/runners/incoming.py b/src/mailman/runners/incoming.py
index 7072f9bcc..d8db926c7 100644
--- a/src/mailman/runners/incoming.py
+++ b/src/mailman/runners/incoming.py
@@ -61,6 +61,9 @@ class IncomingRunner(Runner):
pass
config.db.commit()
# Process the message through the mailing list's start chain.
- process(mlist, msg, msgdata, mlist.posting_chain)
+ start_chain = (mlist.owner_chain
+ if msgdata.get('to_owner', False)
+ else mlist.posting_chain)
+ process(mlist, msg, msgdata, start_chain)
# Do not keep this message queued.
return False
diff --git a/src/mailman/runners/tests/test_incoming.py b/src/mailman/runners/tests/test_incoming.py
new file mode 100644
index 000000000..5a0d82765
--- /dev/null
+++ b/src/mailman/runners/tests/test_incoming.py
@@ -0,0 +1,94 @@
+# Copyright (C) 2012 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/>.
+
+"""Test the incoming queue runner."""
+
+from __future__ import absolute_import, print_function, unicode_literals
+
+__metaclass__ = type
+__all__ = [
+ 'TestIncoming',
+ ]
+
+
+import unittest
+
+from mailman.app.lifecycle import create_list
+from mailman.chains.base import TerminalChainBase
+from mailman.config import config
+from mailman.runners.incoming import IncomingRunner
+from mailman.testing.helpers import (
+ get_queue_messages,
+ make_testable_runner,
+ specialized_message_from_string as mfs)
+from mailman.testing.layers import ConfigLayer
+
+
+
+class Chain(TerminalChainBase):
+ name = 'test'
+ description = 'a test chain'
+
+ def __init__(self, marker):
+ self._marker = marker
+
+ def _process(self, mlist, msg, msgdata):
+ msgdata['marker'] = self._marker
+ config.switchboards['out'].enqueue(msg, msgdata)
+
+
+
+class TestIncoming(unittest.TestCase):
+ """Test the incoming queue runner."""
+
+ layer = ConfigLayer
+
+ def setUp(self):
+ self._mlist = create_list('test@example.com')
+ self._mlist.posting_chain = 'test posting'
+ self._mlist.owner_chain = 'test owner'
+ config.chains['test posting'] = Chain('posting')
+ config.chains['test owner'] = Chain('owner')
+ self._in = make_testable_runner(IncomingRunner, 'in')
+ self._msg = mfs("""\
+From: anne@example.com
+To: test@example.com
+
+""")
+
+ def tearDown(self):
+ del config.chains['test posting']
+ del config.chains['test owner']
+
+ def test_posting(self):
+ # A message posted to the list goes through the posting chain.
+ msgdata = dict(listname='test@example.com')
+ config.switchboards['in'].enqueue(self._msg, msgdata)
+ self._in.run()
+ messages = get_queue_messages('out')
+ self.assertEqual(len(messages), 1)
+ self.assertEqual(messages[0].msgdata.get('marker'), 'posting')
+
+ def test_owner(self):
+ # A message posted to the list goes through the posting chain.
+ msgdata = dict(listname='test@example.com',
+ to_owner=True)
+ config.switchboards['in'].enqueue(self._msg, msgdata)
+ self._in.run()
+ messages = get_queue_messages('out')
+ self.assertEqual(len(messages), 1)
+ self.assertEqual(messages[0].msgdata.get('marker'), 'owner')