summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/mailman/handlers/docs/acknowledge.rst8
-rw-r--r--src/mailman/handlers/docs/avoid-duplicates.rst12
-rw-r--r--src/mailman/handlers/docs/file-recips.rst27
-rw-r--r--src/mailman/handlers/docs/filtering.rst18
-rw-r--r--src/mailman/handlers/docs/nntp.rst2
-rw-r--r--src/mailman/handlers/docs/replybot.rst8
-rw-r--r--src/mailman/handlers/docs/rfc-2369.rst2
-rw-r--r--src/mailman/handlers/docs/subject-munging.rst2
-rw-r--r--src/mailman/handlers/docs/tagger.rst24
-rw-r--r--src/mailman/handlers/docs/to-outgoing.rst2
-rw-r--r--src/mailman/handlers/mime_delete.py2
-rw-r--r--src/mailman/handlers/tagger.py6
-rw-r--r--src/mailman/handlers/tests/test_file_recips.py76
-rw-r--r--src/mailman/handlers/tests/test_filter.py60
-rw-r--r--src/mailman/testing/helpers.py5
15 files changed, 182 insertions, 72 deletions
diff --git a/src/mailman/handlers/docs/acknowledge.rst b/src/mailman/handlers/docs/acknowledge.rst
index e91f94f62..42cab04a0 100644
--- a/src/mailman/handlers/docs/acknowledge.rst
+++ b/src/mailman/handlers/docs/acknowledge.rst
@@ -113,9 +113,9 @@ The receipt will include the original message's subject in the response body,
1
>>> dump_msgdata(messages[0].msgdata)
_parsemsg : False
- listname : test@example.com
+ listid : test.example.com
nodecorate : True
- recipients : set([u'aperson@example.com'])
+ recipients : {'aperson@example.com'}
reduced_list_headers: True
...
>>> print(messages[0].msg.as_string())
@@ -150,9 +150,9 @@ If there is no subject, then the receipt will use a generic message.
1
>>> dump_msgdata(messages[0].msgdata)
_parsemsg : False
- listname : test@example.com
+ listid : test.example.com
nodecorate : True
- recipients : set([u'aperson@example.com'])
+ recipients : {'aperson@example.com'}
reduced_list_headers: True
...
>>> print(messages[0].msg.as_string())
diff --git a/src/mailman/handlers/docs/avoid-duplicates.rst b/src/mailman/handlers/docs/avoid-duplicates.rst
index 612634941..19a41bf85 100644
--- a/src/mailman/handlers/docs/avoid-duplicates.rst
+++ b/src/mailman/handlers/docs/avoid-duplicates.rst
@@ -71,7 +71,7 @@ or ``Resent-CC``), then they will get a list copy.
>>> msgdata = recips.copy()
>>> handler.process(mlist, msg, msgdata)
>>> sorted(msgdata['recipients'])
- [u'aperson@example.com', u'bperson@example.com']
+ ['aperson@example.com', 'bperson@example.com']
>>> print(msg.as_string())
From: Claire Person <cperson@example.com>
<BLANKLINE>
@@ -89,7 +89,7 @@ If they're mentioned on the ``CC`` line, they won't get a list copy.
>>> msgdata = recips.copy()
>>> handler.process(mlist, msg, msgdata)
>>> sorted(msgdata['recipients'])
- [u'bperson@example.com']
+ ['bperson@example.com']
>>> print(msg.as_string())
From: Claire Person <cperson@example.com>
CC: aperson@example.com
@@ -109,7 +109,7 @@ to ``True`` (the default), then they still get a list copy.
>>> msgdata = recips.copy()
>>> handler.process(mlist, msg, msgdata)
>>> sorted(msgdata['recipients'])
- [u'aperson@example.com', u'bperson@example.com']
+ ['aperson@example.com', 'bperson@example.com']
>>> print(msg.as_string())
From: Claire Person <cperson@example.com>
CC: bperson@example.com
@@ -128,7 +128,7 @@ Other headers checked for recipients include the ``To``...
>>> msgdata = recips.copy()
>>> handler.process(mlist, msg, msgdata)
>>> sorted(msgdata['recipients'])
- [u'bperson@example.com']
+ ['bperson@example.com']
>>> print(msg.as_string())
From: Claire Person <cperson@example.com>
To: aperson@example.com
@@ -147,7 +147,7 @@ Other headers checked for recipients include the ``To``...
>>> msgdata = recips.copy()
>>> handler.process(mlist, msg, msgdata)
>>> sorted(msgdata['recipients'])
- [u'bperson@example.com']
+ ['bperson@example.com']
>>> print(msg.as_string())
From: Claire Person <cperson@example.com>
Resent-To: aperson@example.com
@@ -166,7 +166,7 @@ Other headers checked for recipients include the ``To``...
>>> msgdata = recips.copy()
>>> handler.process(mlist, msg, msgdata)
>>> sorted(msgdata['recipients'])
- [u'bperson@example.com']
+ ['bperson@example.com']
>>> print(msg.as_string())
From: Claire Person <cperson@example.com>
Resent-Cc: aperson@example.com
diff --git a/src/mailman/handlers/docs/file-recips.rst b/src/mailman/handlers/docs/file-recips.rst
index 58af6f480..73b47adb1 100644
--- a/src/mailman/handlers/docs/file-recips.rst
+++ b/src/mailman/handlers/docs/file-recips.rst
@@ -34,26 +34,6 @@ returns.
recipients: 7
-Missing file
-============
-
-The include file must live inside the list's data directory, under the name
-``members.txt``. If the file doesn't exist, the list of recipients will be
-empty.
-
- >>> import os
- >>> file_path = os.path.join(mlist.data_path, 'members.txt')
- >>> open(file_path)
- Traceback (most recent call last):
- ...
- IOError: [Errno ...]
- No such file or directory: u'.../_xtest@example.com/members.txt'
- >>> msgdata = {}
- >>> handler.process(mlist, msg, msgdata)
- >>> dump_list(msgdata['recipients'])
- *Empty*
-
-
Existing file
=============
@@ -61,16 +41,15 @@ If the file exists, it contains a list of addresses, one per line. These
addresses are returned as the set of recipients.
::
- >>> fp = open(file_path, 'w')
- >>> try:
+ >>> import os
+ >>> file_path = os.path.join(mlist.data_path, 'members.txt')
+ >>> with open(file_path, 'w', encoding='utf-8') as fp:
... print('bperson@example.com', file=fp)
... print('cperson@example.com', file=fp)
... print('dperson@example.com', file=fp)
... print('eperson@example.com', file=fp)
... print('fperson@example.com', file=fp)
... print('gperson@example.com', file=fp)
- ... finally:
- ... fp.close()
>>> msgdata = {}
>>> handler.process(mlist, msg, msgdata)
diff --git a/src/mailman/handlers/docs/filtering.rst b/src/mailman/handlers/docs/filtering.rst
index 6c3735f1b..6673933ad 100644
--- a/src/mailman/handlers/docs/filtering.rst
+++ b/src/mailman/handlers/docs/filtering.rst
@@ -26,6 +26,8 @@ Filtering the outer content type
A simple filtering setting will just search the content types of the messages
parts, discarding all parts with a matching MIME type. If the message's outer
content type matches the filter, the entire message will be discarded.
+However, if we turn off content filtering altogether, then the handler
+short-circuits.
::
>>> from mailman.interfaces.mime import FilterAction
@@ -42,14 +44,6 @@ content type matches the filter, the entire message will be discarded.
... """)
>>> process = config.handlers['mime-delete'].process
- >>> process(mlist, msg, {})
- Traceback (most recent call last):
- ...
- DiscardMessage: The message's content type was explicitly disallowed
-
-However, if we turn off content filtering altogether, then the handler
-short-circuits.
-
>>> mlist.filter_content = False
>>> msgdata = {}
>>> process(mlist, msg, msgdata)
@@ -74,15 +68,15 @@ crafted internally by Mailman.
MIME-Version: 1.0
<BLANKLINE>
xxxxx
- >>> msgdata
- {u'isdigest': True}
+ >>> dump_msgdata(msgdata)
+ isdigest: True
Simple multipart filtering
==========================
-If one of the subparts in a multipart message matches the filter type, then
-just that subpart will be stripped.
+If one of the subparts in a ``multipart`` message matches the filter type,
+then just that subpart will be stripped.
::
>>> msg = message_from_string("""\
diff --git a/src/mailman/handlers/docs/nntp.rst b/src/mailman/handlers/docs/nntp.rst
index 2dfc95ce1..72bcb35f0 100644
--- a/src/mailman/handlers/docs/nntp.rst
+++ b/src/mailman/handlers/docs/nntp.rst
@@ -63,5 +63,5 @@ messages are gated to.
>>> dump_msgdata(messages[0].msgdata)
_parsemsg: False
- listname : test@example.com
+ listid : test.example.com
version : 3
diff --git a/src/mailman/handlers/docs/replybot.rst b/src/mailman/handlers/docs/replybot.rst
index 638c2fdc8..9e18ce911 100644
--- a/src/mailman/handlers/docs/replybot.rst
+++ b/src/mailman/handlers/docs/replybot.rst
@@ -49,9 +49,9 @@ response.
>>> dump_msgdata(messages[0].msgdata)
_parsemsg : False
- listname : _xtest@example.com
+ listid : _xtest.example.com
nodecorate : True
- recipients : set([u'aperson@example.com'])
+ recipients : {'aperson@example.com'}
reduced_list_headers: True
version : 3
@@ -141,9 +141,9 @@ Unless the ``X-Ack:`` header has a value of ``yes``, in which case, the
>>> dump_msgdata(messages[0].msgdata)
_parsemsg : False
- listname : _xtest@example.com
+ listid : _xtest.example.com
nodecorate : True
- recipients : set([u'asystem@example.com'])
+ recipients : {'asystem@example.com'}
reduced_list_headers: True
version : 3
diff --git a/src/mailman/handlers/docs/rfc-2369.rst b/src/mailman/handlers/docs/rfc-2369.rst
index 8180b0635..b5a783edc 100644
--- a/src/mailman/handlers/docs/rfc-2369.rst
+++ b/src/mailman/handlers/docs/rfc-2369.rst
@@ -13,7 +13,7 @@ headers generally start with the `List-` prefix.
..
This is a helper function for the following section.
>>> def list_headers(msg, only=None):
- ... if isinstance(only, basestring):
+ ... if isinstance(only, str):
... only = (only.lower(),)
... elif only is None:
... only = set(header.lower() for header in msg.keys()
diff --git a/src/mailman/handlers/docs/subject-munging.rst b/src/mailman/handlers/docs/subject-munging.rst
index 072e80d17..6f70a9d5e 100644
--- a/src/mailman/handlers/docs/subject-munging.rst
+++ b/src/mailman/handlers/docs/subject-munging.rst
@@ -35,7 +35,7 @@ subject munging, a mailing list must have a preferred language.
The original subject header is stored in the message metadata.
>>> msgdata['original_subject']
- u''
+ ''
>>> print(msg['subject'])
[XTest] (no subject)
diff --git a/src/mailman/handlers/docs/tagger.rst b/src/mailman/handlers/docs/tagger.rst
index f3303b7ef..fcefdb01c 100644
--- a/src/mailman/handlers/docs/tagger.rst
+++ b/src/mailman/handlers/docs/tagger.rst
@@ -55,7 +55,7 @@ and the message metadata gets a key with a list of matching topic names.
<BLANKLINE>
<BLANKLINE>
>>> msgdata['topichits']
- [u'bar fight']
+ ['bar fight']
Scanning body lines
@@ -114,7 +114,7 @@ found.
Keywords: barbaz
<BLANKLINE>
>>> msgdata['topichits']
- [u'bar fight']
+ ['bar fight']
However, scanning stops at the first body line that doesn't look like a
header.
@@ -161,7 +161,7 @@ When set to a negative number, all body lines will be scanned.
>>> print(msg['x-topics'])
bar fight
>>> msgdata['topichits']
- [u'bar fight']
+ ['bar fight']
Scanning sub-parts
@@ -175,14 +175,14 @@ text payload.
... Subject: Was
... Keywords: Raw
... Content-Type: multipart/alternative; boundary="BOUNDARY"
- ...
+ ...
... --BOUNDARY
... From: sabo
... To: obas
- ...
+ ...
... Subject: farbaw
... Keywords: barbaz
- ...
+ ...
... --BOUNDARY--
... """)
>>> msgdata = {}
@@ -203,7 +203,7 @@ text payload.
--BOUNDARY--
<BLANKLINE>
>>> msgdata['topichits']
- [u'bar fight']
+ ['bar fight']
But the tagger will not descend into non-text parts.
@@ -211,23 +211,23 @@ But the tagger will not descend into non-text parts.
... Subject: Was
... Keywords: Raw
... Content-Type: multipart/alternative; boundary=BOUNDARY
- ...
+ ...
... --BOUNDARY
... From: sabo
... To: obas
... Content-Type: message/rfc822
- ...
+ ...
... Subject: farbaw
... Keywords: barbaz
- ...
+ ...
... --BOUNDARY
... From: sabo
... To: obas
... Content-Type: message/rfc822
- ...
+ ...
... Subject: farbaw
... Keywords: barbaz
- ...
+ ...
... --BOUNDARY--
... """)
>>> msgdata = {}
diff --git a/src/mailman/handlers/docs/to-outgoing.rst b/src/mailman/handlers/docs/to-outgoing.rst
index e87fd4f26..90ea137a5 100644
--- a/src/mailman/handlers/docs/to-outgoing.rst
+++ b/src/mailman/handlers/docs/to-outgoing.rst
@@ -37,6 +37,6 @@ additional key set: the mailing list name.
_parsemsg: False
bar : 2
foo : 1
- listname : test@example.com
+ listid : test.example.com
verp : True
version : 3
diff --git a/src/mailman/handlers/mime_delete.py b/src/mailman/handlers/mime_delete.py
index 98c1de3f9..b5c937fdb 100644
--- a/src/mailman/handlers/mime_delete.py
+++ b/src/mailman/handlers/mime_delete.py
@@ -245,7 +245,7 @@ def to_plaintext(msg):
filename = tempfile.mktemp('.html')
fp = open(filename, 'w')
try:
- fp.write(subpart.get_payload(decode=True))
+ fp.write(subpart.get_payload())
fp.close()
cmd = os.popen(config.HTML_TO_PLAIN_TEXT_COMMAND %
{'filename': filename})
diff --git a/src/mailman/handlers/tagger.py b/src/mailman/handlers/tagger.py
index 803cc6d11..51ff6b39e 100644
--- a/src/mailman/handlers/tagger.py
+++ b/src/mailman/handlers/tagger.py
@@ -37,7 +37,7 @@ from mailman.interfaces.handler import IHandler
OR = '|'
CRNL = '\r\n'
-EMPTYBYTES = b''
+EMPTYSTRING = ''
NLTAB = '\n\t'
@@ -104,7 +104,7 @@ def scanbody(msg, numlines=None):
reader = list(email.iterators.body_line_iterator(msg))
while numlines is None or lineno < numlines:
try:
- line = bytes(reader.pop(0))
+ line = reader.pop(0)
except IndexError:
break
# Blank lines don't count
@@ -115,7 +115,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(EMPTYBYTES.join(lines))
+ msg = p.parsestr(EMPTYSTRING.join(lines))
return msg.get_all('subject', []) + msg.get_all('keywords', [])
diff --git a/src/mailman/handlers/tests/test_file_recips.py b/src/mailman/handlers/tests/test_file_recips.py
new file mode 100644
index 000000000..9f3e0ec6e
--- /dev/null
+++ b/src/mailman/handlers/tests/test_file_recips.py
@@ -0,0 +1,76 @@
+# Copyright (C) 2014 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 file-recips handler."""
+
+from __future__ import absolute_import, print_function, unicode_literals
+
+__metaclass__ = type
+__all__ = [
+ 'TestFileRecips',
+ ]
+
+
+import os
+import unittest
+
+from mailman.app.lifecycle import create_list
+from mailman.config import config
+from mailman.testing.helpers import specialized_message_from_string as mfs
+from mailman.testing.layers import ConfigLayer
+
+
+
+class TestFileRecips(unittest.TestCase):
+ layer = ConfigLayer
+
+ def setUp(self):
+ self._mlist = create_list('test@example.com')
+ self._handler = config.handlers['file-recipients'].process
+ self._msg = mfs("""\
+From: aperson@example.com
+
+A message.
+""")
+
+ def test_file_is_missing(self):
+ # It is not an error for the list's the members.txt file to be
+ # missing. The missing file is just ignored.
+ msgdata = {}
+ self._handler(self._mlist, self._msg, msgdata)
+ self.assertEqual(msgdata['recipients'], set())
+
+ def test_file_exists(self):
+ # Like above, but the file exists and contains recipients.
+ path = os.path.join(self._mlist.data_path, 'members.txt')
+ with open(path, 'w', encoding='utf-8') as fp:
+ print('bperson@example.com', file=fp)
+ print('cperson@example.com', file=fp)
+ print('dperson@example.com', file=fp)
+ print('eperson@example.com', file=fp)
+ print('fperson@example.com', file=fp)
+ print('gperson@example.com', file=fp)
+ msgdata = {}
+ self._handler(self._mlist, self._msg, msgdata)
+ self.assertEqual(msgdata['recipients'], set((
+ 'bperson@example.com',
+ 'cperson@example.com',
+ 'dperson@example.com',
+ 'eperson@example.com',
+ 'fperson@example.com',
+ 'gperson@example.com',
+ )))
diff --git a/src/mailman/handlers/tests/test_filter.py b/src/mailman/handlers/tests/test_filter.py
new file mode 100644
index 000000000..292e646cd
--- /dev/null
+++ b/src/mailman/handlers/tests/test_filter.py
@@ -0,0 +1,60 @@
+# Copyright (C) 2014 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 filter handler."""
+
+from __future__ import absolute_import, print_function, unicode_literals
+
+__metaclass__ = type
+__all__ = [
+ 'TestFilters',
+ ]
+
+
+import unittest
+
+from mailman.app.lifecycle import create_list
+from mailman.config import config
+from mailman.core.errors import DiscardMessage
+from mailman.interfaces.mime import FilterAction
+from mailman.testing.helpers import specialized_message_from_string as mfs
+from mailman.testing.layers import ConfigLayer
+
+
+
+class TestFilters(unittest.TestCase):
+ layer = ConfigLayer
+
+ def setUp(self):
+ self._mlist = create_list('test@example.com')
+
+ def test_discard_when_outer_type_matches(self):
+ # When the outer MIME type of the message matches a filter type, the
+ # entire message is discarded.
+ self._mlist.filter_content = True
+ self._mlist.filter_types = ['image/jpeg']
+ self._mlist.filter_action = FilterAction.discard
+ msg = mfs("""\
+From: aperson@example.com
+Content-Type: image/jpeg
+MIME-Version: 1.0
+
+xxxxx
+""")
+ self.assertRaises(DiscardMessage,
+ config.handlers['mime-delete'].process,
+ self._mlist, msg, {})
diff --git a/src/mailman/testing/helpers.py b/src/mailman/testing/helpers.py
index 882e69cd9..5bfac20ee 100644
--- a/src/mailman/testing/helpers.py
+++ b/src/mailman/testing/helpers.py
@@ -471,10 +471,11 @@ def reset_the_world():
"""
# Reset the database between tests.
config.db._reset()
- # Remove any digest files.
+ # Remove any digest files and members.txt file (for the file-recips
+ # handler) in the lists' data directories.
for dirpath, dirnames, filenames in os.walk(config.LIST_DATA_DIR):
for filename in filenames:
- if filename.endswith('.mmdf'):
+ if filename.endswith('.mmdf') or filename == 'members.txt':
os.remove(os.path.join(dirpath, filename))
# Remove all residual queue files.
for dirpath, dirnames, filenames in os.walk(config.QUEUE_DIR):