summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBarry Warsaw2007-12-29 19:53:23 -0500
committerBarry Warsaw2007-12-29 19:53:23 -0500
commit86f00a6cec71753952d1290bdadd836fdba5fdc1 (patch)
tree94bd4167060de21e706fc6dec1848092febaa57a
parent68cce110887cc9fc46fd4c7798f3b8d893f1038f (diff)
downloadmailman-86f00a6cec71753952d1290bdadd836fdba5fdc1.tar.gz
mailman-86f00a6cec71753952d1290bdadd836fdba5fdc1.tar.zst
mailman-86f00a6cec71753952d1290bdadd836fdba5fdc1.zip
Port the maximum message size check to a rule. Add doctest.
Rename the implicit.txt doctest. specialized_message_from_string(): Mimic the way the text->message parser will include the size of the original text as an attribute on the message object. The maximum message size rule will use this information.
-rw-r--r--Mailman/Handlers/Hold.py16
-rw-r--r--Mailman/docs/hold.txt22
-rw-r--r--Mailman/docs/implicit-dest.txt (renamed from Mailman/docs/implicit.txt)2
-rw-r--r--Mailman/docs/max-size.txt41
-rw-r--r--Mailman/queue/__init__.py6
-rw-r--r--Mailman/rules/implicit_dest.py1
-rw-r--r--Mailman/rules/max_size.py49
-rw-r--r--Mailman/tests/test_documentation.py14
8 files changed, 110 insertions, 41 deletions
diff --git a/Mailman/Handlers/Hold.py b/Mailman/Handlers/Hold.py
index 12bab8a8b..81dab3189 100644
--- a/Mailman/Handlers/Hold.py
+++ b/Mailman/Handlers/Hold.py
@@ -165,22 +165,6 @@ def process(mlist, msg, msgdata):
# message because the info would also go to the sender
hold_for_approval(mlist, msg, msgdata, SuspiciousHeaders)
# no return
- #
- # Is the message too big?
- if mlist.max_message_size > 0:
- bodylen = 0
- for line in email.Iterators.body_line_iterator(msg):
- bodylen += len(line)
- for part in msg.walk():
- if part.preamble:
- bodylen += len(part.preamble)
- if part.epilogue:
- bodylen += len(part.epilogue)
- if bodylen/1024.0 > mlist.max_message_size:
- hold_for_approval(mlist, msg, msgdata,
- MessageTooBig(bodylen, mlist.max_message_size))
- # no return
- #
# Are we gatewaying to a moderated newsgroup and is this list the
# moderator's address for the group?
if mlist.news_moderation == 2:
diff --git a/Mailman/docs/hold.txt b/Mailman/docs/hold.txt
index ed3fabdf0..16948331f 100644
--- a/Mailman/docs/hold.txt
+++ b/Mailman/docs/hold.txt
@@ -96,28 +96,6 @@ Just a bit of clean up.
>>> mlist.bounce_matching_headers = None
-Message size
-------------
-
-Mailman can hold messages that are bigger than a given size. Generally this
-is used to prevent huge attachments from getting posted to the list. This
-value is calculated in terms of KB (1024 bytes).
-
- >>> mlist.max_message_size = 1
- >>> one_line = 'x' * 79
- >>> big_body = '\n'.join([one_line] * 15)
- >>> msg = message_from_string("""\
- ... From: aperson@example.com
- ... To: _xtest@example.com
- ...
- ... """ + big_body)
- >>> process(mlist, msg, {})
- Traceback (most recent call last):
- ...
- MessageTooBig
- >>> clear()
-
-
X Hold Notifications
X ------------------
X
diff --git a/Mailman/docs/implicit.txt b/Mailman/docs/implicit-dest.txt
index 967ddc8c7..b6fed2769 100644
--- a/Mailman/docs/implicit.txt
+++ b/Mailman/docs/implicit-dest.txt
@@ -11,7 +11,7 @@ not explicitly mentioned in the set of message recipients.
>>> rule.name
'implicit-dest'
-Mailman will hold messages that have implicit destination, meaning that the
+This rule matches messages that have implicit destination, meaning that the
mailing list's posting address isn't included in the explicit recipients.
>>> mlist.require_explicit_destination = True
diff --git a/Mailman/docs/max-size.txt b/Mailman/docs/max-size.txt
new file mode 100644
index 000000000..b477ecd2b
--- /dev/null
+++ b/Mailman/docs/max-size.txt
@@ -0,0 +1,41 @@
+Message size
+============
+
+The 'message-size' rule matches when the posted message is bigger than a
+specified maximum. Generally this is used to prevent huge attachments from
+getting posted to the list. This value is calculated in terms of KB (1024
+bytes).
+
+ >>> from Mailman.configuration import config
+ >>> mlist = config.db.list_manager.create(u'_xtest@example.com')
+ >>> from Mailman.app.rules import find_rule
+ >>> rule = find_rule('max-size')
+ >>> rule.name
+ 'max-size'
+
+For example, setting the maximum message size to 1 means that any message
+bigger than that will match the rule.
+
+ >>> mlist.max_message_size = 1 # 1024 bytes
+ >>> one_line = u'x' * 79
+ >>> big_body = u'\n'.join([one_line] * 15)
+ >>> msg = message_from_string(u"""\
+ ... From: aperson@example.com
+ ... To: _xtest@example.com
+ ...
+ ... """ + big_body)
+ >>> rule.check(mlist, msg, {})
+ True
+
+Setting the maximum message size to zero means no size check is performed.
+
+ >>> mlist.max_message_size = 0
+ >>> rule.check(mlist, msg, {})
+ False
+
+Of course, if the maximum size is larger than the message's size, then it's
+still okay.
+
+ >>> mlist.max_message_size = msg.original_size/1024.0 + 1
+ >>> rule.check(mlist, msg, {})
+ False
diff --git a/Mailman/queue/__init__.py b/Mailman/queue/__init__.py
index c415834ba..6a1873d60 100644
--- a/Mailman/queue/__init__.py
+++ b/Mailman/queue/__init__.py
@@ -140,7 +140,13 @@ class Switchboard:
msg = cPickle.load(fp)
data = cPickle.load(fp)
if data.get('_parsemsg'):
+ # Calculate the original size of the text now so that we won't
+ # have to generate the message later when we do size restriction
+ # checking.
+ original_size = len(msg)
msg = email.message_from_string(msg, Message.Message)
+ msg.original_size = original_size
+ data['original_size'] = original_size
return msg, data
def finish(self, filebase, preserve=False):
diff --git a/Mailman/rules/implicit_dest.py b/Mailman/rules/implicit_dest.py
index 8c9ba8899..e056a2e9e 100644
--- a/Mailman/rules/implicit_dest.py
+++ b/Mailman/rules/implicit_dest.py
@@ -23,7 +23,6 @@ __metaclass__ = type
import re
from email.utils import getaddresses
-from itertools import chain
from zope.interface import implements
from Mailman.i18n import _
diff --git a/Mailman/rules/max_size.py b/Mailman/rules/max_size.py
new file mode 100644
index 000000000..1e62b2ad8
--- /dev/null
+++ b/Mailman/rules/max_size.py
@@ -0,0 +1,49 @@
+# Copyright (C) 2007 by the Free Software Foundation, Inc.
+#
+# This program 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 2
+# of the License, or (at your option) any later version.
+#
+# This program 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 this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+# USA.
+
+"""The maximum message size rule."""
+
+__all__ = ['max_size']
+__metaclass__ = type
+
+
+from zope.interface import implements
+
+from Mailman.i18n import _
+from Mailman.interfaces import IRule
+
+
+
+class MaximumSize:
+ """The implicit destination rule."""
+ implements(IRule)
+
+ name = 'max-size'
+ description = _('Catch messages that are bigger than a specified maximum.')
+
+ def check(self, mlist, msg, msgdata):
+ """See `IRule`."""
+ if mlist.max_message_size == 0:
+ return False
+ assert hasattr(msg, 'original_size'), (
+ 'Message was not sized on initial parsing.')
+ # The maximum size is specified in 1024 bytes.
+ return msg.original_size / 1024.0 > mlist.max_message_size
+
+
+
+max_size = MaximumSize()
diff --git a/Mailman/tests/test_documentation.py b/Mailman/tests/test_documentation.py
index 390ba6a66..36b3c7ecb 100644
--- a/Mailman/tests/test_documentation.py
+++ b/Mailman/tests/test_documentation.py
@@ -36,7 +36,19 @@ COMMASPACE = ', '
def specialized_message_from_string(text):
- return message_from_string(text, Message)
+ """Parse text into a message object.
+
+ This is specialized in the sense that an instance of Mailman's own Message
+ object is returned, and this message object has an attribute
+ `original_size` which is the pre-calculated size in bytes of the message's
+ text representation.
+ """
+ # This mimic what Switchboard.dequeue() does when parsing a message from
+ # text into a Message instance.
+ original_size = len(text)
+ message = message_from_string(text, Message)
+ message.original_size = original_size
+ return message
def setup(testobj):