1
# Copyright 2010 Canonical Ltd. This software is licensed under the
2
# GNU Affero General Public License version 3 (see the file LICENSE).
3
"""Test the lpsize monekypatches"""
5
from __future__ import with_statement
11
from email.mime.application import MIMEApplication
13
from zope.security.proxy import removeSecurityProxy
15
from Mailman import Errors
16
from Mailman.Handlers import LPSize
18
from canonical.config import config
19
from canonical.testing import (
20
DatabaseFunctionalLayer,
21
LaunchpadFunctionalLayer,
23
from lp.services.mailman.testing import MailmanTestCase
26
class TestLPSizeTestCase(MailmanTestCase):
29
Mailman process() methods quietly return. They may set msg_data key-values
30
or raise an error to end processing. These tests often check for errors,
31
but that does not mean there is an error condition, it only means message
32
processing has reached a final decision. Messages that do not cause a
33
final decision pass through, and the process() methods ends without a
37
layer = LaunchpadFunctionalLayer
40
super(TestLPSizeTestCase, self).setUp()
41
self.team, self.mailing_list = self.factory.makeTeamAndMailingList(
42
'team-1', 'team-1-owner')
43
self.mm_list = self.makeMailmanList(self.mailing_list)
44
self.subscriber_email = removeSecurityProxy(
45
self.team.teamowner.preferredemail).email
48
super(TestLPSizeTestCase, self).tearDown()
49
self.cleanMailmanList(self.mm_list)
51
def test_process_size_under_soft_limit(self):
52
# Any message under 40kb is sent to the list.
53
attachment = MIMEApplication(
54
'\n'.join(['x' * 20] * 1000), 'octet-stream')
55
message = self.makeMailmanMessage(
56
self.mm_list, self.subscriber_email, 'subject', 'content',
57
attachment=attachment)
59
silence = LPSize.process(self.mm_list, message, msg_data)
60
self.assertEqual(None, silence)
62
def test_process_size_over_soft_limit_held(self):
63
# Messages over 40kb held for moderation.
64
self.assertEqual(40000, config.mailman.soft_max_size)
65
attachment = MIMEApplication(
66
'\n'.join(['x' * 40] * 1000), 'octet-stream')
67
message = self.makeMailmanMessage(
68
self.mm_list, self.subscriber_email, 'subject', 'content',
69
attachment=attachment)
71
args = (self.mm_list, message, msg_data)
73
Errors.HoldMessage, LPSize.process, *args)
74
self.assertEqual(1, self.mailing_list.getReviewableMessages().count())
76
def test_process_size_over_hard_limit_discarded(self):
77
# Messages over 1MB are discarded.
78
self.assertEqual(1000000, config.mailman.hard_max_size)
79
attachment = MIMEApplication(
80
'\n'.join(['x' * 1000] * 1000), 'octet-stream')
81
message = self.makeMailmanMessage(
82
self.mm_list, self.subscriber_email, 'subject', 'content',
83
attachment=attachment)
85
args = (self.mm_list, message, msg_data)
87
Errors.DiscardMessage, LPSize.process, *args)
88
self.assertEqual(0, self.mailing_list.getReviewableMessages().count())
91
class TestTruncatedMessage(MailmanTestCase):
92
"""Test truncated_message helper."""
94
layer = DatabaseFunctionalLayer
97
super(TestTruncatedMessage, self).setUp()
98
self.team, self.mailing_list = self.factory.makeTeamAndMailingList(
99
'team-1', 'team-1-owner')
100
self.mm_list = self.makeMailmanList(self.mailing_list)
101
self.subscriber_email = removeSecurityProxy(
102
self.team.teamowner.preferredemail).email
104
def test_attchments_are_removed(self):
105
# Plain-text and multipart are preserved, everything else is removed.
106
attachment = MIMEApplication('binary gibberish', 'octet-stream')
107
message = self.makeMailmanMessage(
108
self.mm_list, self.subscriber_email, 'subject', 'content',
109
attachment=attachment)
110
moderated_message = LPSize.truncated_message(message)
111
parts = [part for part in moderated_message.walk()]
112
types = [part.get_content_type() for part in parts]
113
self.assertEqual(['multipart/mixed', 'text/plain'], types)
115
def test_small_text_is_preserved(self):
116
# Text parts below the limit are unchanged.
117
message = self.makeMailmanMessage(
118
self.mm_list, self.subscriber_email, 'subject', 'content')
119
moderated_message = LPSize.truncated_message(message, limit=1000)
120
parts = [part for part in moderated_message.walk()]
121
types = [part.get_content_type() for part in parts]
122
self.assertEqual(['multipart/mixed', 'text/plain'], types)
123
self.assertEqual('content', parts[1].get_payload())
125
def test_large_text_is_truncated(self):
126
# Text parts above the limit are truncated.
127
message = self.makeMailmanMessage(
128
self.mm_list, self.subscriber_email, 'subject', 'content excess')
129
moderated_message = LPSize.truncated_message(message, limit=7)
130
parts = [part for part in moderated_message.walk()]
131
types = [part.get_content_type() for part in parts]
132
self.assertEqual(['multipart/mixed', 'text/plain'], types)
134
'content\n[truncated for moderation]', parts[1].get_payload())