summaryrefslogtreecommitdiff
path: root/src/mailman/app
diff options
context:
space:
mode:
Diffstat (limited to 'src/mailman/app')
-rw-r--r--src/mailman/app/docs/pipelines.rst31
-rw-r--r--src/mailman/app/inject.py14
-rw-r--r--src/mailman/app/tests/test_inject.py77
-rw-r--r--src/mailman/app/tests/test_moderation.py7
4 files changed, 101 insertions, 28 deletions
diff --git a/src/mailman/app/docs/pipelines.rst b/src/mailman/app/docs/pipelines.rst
index fbd405f68..56fdeb5c6 100644
--- a/src/mailman/app/docs/pipelines.rst
+++ b/src/mailman/app/docs/pipelines.rst
@@ -24,6 +24,7 @@ Messages hit the pipeline after they've been accepted for posting.
... To: test@example.com
... Subject: My first post
... Message-ID: <first>
+ ... X-Message-ID-Hash: 4CMWUN6BHVCMHMDAOSJZ2Q72G5M32MWB
...
... First post!
... """)
@@ -37,15 +38,15 @@ etc.
From: aperson@example.com
To: test@example.com
Message-ID: <first>
+ X-Message-ID-Hash: 4CMWUN6BHVCMHMDAOSJZ2Q72G5M32MWB
Subject: [Test] My first post
X-Mailman-Version: ...
Precedence: list
List-Id: <test.example.com>
- X-Message-ID-Hash: 4CMWUN6BHVCMHMDAOSJZ2Q72G5M32MWB
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/4CMWUN6BHVCMHMDAOSJZ2Q72G5M32MWB
+ Archived-At: http://lists.example.com/.../4CMWUN6BHVCMHMDAOSJZ2Q72G5M32MWB
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>
@@ -65,15 +66,18 @@ However there are currently no recipients for this message.
After pipeline processing, the message is now sitting in various other
processing queues.
+::
>>> from mailman.testing.helpers import get_queue_messages
>>> messages = get_queue_messages('archive')
>>> len(messages)
1
+
>>> print messages[0].msg.as_string()
From: aperson@example.com
To: test@example.com
Message-ID: <first>
+ X-Message-ID-Hash: 4CMWUN6BHVCMHMDAOSJZ2Q72G5M32MWB
Subject: [Test] My first post
X-Mailman-Version: ...
Precedence: list
@@ -82,6 +86,7 @@ processing queues.
<BLANKLINE>
First post!
<BLANKLINE>
+
>>> dump_msgdata(messages[0].msgdata)
_parsemsg : False
original_sender : aperson@example.com
@@ -97,15 +102,19 @@ the outgoing nntp queue.
>>> len(messages)
0
-This is the message that will actually get delivered to end recipients.
+The outgoing queue will hold the copy of the message that will actually get
+delivered to end recipients.
+::
>>> messages = get_queue_messages('out')
>>> len(messages)
1
+
>>> print messages[0].msg.as_string()
From: aperson@example.com
To: test@example.com
Message-ID: <first>
+ X-Message-ID-Hash: 4CMWUN6BHVCMHMDAOSJZ2Q72G5M32MWB
Subject: [Test] My first post
X-Mailman-Version: ...
Precedence: list
@@ -114,6 +123,7 @@ This is the message that will actually get delivered to end recipients.
<BLANKLINE>
First post!
<BLANKLINE>
+
>>> dump_msgdata(messages[0].msgdata)
_parsemsg : False
listname : test@example.com
@@ -124,15 +134,18 @@ This is the message that will actually get delivered to end recipients.
version : 3
There's now one message in the digest mailbox, getting ready to be sent.
+::
>>> from mailman.testing.helpers import digest_mbox
>>> digest = digest_mbox(mlist)
>>> sum(1 for mboxmsg in digest)
1
+
>>> print list(digest)[0].as_string()
From: aperson@example.com
To: test@example.com
Message-ID: <first>
+ X-Message-ID-Hash: 4CMWUN6BHVCMHMDAOSJZ2Q72G5M32MWB
Subject: [Test] My first post
X-Mailman-Version: ...
Precedence: list
@@ -143,10 +156,8 @@ There's now one message in the digest mailbox, getting ready to be sent.
<BLANKLINE>
-Clean up the digests
-====================
-
- >>> digest.clear()
- >>> digest.flush()
- >>> sum(1 for msg in digest_mbox(mlist))
- 0
+.. Clean up the digests
+ >>> digest.clear()
+ >>> digest.flush()
+ >>> sum(1 for msg in digest_mbox(mlist))
+ 0
diff --git a/src/mailman/app/inject.py b/src/mailman/app/inject.py
index 8bf907af0..5dcaf5584 100644
--- a/src/mailman/app/inject.py
+++ b/src/mailman/app/inject.py
@@ -17,7 +17,7 @@
"""Inject a message into a queue."""
-from __future__ import absolute_import, unicode_literals
+from __future__ import absolute_import, print_function, unicode_literals
__metaclass__ = type
__all__ = [
@@ -31,12 +31,16 @@ from email.utils import formatdate, make_msgid
from mailman.config import config
from mailman.email.message import Message
+from mailman.utilities.email import add_message_hash
def inject_message(mlist, msg, recipients=None, switchboard=None, **kws):
"""Inject a message into a queue.
+ If the message does not have a Message-ID header, one is added. An
+ X-Message-Id-Hash header is also always added.
+
:param mlist: The mailing list this message is destined for.
:type mlist: IMailingList
:param msg: The Message object to inject.
@@ -56,12 +60,14 @@ def inject_message(mlist, msg, recipients=None, switchboard=None, **kws):
# message has a Message-ID.
if 'message-id' not in msg:
msg['Message-ID'] = make_msgid()
+ add_message_hash(msg)
# Ditto for Date: as required by RFC 2822.
if 'date' not in msg:
msg['Date'] = formatdate(localtime=True)
+ msg.original_size = len(msg.as_string())
msgdata = dict(
listname=mlist.fqdn_listname,
- original_size=getattr(msg, 'original_size', len(msg.as_string())),
+ original_size=msg.original_size,
)
msgdata.update(kws)
if recipients is not None:
@@ -73,6 +79,9 @@ def inject_message(mlist, msg, recipients=None, switchboard=None, **kws):
def inject_text(mlist, text, recipients=None, switchboard=None, **kws):
"""Turn text into a message and inject that into a queue.
+ If the text does not have a Message-ID header, one is added. An
+ X-Message-Id-Hash header is also always added.
+
:param mlist: The mailing list this message is destined for.
:type mlist: IMailingList
:param text: The text of the message to inject. This will be parsed into
@@ -88,5 +97,4 @@ def inject_text(mlist, text, recipients=None, switchboard=None, **kws):
:type kws: dictionary
"""
message = message_from_string(text, Message)
- message.original_size = len(text)
inject_message(mlist, message, recipients, switchboard, **kws)
diff --git a/src/mailman/app/tests/test_inject.py b/src/mailman/app/tests/test_inject.py
index de7e4bd29..4e08ff0a7 100644
--- a/src/mailman/app/tests/test_inject.py
+++ b/src/mailman/app/tests/test_inject.py
@@ -17,7 +17,7 @@
"""Testing app.inject functions."""
-from __future__ import absolute_import, unicode_literals
+from __future__ import absolute_import, print_function, unicode_literals
__metaclass__ = type
__all__ = [
@@ -108,14 +108,6 @@ Nothing.
self.assertTrue('date' in items[0].msg)
self.assertEqual(items[0].msg['date'], self.msg['date'])
- def test_inject_message_trusts_original_size_attribute(self):
- # If the message object has an `original_size` attribute, this is
- # copied into the metadata.
- self.msg.original_size = 3
- inject_message(self.mlist, self.msg)
- items = get_queue_messages('in')
- self.assertEqual(items[0].msgdata['original_size'], 3)
-
def test_inject_message_with_keywords(self):
# Keyword arguments are copied into the metadata.
inject_message(self.mlist, self.msg, foo='yes', bar='no')
@@ -123,6 +115,26 @@ Nothing.
self.assertEqual(items[0].msgdata['foo'], 'yes')
self.assertEqual(items[0].msgdata['bar'], 'no')
+ def test_inject_message_id_hash(self):
+ # When the injected message has a Message-ID header, the injected
+ # message will also get an X-Message-ID-Hash header.
+ inject_message(self.mlist, self.msg)
+ items = get_queue_messages('in')
+ self.assertEqual(items[0].msg['x-message-id-hash'],
+ '4CMWUN6BHVCMHMDAOSJZ2Q72G5M32MWB')
+
+ def test_inject_message_id_hash_without_message_id(self):
+ # When the injected message does not have a Message-ID header, a
+ # Message-ID header will be added, and the injected message will also
+ # get an X-Message-ID-Hash header.
+ del self.msg['message-id']
+ self.assertFalse('message-id' in self.msg)
+ self.assertFalse('x-message-id-hash' in self.msg)
+ inject_message(self.mlist, self.msg)
+ items = get_queue_messages('in')
+ self.assertTrue('message-id' in items[0].msg)
+ self.assertTrue('x-message-id-hash' in items[0].msg)
+
class TestInjectText(unittest.TestCase):
@@ -155,9 +167,18 @@ Nothing.
items = get_queue_messages('in')
self.assertEqual(len(items), 1)
self.assertTrue(isinstance(items[0].msg, Message))
+ self.assertEqual(items[0].msg['x-message-id-hash'],
+ 'GUXXQKNCHBFQAHGBFMGCME6HKZCUUH3K')
+ # Delete that header because it is not in the original text.
+ del items[0].msg['x-message-id-hash']
self.eq(items[0].msg.as_string(), self.text)
self.assertEqual(items[0].msgdata['listname'], 'test@example.com')
- self.assertEqual(items[0].msgdata['original_size'], len(self.text))
+ self.assertEqual(items[0].msgdata['original_size'],
+ # Add back the X-Message-ID-Header which was in the
+ # message contributing to the original_size, but
+ # wasn't in the original text. Don't forget the
+ # newline!
+ len(self.text) + 52)
def test_inject_text_with_recipients(self):
# Explicit recipients end up in the metadata.
@@ -173,9 +194,16 @@ Nothing.
self.assertEqual(len(items), 0)
items = get_queue_messages('virgin')
self.assertEqual(len(items), 1)
+ # Remove the X-Message-ID-Hash header which isn't in the original text.
+ del items[0].msg['x-message-id-hash']
self.eq(items[0].msg.as_string(), self.text)
self.assertEqual(items[0].msgdata['listname'], 'test@example.com')
- self.assertEqual(items[0].msgdata['original_size'], len(self.text))
+ self.assertEqual(items[0].msgdata['original_size'],
+ # Add back the X-Message-ID-Header which was in the
+ # message contributing to the original_size, but
+ # wasn't in the original text. Don't forget the
+ # newline!
+ len(self.text) + 52)
def test_inject_text_without_message_id(self):
# inject_text() adds a Message-ID header if it's missing.
@@ -198,7 +226,12 @@ Nothing.
# the injected text.
inject_text(self.mlist, self.text)
items = get_queue_messages('in')
- self.assertEqual(items[0].msgdata['original_size'], len(self.text))
+ self.assertEqual(items[0].msgdata['original_size'],
+ # Add back the X-Message-ID-Header which was in the
+ # message contributing to the original_size, but
+ # wasn't in the original text. Don't forget the
+ # newline!
+ len(self.text) + 52)
def test_inject_text_with_keywords(self):
# Keyword arguments are copied into the metadata.
@@ -206,3 +239,23 @@ Nothing.
items = get_queue_messages('in')
self.assertEqual(items[0].msgdata['foo'], 'yes')
self.assertEqual(items[0].msgdata['bar'], 'no')
+
+ def test_inject_message_id_hash(self):
+ # When the injected message has a Message-ID header, the injected
+ # message will also get an X-Message-ID-Hash header.
+ inject_text(self.mlist, self.text)
+ items = get_queue_messages('in')
+ self.assertEqual(items[0].msg['x-message-id-hash'],
+ 'GUXXQKNCHBFQAHGBFMGCME6HKZCUUH3K')
+
+ def test_inject_message_id_hash_without_message_id(self):
+ # When the injected message does not have a Message-ID header, a
+ # Message-ID header will be added, and the injected message will also
+ # get an X-Message-ID-Hash header.
+ filtered = self._remove_line('message-id')
+ self.assertFalse('Message-ID' in filtered)
+ self.assertFalse('X-Message-ID-Hash' in filtered)
+ inject_text(self.mlist, filtered)
+ items = get_queue_messages('in')
+ self.assertTrue('message-id' in items[0].msg)
+ self.assertTrue('x-message-id-hash' in items[0].msg)
diff --git a/src/mailman/app/tests/test_moderation.py b/src/mailman/app/tests/test_moderation.py
index dea2f5918..bc324faea 100644
--- a/src/mailman/app/tests/test_moderation.py
+++ b/src/mailman/app/tests/test_moderation.py
@@ -17,10 +17,11 @@
"""Moderation tests."""
-from __future__ import absolute_import, unicode_literals
+from __future__ import absolute_import, print_function, unicode_literals
__metaclass__ = type
__all__ = [
+ 'TestModeration',
]
@@ -79,8 +80,8 @@ Message-ID: <alpha>
self.assertTrue('x-peer' in message)
# The X-Mailman-Approved-At header has local timezone information in
# it, so test that separately.
- self.assertEqual(message['x-mailman-approved-at'][:-4],
- 'Mon, 01 Aug 2005 07:49:23 -')
+ self.assertEqual(message['x-mailman-approved-at'][:-5],
+ 'Mon, 01 Aug 2005 07:49:23 ')
del message['x-mailman-approved-at']
# The Message-ID matches the original.
self.assertEqual(message['message-id'], '<alpha>')