Merge lp:~abompard/mailman/bug-1130957 into lp:mailman

Proposed by Aurélien Bompard
Status: Merged
Merged at revision: 7268
Proposed branch: lp:~abompard/mailman/bug-1130957
Merge into: lp:mailman
Diff against target: 151 lines (+115/-2)
4 files modified
src/mailman/handlers/owner_recipients.py (+1/-1)
src/mailman/handlers/tests/test_recipients.py (+17/-0)
src/mailman/runners/digest.py (+1/-1)
src/mailman/runners/tests/test_digest.py (+96/-0)
To merge this branch: bzr merge lp:~abompard/mailman/bug-1130957
Reviewer Review Type Date Requested Status
Barry Warsaw Approve
Review via email: mp+243060@code.launchpad.net

Description of the change

Fixes the unicode issues reported in bug #1130957 (unit tests included! ;-))

To post a comment you must log in.
Revision history for this message
Barry Warsaw (barry) wrote :

Looks great, thanks! I cleaned some things up and changed a few things stylistically. All tests pass so I committed fixes.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'src/mailman/handlers/owner_recipients.py'
--- src/mailman/handlers/owner_recipients.py 2014-01-01 14:59:42 +0000
+++ src/mailman/handlers/owner_recipients.py 2014-11-27 16:04:23 +0000
@@ -55,7 +55,7 @@
55 # To prevent -owner messages from going into a black hole, if there55 # To prevent -owner messages from going into a black hole, if there
56 # are no administrators available, the message goes to the site owner.56 # are no administrators available, the message goes to the site owner.
57 if len(recipients) == 0:57 if len(recipients) == 0:
58 msgdata['recipients'] = set((config.mailman.site_owner,))58 msgdata['recipients'] = set((unicode(config.mailman.site_owner),))
59 else:59 else:
60 msgdata['recipients'] = recipients60 msgdata['recipients'] = recipients
61 # Don't decorate these messages with the header/footers. Eventually61 # Don't decorate these messages with the header/footers. Eventually
6262
=== modified file 'src/mailman/handlers/tests/test_recipients.py'
--- src/mailman/handlers/tests/test_recipients.py 2014-01-01 14:59:42 +0000
+++ src/mailman/handlers/tests/test_recipients.py 2014-11-27 16:04:23 +0000
@@ -198,3 +198,20 @@
198 msgdata = {}198 msgdata = {}
199 self._process(self._mlist, self._msg, msgdata)199 self._process(self._mlist, self._msg, msgdata)
200 self.assertEqual(msgdata['recipients'], set(('noreply@example.com',)))200 self.assertEqual(msgdata['recipients'], set(('noreply@example.com',)))
201
202 def test_site_admin_unicode(self):
203 # Since the conf file is read as a bytestring, the site_owner is also a
204 # bytestring and must be converted to unicode when used as a fallback.
205 self._cris.unsubscribe()
206 self._dave.unsubscribe()
207 self.assertEqual(self._mlist.administrators.member_count, 0)
208 msgdata = {}
209 strconf = b"""
210 [mailman]
211 site_owner: siteadmin@example.com
212 """
213 config.push("test_site_admin_unicode", strconf)
214 self._process(self._mlist, self._msg, msgdata)
215 config.pop("test_site_admin_unicode")
216 self.assertEqual(len(msgdata['recipients']), 1)
217 self.assertTrue(isinstance(list(msgdata['recipients'])[0], unicode))
201218
=== modified file 'src/mailman/runners/digest.py'
--- src/mailman/runners/digest.py 2014-04-28 15:23:35 +0000
+++ src/mailman/runners/digest.py 2014-11-27 16:04:23 +0000
@@ -260,7 +260,7 @@
260 # Add the payload. If the decoded payload is empty, this may be a260 # Add the payload. If the decoded payload is empty, this may be a
261 # multipart message. In that case, just stringify it.261 # multipart message. In that case, just stringify it.
262 payload = msg.get_payload(decode=True)262 payload = msg.get_payload(decode=True)
263 payload = (payload if payload else msg.as_string().split('\n\n', 1)[1])263 payload = (payload if payload else msg.as_string().split(b'\n\n', 1)[1])
264 try:264 try:
265 charset = msg.get_content_charset('us-ascii')265 charset = msg.get_content_charset('us-ascii')
266 payload = unicode(payload, charset, 'replace')266 payload = unicode(payload, charset, 'replace')
267267
=== added file 'src/mailman/runners/tests/test_digest.py'
--- src/mailman/runners/tests/test_digest.py 1970-01-01 00:00:00 +0000
+++ src/mailman/runners/tests/test_digest.py 2014-11-27 16:04:23 +0000
@@ -0,0 +1,96 @@
1# Copyright (C) 2012-2014 by the Free Software Foundation, Inc.
2#
3# This file is part of GNU Mailman.
4#
5# GNU Mailman is free software: you can redistribute it and/or modify it under
6# the terms of the GNU General Public License as published by the Free
7# Software Foundation, either version 3 of the License, or (at your option)
8# any later version.
9#
10# GNU Mailman is distributed in the hope that it will be useful, but WITHOUT
11# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13# more details.
14#
15# You should have received a copy of the GNU General Public License along with
16# GNU Mailman. If not, see <http://www.gnu.org/licenses/>.
17
18"""Test the digest runner."""
19
20from __future__ import absolute_import, print_function, unicode_literals
21
22__metaclass__ = type
23__all__ = [
24 'TestDigest',
25 ]
26
27import os
28import unittest
29from email.mime.text import MIMEText
30
31from mailman.app.lifecycle import create_list
32from mailman.config import config
33from mailman.email.message import Message
34from mailman.runners.digest import DigestRunner
35from mailman.testing.helpers import (
36 digest_mbox, make_testable_runner, reset_the_world,
37 specialized_message_from_string as mfs)
38from mailman.testing.layers import ConfigLayer
39
40
41
042
43class TestDigest(unittest.TestCase):
44 """Test the digest runner."""
45
46 layer = ConfigLayer
47
48 def setUp(self):
49 self._mlist = create_list('test@example.com')
50 self._mlist.digest_size_threshold = 1
51 #self._mlist.volume = 1
52 #self._mlist.next_digest_number = 1
53 self._digestq = config.switchboards['digest']
54 self._shuntq = config.switchboards['shunt']
55 self._virginq = config.switchboards['virgin']
56 self._runner = make_testable_runner(DigestRunner, 'digest')
57 self._process = config.handlers['to-digest'].process
58
59 def tearDown(self):
60 reset_the_world()
61
62 def test_simple_message(self):
63 msg = mfs("""\
64From: anne@example.org
65To: test@example.com
66
67message triggering a digest
68""")
69 mbox = digest_mbox(self._mlist)
70 mbox_path = os.path.join(self._mlist.data_path, 'digest.mmdf')
71 self._process(self._mlist, msg, {})
72 self._digestq.enqueue(msg,
73 listname=self._mlist.fqdn_listname,
74 digest_path=mbox_path,
75 volume=1, digest_number=1)
76 self._runner.run()
77
78 def test_non_ascii_message(self):
79 msg = Message()
80 msg["From"] = "anne@example.org"
81 msg["To"] = "test@example.com"
82 msg["Content-Type"] = "multipart/mixed"
83 msg.attach(MIMEText("message with non-ascii chars: \xc3\xa9",
84 "plain", "utf-8"))
85 mbox = digest_mbox(self._mlist)
86 mbox_path = os.path.join(self._mlist.data_path, 'digest.mmdf')
87 mbox.add(msg.as_string())
88 self._digestq.enqueue(msg,
89 listname=self._mlist.fqdn_listname,
90 digest_path=mbox_path,
91 volume=1, digest_number=1)
92 self._runner.run()
93 errorlog = open(os.path.join(config.LOG_DIR, "error")).read()
94 # The runner will send the file to the shunt queue on exception
95 self.assertEqual(len(self._shuntq.files), 0, errorlog)
96 # 2 messages in the virgin queue: the digest as plain-text and as multipart
97 self.assertEqual(len(self._virginq.files), 2, errorlog)