summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBarry Warsaw2012-03-31 04:51:42 -0600
committerBarry Warsaw2012-03-31 04:51:42 -0600
commitf11b1601c61c97a3fc2dd400fbc2913235efa83d (patch)
tree5b3ef89bbc99cf17b7dabbc48026c1f585eead29 /src
parent7f0c57ca63d13058934e3eb8423ea52075e984ae (diff)
downloadmailman-f11b1601c61c97a3fc2dd400fbc2913235efa83d.tar.gz
mailman-f11b1601c61c97a3fc2dd400fbc2913235efa83d.tar.zst
mailman-f11b1601c61c97a3fc2dd400fbc2913235efa83d.zip
Diffstat (limited to 'src')
-rw-r--r--src/mailman/app/docs/pipelines.rst8
-rw-r--r--src/mailman/commands/docs/inject.rst2
-rw-r--r--src/mailman/config/mailman.cfg4
-rw-r--r--src/mailman/docs/NEWS.rst2
-rw-r--r--src/mailman/handlers/cook_headers.py2
-rw-r--r--src/mailman/handlers/docs/nntp.rst35
-rw-r--r--src/mailman/handlers/docs/subject-munging.rst10
-rw-r--r--src/mailman/handlers/to_usenet.py13
-rw-r--r--src/mailman/interfaces/nntp.py4
-rw-r--r--src/mailman/runners/docs/nntp.rst (renamed from src/mailman/runners/docs/news.rst)37
-rw-r--r--src/mailman/runners/nntp.py (renamed from src/mailman/runners/news.py)4
-rw-r--r--src/mailman/runners/tests/test_nntp.py141
-rw-r--r--src/mailman/testing/testing.cfg2
13 files changed, 201 insertions, 63 deletions
diff --git a/src/mailman/app/docs/pipelines.rst b/src/mailman/app/docs/pipelines.rst
index 56fdeb5c6..96d9d232a 100644
--- a/src/mailman/app/docs/pipelines.rst
+++ b/src/mailman/app/docs/pipelines.rst
@@ -60,7 +60,7 @@ However there are currently no recipients for this message.
>>> dump_msgdata(msgdata)
original_sender : aperson@example.com
- origsubj : My first post
+ original_subject: My first post
recipients : set([])
stripped_subject: My first post
@@ -90,7 +90,7 @@ processing queues.
>>> dump_msgdata(messages[0].msgdata)
_parsemsg : False
original_sender : aperson@example.com
- origsubj : My first post
+ original_subject: My first post
recipients : set([])
stripped_subject: My first post
version : 3
@@ -98,7 +98,7 @@ processing queues.
This mailing list is not linked to an NNTP newsgroup, so there's nothing in
the outgoing nntp queue.
- >>> messages = get_queue_messages('news')
+ >>> messages = get_queue_messages('nntp')
>>> len(messages)
0
@@ -128,7 +128,7 @@ delivered to end recipients.
_parsemsg : False
listname : test@example.com
original_sender : aperson@example.com
- origsubj : My first post
+ original_subject: My first post
recipients : set([])
stripped_subject: My first post
version : 3
diff --git a/src/mailman/commands/docs/inject.rst b/src/mailman/commands/docs/inject.rst
index 7150beac7..e8987128c 100644
--- a/src/mailman/commands/docs/inject.rst
+++ b/src/mailman/commands/docs/inject.rst
@@ -35,7 +35,7 @@ It's easy to find out which queues are available.
digest
in
lmtp
- news
+ nntp
out
pipeline
rest
diff --git a/src/mailman/config/mailman.cfg b/src/mailman/config/mailman.cfg
index 0d37ceed9..10ef0ba17 100644
--- a/src/mailman/config/mailman.cfg
+++ b/src/mailman/config/mailman.cfg
@@ -61,8 +61,8 @@ class: mailman.runners.incoming.IncomingRunner
[runner.lmtp]
class: mailman.runners.lmtp.LMTPRunner
-[runner.news]
-class: mailman.runners.news.NewsRunner
+[runner.nntp]
+class: mailman.runners.nntp.NNTPRunner
[runner.out]
class: mailman.runners.outgoing.OutgoingRunner
diff --git a/src/mailman/docs/NEWS.rst b/src/mailman/docs/NEWS.rst
index 48736b518..6c5883814 100644
--- a/src/mailman/docs/NEWS.rst
+++ b/src/mailman/docs/NEWS.rst
@@ -22,6 +22,8 @@ Architecture
* The `ArchiveRunner` no longer acquires a lock before it calls the
individual archiver implementations, since not all of them need a lock. If
they do, the implementations must acquire said lock themselves.
+ * The `news` runner and queue has been renamed to the more accurate `nntp`.
+ Beta testers can can safely remove `$var_dir/queue/news`.
Configuration
-------------
diff --git a/src/mailman/handlers/cook_headers.py b/src/mailman/handlers/cook_headers.py
index 2d117429c..5d1e416a6 100644
--- a/src/mailman/handlers/cook_headers.py
+++ b/src/mailman/handlers/cook_headers.py
@@ -190,7 +190,7 @@ def prefix_subject(mlist, msg, msgdata):
ws = '\t'
if len(lines) > 1 and lines[1] and lines[1][0] in ' \t':
ws = lines[1][0]
- msgdata['origsubj'] = subject
+ msgdata['original_subject'] = subject
# The subject may be multilingual but we take the first charset as major
# one and try to decode. If it is decodable, returned subject is in one
# line and cset is properly set. If fail, subject is mime-encoded and
diff --git a/src/mailman/handlers/docs/nntp.rst b/src/mailman/handlers/docs/nntp.rst
index 874712397..c298fcb14 100644
--- a/src/mailman/handlers/docs/nntp.rst
+++ b/src/mailman/handlers/docs/nntp.rst
@@ -3,15 +3,14 @@ NNTP Gateway
============
Mailman has an NNTP gateway, whereby messages posted to the mailing list can
-be forwarded onto an NNTP newsgroup. Typically this means Usenet, but since
-NNTP is to Usenet as IP is to the web, it's more general than that.
+be forwarded onto an NNTP newsgroup.
- >>> mlist = create_list('_xtest@example.com')
+ >>> mlist = create_list('test@example.com')
Gatewaying from the mailing list to the newsgroup happens through a separate
``nntp`` queue and happen immediately when the message is posted through to
the list. Note that gatewaying from the newsgroup to the list happens via a
-cronjob (currently not shown).
+separate process.
There are several situations which prevent a message from being gatewayed to
the newsgroup. The feature could be disabled, as is the default.
@@ -26,43 +25,43 @@ the newsgroup. The feature could be disabled, as is the default.
>>> handler = config.handlers['to-usenet']
>>> handler.process(mlist, msg, {})
-
- >>> switchboard = config.switchboards['news']
- >>> switchboard.files
+ >>> from mailman.testing.helpers import get_queue_messages
+ >>> get_queue_messages('nntp')
[]
Even if enabled, messages that came from the newsgroup are never gated back to
the newsgroup.
>>> mlist.gateway_to_news = True
- >>> handler.process(mlist, msg, {'fromusenet': True})
- >>> switchboard.files
+ >>> handler.process(mlist, msg, dict(fromusenet=True))
+ >>> get_queue_messages('nntp')
[]
Neither are digests ever gated to the newsgroup.
- >>> handler.process(mlist, msg, {'isdigest': True})
- >>> switchboard.files
+ >>> handler.process(mlist, msg, dict(isdigest=True))
+ >>> get_queue_messages('nntp')
[]
However, other posted messages get gated to the newsgroup via the nntp queue.
The list owner can set the linked newsgroup and the nntp host that its
messages are gated to.
+::
>>> mlist.linked_newsgroup = 'comp.lang.thing'
>>> mlist.nntp_host = 'news.example.com'
>>> handler.process(mlist, msg, {})
- >>> len(switchboard.files)
+ >>> messages = get_queue_messages('nntp')
+ >>> len(messages)
1
- >>> filebase = switchboard.files[0]
- >>> msg, msgdata = switchboard.dequeue(filebase)
- >>> switchboard.finish(filebase)
- >>> print msg.as_string()
+
+ >>> print messages[0].msg.as_string()
Subject: An important message
<BLANKLINE>
Something of great import.
<BLANKLINE>
- >>> dump_msgdata(msgdata)
+
+ >>> dump_msgdata(messages[0].msgdata)
_parsemsg: False
- listname : _xtest@example.com
+ listname : test@example.com
version : 3
diff --git a/src/mailman/handlers/docs/subject-munging.rst b/src/mailman/handlers/docs/subject-munging.rst
index 48cee8e2b..f9e3b9abb 100644
--- a/src/mailman/handlers/docs/subject-munging.rst
+++ b/src/mailman/handlers/docs/subject-munging.rst
@@ -8,7 +8,7 @@ transformations. Some headers get added, others get changed. Some of these
changes depend on mailing list settings and others depend on how the message
is getting sent through the system. We'll take things one-by-one.
- >>> mlist = create_list('_xtest@example.com')
+ >>> mlist = create_list('test@example.com')
Inserting a prefix
@@ -32,11 +32,9 @@ subject munging, a mailing list must have a preferred language.
>>> from mailman.handlers.cook_headers import process
>>> process(mlist, msg, msgdata)
-The original subject header is stored in the message metadata. We must print
-the new ``Subject`` header because it gets converted from a string to an
-``email.header.Header`` instance which has an unhelpful ``repr``.
+The original subject header is stored in the message metadata.
- >>> msgdata['origsubj']
+ >>> msgdata['original_subject']
u''
>>> print msg['subject']
[XTest] (no subject)
@@ -52,7 +50,7 @@ at the beginning of the header's value.
... """)
>>> msgdata = {}
>>> process(mlist, msg, msgdata)
- >>> print msgdata['origsubj']
+ >>> print msgdata['original_subject']
Something important
>>> print msg['subject']
[XTest] Something important
diff --git a/src/mailman/handlers/to_usenet.py b/src/mailman/handlers/to_usenet.py
index 26a383c64..021f8f9e5 100644
--- a/src/mailman/handlers/to_usenet.py
+++ b/src/mailman/handlers/to_usenet.py
@@ -17,7 +17,7 @@
"""Move the message to the mail->news queue."""
-from __future__ import absolute_import, unicode_literals
+from __future__ import absolute_import, print_function, unicode_literals
__metaclass__ = type
__all__ = [
@@ -50,11 +50,12 @@ class ToUsenet:
def process(self, mlist, msg, msgdata):
"""See `IHandler`."""
# Short circuits.
- if not mlist.gateway_to_news or \
- msgdata.get('isdigest') or \
- msgdata.get('fromusenet'):
+ if (not mlist.gateway_to_news or
+ msgdata.get('isdigest') or
+ msgdata.get('fromusenet')):
+ # Short-circuit.
return
- # sanity checks
+ # Sanity checks.
error = []
if not mlist.linked_newsgroup:
error.append('no newsgroup')
@@ -65,5 +66,5 @@ class ToUsenet:
COMMASPACE.join(error))
return
# Put the message in the news runner's queue.
- config.switchboards['news'].enqueue(
+ config.switchboards['nntp'].enqueue(
msg, msgdata, listname=mlist.fqdn_listname)
diff --git a/src/mailman/interfaces/nntp.py b/src/mailman/interfaces/nntp.py
index 099e14a07..d5d08d3f0 100644
--- a/src/mailman/interfaces/nntp.py
+++ b/src/mailman/interfaces/nntp.py
@@ -26,9 +26,9 @@ from flufl.enum import Enum
class NewsModeration(Enum):
- # The newsgroup is not moderated
+ # The newsgroup is not moderated.
none = 0
# The newsgroup is moderated, but allows for an open posting policy.
open_moderated = 1
- # The newsgroup is moderated
+ # The newsgroup is moderated.
moderated = 2
diff --git a/src/mailman/runners/docs/news.rst b/src/mailman/runners/docs/nntp.rst
index 71febf95c..c54dd3696 100644
--- a/src/mailman/runners/docs/news.rst
+++ b/src/mailman/runners/docs/nntp.rst
@@ -1,23 +1,20 @@
===============
-The news runner
+The NNTP runner
===============
-The news runner gateways mailing list messages to an NNTP newsgroup. One of
-the most important things this runner does is prepare the message for Usenet
-(yes, I know that NNTP is not Usenet, but this runner was originally written
-to gate to Usenet, which has its own rules).
+The NNTP runner gateways mailing list messages to an NNTP newsgroup.
- >>> mlist = create_list('_xtest@example.com')
+ >>> mlist = create_list('test@example.com')
>>> mlist.linked_newsgroup = 'comp.lang.python'
Some NNTP servers such as INN reject messages containing a set of prohibited
-headers, so one of the things that the news runner does is remove these
-prohibited headers.
+headers, so one of the things that this runner does is remove these prohibited
+headers.
::
>>> msg = message_from_string("""\
... From: aperson@example.com
- ... To: _xtest@example.com
+ ... To: test@example.com
... NNTP-Posting-Host: news.example.com
... NNTP-Posting-Date: today
... X-Trace: blah blah
@@ -34,13 +31,13 @@ prohibited headers.
... """)
>>> msgdata = {}
- >>> from mailman.runners.news import prepare_message
+ >>> from mailman.runners.nntp import prepare_message
>>> prepare_message(mlist, msg, msgdata)
>>> msgdata['prepped']
True
>>> print msg.as_string()
From: aperson@example.com
- To: _xtest@example.com
+ To: test@example.com
Newsgroups: comp.lang.python
Message-ID: ...
Lines: 1
@@ -54,7 +51,7 @@ so the news runner must collapse or move these duplicate headers to an
>>> msg = message_from_string("""\
... From: aperson@example.com
- ... To: _xtest@example.com
+ ... To: test@example.com
... To: two@example.com
... Cc: three@example.com
... Cc: four@example.com
@@ -74,7 +71,7 @@ so the news runner must collapse or move these duplicate headers to an
Newsgroups: comp.lang.python
Message-ID: ...
Lines: 1
- To: _xtest@example.com
+ To: test@example.com
X-Original-To: two@example.com
CC: three@example.com
X-Original-CC: four@example.com
@@ -91,7 +88,7 @@ the message.
>>> msg = message_from_string("""\
... From: aperson@example.com
- ... To: _xtest@example.com
+ ... To: test@example.com
... Cc: someother@example.com
... Content-Transfer-Encoding: yes
...
@@ -103,7 +100,7 @@ the message.
True
>>> print msg.as_string()
From: aperson@example.com
- To: _xtest@example.com
+ To: test@example.com
Cc: someother@example.com
Content-Transfer-Encoding: yes
Newsgroups: comp.lang.python
@@ -125,31 +122,31 @@ posting address is added for the benefit of the Usenet system.
>>> mlist.news_moderation = NewsModeration.open_moderated
>>> msg = message_from_string("""\
... From: aperson@example.com
- ... To: _xtest@example.com
+ ... To: test@example.com
... Approved: this gets deleted
...
... """)
>>> prepare_message(mlist, msg, {})
>>> print msg['approved']
- _xtest@example.com
+ test@example.com
>>> mlist.news_moderation = NewsModeration.moderated
>>> msg = message_from_string("""\
... From: aperson@example.com
- ... To: _xtest@example.com
+ ... To: test@example.com
... Approved: this gets deleted
...
... """)
>>> prepare_message(mlist, msg, {})
>>> print msg['approved']
- _xtest@example.com
+ test@example.com
But if the newsgroup is not moderated, the ``Approved:`` header is not changed.
>>> mlist.news_moderation = NewsModeration.none
>>> msg = message_from_string("""\
... From: aperson@example.com
- ... To: _xtest@example.com
+ ... To: test@example.com
... Approved: this doesn't get deleted
...
... """)
diff --git a/src/mailman/runners/news.py b/src/mailman/runners/nntp.py
index e3c6f060d..32f0165da 100644
--- a/src/mailman/runners/news.py
+++ b/src/mailman/runners/nntp.py
@@ -99,8 +99,8 @@ def prepare_message(mlist, msg, msgdata):
# messages? TK: We use stripped_subject (prefix stripped) which was
# crafted in CookHeaders.py to ensure prefix was stripped from the subject
# came from mailing list user.
- stripped_subject = msgdata.get('stripped_subject') \
- or msgdata.get('origsubj')
+ stripped_subject = msgdata.get('stripped_subject',
+ msgdata.get('original_subject'))
if not mlist.news_prefix_subject_too and stripped_subject is not None:
del msg['subject']
msg['subject'] = stripped_subject
diff --git a/src/mailman/runners/tests/test_nntp.py b/src/mailman/runners/tests/test_nntp.py
new file mode 100644
index 000000000..2df02d205
--- /dev/null
+++ b/src/mailman/runners/tests/test_nntp.py
@@ -0,0 +1,141 @@
+# 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 NNTP runner and related utilities."""
+
+from __future__ import absolute_import, print_function, unicode_literals
+
+__metaclass__ = type
+__all__ = [
+ 'TestNNTP',
+ ]
+
+
+import unittest
+
+from mailman.app.lifecycle import create_list
+from mailman.interfaces.nntp import NewsModeration
+from mailman.runners import nntp
+from mailman.testing.helpers import (
+ specialized_message_from_string as mfs)
+from mailman.testing.layers import ConfigLayer
+
+
+
+class TestNNTP(unittest.TestCase):
+ """Test the NNTP runner and related utilities."""
+
+ layer = ConfigLayer
+
+ def setUp(self):
+ self._mlist = create_list('test@example.com')
+ self._msg = mfs("""\
+From: anne@example.com
+To: test@example.com
+Subject: A newsgroup posting
+Message-ID: <ant>
+
+Testing
+""")
+
+ def test_moderated_approved_header(self):
+ # When the mailing list is moderated , the message will get an
+ # Approved header, which NNTP software uses to forward to the
+ # newsgroup. The message would not have gotten to the mailing list if
+ # it wasn't already approved.
+ self._mlist.news_moderation = NewsModeration.moderated
+ nntp.prepare_message(self._mlist, self._msg, {})
+ self.assertEqual(self._msg['approved'], 'test@example.com')
+
+ def test_open_moderated_approved_header(self):
+ # When the mailing list is moderated using an open posting policy, the
+ # message will get an Approved header, which NNTP software uses to
+ # forward to the newsgroup. The message would not have gotten to the
+ # mailing list if it wasn't already approved.
+ self._mlist.news_moderation = NewsModeration.open_moderated
+ nntp.prepare_message(self._mlist, self._msg, {})
+ self.assertEqual(self._msg['approved'], 'test@example.com')
+
+ def test_moderation_removes_previous_approved_header(self):
+ # Any existing Approved header is removed from moderated messages.
+ self._msg['Approved'] = 'a bogus approval'
+ self._mlist.news_moderation = NewsModeration.moderated
+ nntp.prepare_message(self._mlist, self._msg, {})
+ headers = self._msg.get_all('approved')
+ self.assertEqual(len(headers), 1)
+ self.assertEqual(headers[0], 'test@example.com')
+
+ def test_open_moderation_removes_previous_approved_header(self):
+ # Any existing Approved header is removed from moderated messages.
+ self._msg['Approved'] = 'a bogus approval'
+ self._mlist.news_moderation = NewsModeration.open_moderated
+ nntp.prepare_message(self._mlist, self._msg, {})
+ headers = self._msg.get_all('approved')
+ self.assertEqual(len(headers), 1)
+ self.assertEqual(headers[0], 'test@example.com')
+
+ def test_stripped_subject(self):
+ # The cook-headers handler adds the original and/or stripped (of the
+ # prefix) subject to the metadata. Assume that handler's been run;
+ # check the Subject header.
+ self._mlist.news_prefix_subject_too = False
+ del self._msg['subject']
+ self._msg['subject'] = 'Re: Your test'
+ msgdata = dict(stripped_subject='Your test')
+ nntp.prepare_message(self._mlist, self._msg, msgdata)
+ headers = self._msg.get_all('subject')
+ self.assertEqual(len(headers), 1)
+ self.assertEqual(headers[0], 'Your test')
+
+ def test_original_subject(self):
+ # The cook-headers handler adds the original and/or stripped (of the
+ # prefix) subject to the metadata. Assume that handler's been run;
+ # check the Subject header.
+ self._mlist.news_prefix_subject_too = False
+ del self._msg['subject']
+ self._msg['subject'] = 'Re: Your test'
+ msgdata = dict(original_subject='Your test')
+ nntp.prepare_message(self._mlist, self._msg, msgdata)
+ headers = self._msg.get_all('subject')
+ self.assertEqual(len(headers), 1)
+ self.assertEqual(headers[0], 'Your test')
+
+ def test_stripped_subject_prefix_okay(self):
+ # The cook-headers handler adds the original and/or stripped (of the
+ # prefix) subject to the metadata. Assume that handler's been run;
+ # check the Subject header.
+ self._mlist.news_prefix_subject_too = True
+ del self._msg['subject']
+ self._msg['subject'] = 'Re: Your test'
+ msgdata = dict(stripped_subject='Your test')
+ nntp.prepare_message(self._mlist, self._msg, msgdata)
+ headers = self._msg.get_all('subject')
+ self.assertEqual(len(headers), 1)
+ self.assertEqual(headers[0], 'Re: Your test')
+
+ def test_original_subject_prefix_okay(self):
+ # The cook-headers handler adds the original and/or stripped (of the
+ # prefix) subject to the metadata. Assume that handler's been run;
+ # check the Subject header.
+ self._mlist.news_prefix_subject_too = True
+ del self._msg['subject']
+ self._msg['subject'] = 'Re: Your test'
+ msgdata = dict(original_subject='Your test')
+ nntp.prepare_message(self._mlist, self._msg, msgdata)
+ headers = self._msg.get_all('subject')
+ self.assertEqual(len(headers), 1)
+ self.assertEqual(headers[0], 'Re: Your test')
diff --git a/src/mailman/testing/testing.cfg b/src/mailman/testing/testing.cfg
index b7e80ff02..91613cc8d 100644
--- a/src/mailman/testing/testing.cfg
+++ b/src/mailman/testing/testing.cfg
@@ -48,7 +48,7 @@ max_restarts: 1
[runner.lmtp]
max_restarts: 1
-[runner.news]
+[runner.nntp]
max_restarts: 1
[runner.out]