summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBarry Warsaw2016-11-14 03:30:54 +0000
committerBarry Warsaw2016-11-14 03:30:54 +0000
commit54d32b872ee4e67a64a176077dbc49a4f87b9324 (patch)
treeba9170245c9f9c87f5604e02a8dc1aaf37443319
parent366dc6517716b7c77c4b7a76559b1b6b5996fc8e (diff)
parenta9e62e4350d1a108af972ab9dc2043f76b98a04c (diff)
downloadmailman-54d32b872ee4e67a64a176077dbc49a4f87b9324.tar.gz
mailman-54d32b872ee4e67a64a176077dbc49a4f87b9324.tar.zst
mailman-54d32b872ee4e67a64a176077dbc49a4f87b9324.zip
-rw-r--r--port_me/checkdbs.py2
-rw-r--r--src/mailman/app/moderator.py2
-rw-r--r--src/mailman/app/subscriptions.py4
-rw-r--r--src/mailman/app/tests/test_moderation.py21
-rw-r--r--src/mailman/app/tests/test_subscriptions.py12
-rw-r--r--src/mailman/chains/hold.py2
-rw-r--r--src/mailman/chains/tests/test_hold.py11
-rw-r--r--src/mailman/docs/NEWS.rst2
-rw-r--r--src/mailman/email/message.py12
9 files changed, 55 insertions, 13 deletions
diff --git a/port_me/checkdbs.py b/port_me/checkdbs.py
index 9e5213b4c..7f46e97d4 100644
--- a/port_me/checkdbs.py
+++ b/port_me/checkdbs.py
@@ -199,7 +199,7 @@ def main():
mlist.GetBouncesEmail(),
subject, text,
mlist.preferred_language)
- msg.send(mlist, **{'tomoderators': True})
+ msg.send(mlist, to_moderators=True)
finally:
mlist.Unlock()
diff --git a/src/mailman/app/moderator.py b/src/mailman/app/moderator.py
index c3347c1ff..9d3856f33 100644
--- a/src/mailman/app/moderator.py
+++ b/src/mailman/app/moderator.py
@@ -204,7 +204,7 @@ def hold_unsubscription(mlist, email):
msg = UserNotification(
mlist.owner_address, mlist.owner_address,
subject, text, mlist.preferred_language)
- msg.send(mlist, tomoderators=True)
+ msg.send(mlist, to_moderators=True)
return request_id
diff --git a/src/mailman/app/subscriptions.py b/src/mailman/app/subscriptions.py
index 9e915a25d..9e8d8dd9d 100644
--- a/src/mailman/app/subscriptions.py
+++ b/src/mailman/app/subscriptions.py
@@ -286,7 +286,7 @@ class SubscriptionWorkflow(_SubscriptionWorkflowCommon):
msg = UserNotification(
self.mlist.owner_address, self.mlist.owner_address,
subject, text, self.mlist.preferred_language)
- msg.send(self.mlist, tomoderators=True)
+ msg.send(self.mlist, to_moderators=True)
# The workflow must stop running here.
raise StopIteration
@@ -434,7 +434,7 @@ class UnSubscriptionWorkflow(_SubscriptionWorkflowCommon):
msg = UserNotification(
self.mlist.owner_address, self.mlist.owner_address,
subject, text, self.mlist.preferred_language)
- msg.send(self.mlist, tomoderators=True)
+ msg.send(self.mlist, to_moderators=True)
# The workflow must stop running here
raise StopIteration
diff --git a/src/mailman/app/tests/test_moderation.py b/src/mailman/app/tests/test_moderation.py
index 20584da49..bb3958cd7 100644
--- a/src/mailman/app/tests/test_moderation.py
+++ b/src/mailman/app/tests/test_moderation.py
@@ -23,6 +23,7 @@ from mailman.app.lifecycle import create_list
from mailman.app.moderator import (
handle_message, handle_unsubscription, hold_message, hold_unsubscription)
from mailman.interfaces.action import Action
+from mailman.interfaces.member import MemberRole
from mailman.interfaces.messages import IMessageStore
from mailman.interfaces.requests import IListRequests
from mailman.interfaces.subscriptions import ISubscriptionManager
@@ -31,7 +32,7 @@ from mailman.runners.incoming import IncomingRunner
from mailman.runners.outgoing import OutgoingRunner
from mailman.runners.pipeline import PipelineRunner
from mailman.testing.helpers import (
- get_queue_messages, make_testable_runner,
+ get_queue_messages, make_testable_runner, set_preferred,
specialized_message_from_string as mfs)
from mailman.testing.layers import SMTPLayer
from mailman.utilities.datetime import now
@@ -158,15 +159,29 @@ class TestUnsubscription(unittest.TestCase):
def test_unsubscribe_defer(self):
# When unsubscriptions must be approved by the moderator, but the
# moderator defers this decision.
- anne = getUtility(IUserManager).create_address(
- 'anne@example.org', 'Anne Person')
+ user_manager = getUtility(IUserManager)
+ anne = user_manager.create_address('anne@example.org', 'Anne Person')
token, token_owner, member = self._manager.register(
anne, pre_verified=True, pre_confirmed=True, pre_approved=True)
self.assertIsNone(token)
self.assertEqual(member.address.email, 'anne@example.org')
+ bart = user_manager.create_user('bart@example.com', 'Bart User')
+ address = set_preferred(bart)
+ self._mlist.subscribe(address, MemberRole.moderator)
# Now hold and handle an unsubscription request.
token = hold_unsubscription(self._mlist, 'anne@example.org')
handle_unsubscription(self._mlist, token, Action.defer)
+ items = get_queue_messages('virgin', expected_count=2)
+ # Find the moderator message.
+ for item in items:
+ if item.msg['to'] == 'test-owner@example.com':
+ break
+ else:
+ raise AssertionError('No moderator email found')
+ self.assertEqual(item.msgdata['recipients'], {'bart@example.com'})
+ self.assertEqual(
+ item.msg['subject'],
+ 'New unsubscription request from Test by anne@example.org')
def test_bogus_token(self):
# Try to handle an unsubscription with a bogus token.
diff --git a/src/mailman/app/tests/test_subscriptions.py b/src/mailman/app/tests/test_subscriptions.py
index 19198307d..f7b9b584e 100644
--- a/src/mailman/app/tests/test_subscriptions.py
+++ b/src/mailman/app/tests/test_subscriptions.py
@@ -24,7 +24,7 @@ from mailman.app.lifecycle import create_list
from mailman.app.subscriptions import SubscriptionWorkflow
from mailman.interfaces.bans import IBanManager
from mailman.interfaces.mailinglist import SubscriptionPolicy
-from mailman.interfaces.member import MembershipIsBannedError
+from mailman.interfaces.member import MemberRole, MembershipIsBannedError
from mailman.interfaces.pending import IPendings
from mailman.interfaces.subscriptions import TokenOwner
from mailman.interfaces.usermanager import IUserManager
@@ -436,12 +436,22 @@ class TestSubscriptionWorkflow(unittest.TestCase):
self._mlist.admin_immed_notify = True
self._mlist.subscription_policy = SubscriptionPolicy.moderate
anne = self._user_manager.create_address(self._anne)
+ bart = self._user_manager.create_user('bart@example.com', 'Bart User')
+ address = set_preferred(bart)
+ self._mlist.subscribe(address, MemberRole.moderator)
workflow = SubscriptionWorkflow(self._mlist, anne,
pre_verified=True,
pre_confirmed=True)
# Consume the entire state machine.
list(workflow)
+ # Find the moderator message.
items = get_queue_messages('virgin', expected_count=1)
+ for item in items:
+ if item.msg['to'] == 'test-owner@example.com':
+ break
+ else:
+ raise AssertionError('No moderator email found')
+ self.assertEqual(item.msgdata['recipients'], {'bart@example.com'})
message = items[0].msg
self.assertEqual(message['From'], 'test-owner@example.com')
self.assertEqual(message['To'], 'test-owner@example.com')
diff --git a/src/mailman/chains/hold.py b/src/mailman/chains/hold.py
index f1bd42961..f111aee3c 100644
--- a/src/mailman/chains/hold.py
+++ b/src/mailman/chains/hold.py
@@ -246,7 +246,7 @@ also appear in the first line of the body of the reply.""")),
nmsg.attach(text)
nmsg.attach(MIMEMessage(msg))
nmsg.attach(MIMEMessage(dmsg))
- nmsg.send(mlist, **dict(tomoderators=True))
+ nmsg.send(mlist, to_moderators=True)
# Log the held message. Log messages are not translated, so recast
# the reasons in the English.
with _.using('en'):
diff --git a/src/mailman/chains/tests/test_hold.py b/src/mailman/chains/tests/test_hold.py
index 0957fe880..13dd1b40e 100644
--- a/src/mailman/chains/tests/test_hold.py
+++ b/src/mailman/chains/tests/test_hold.py
@@ -24,10 +24,11 @@ from mailman.app.lifecycle import create_list
from mailman.chains.hold import autorespond_to_sender
from mailman.core.chains import process as process_chain
from mailman.interfaces.autorespond import IAutoResponseSet, Response
+from mailman.interfaces.member import MemberRole
from mailman.interfaces.messages import IMessageStore
from mailman.interfaces.usermanager import IUserManager
from mailman.testing.helpers import (
- LogFileMark, configuration, get_queue_messages,
+ LogFileMark, configuration, get_queue_messages, set_preferred,
specialized_message_from_string as mfs)
from mailman.testing.layers import ConfigLayer
from pkg_resources import resource_filename
@@ -94,6 +95,7 @@ class TestHoldChain(unittest.TestCase):
def setUp(self):
self._mlist = create_list('test@example.com')
+ self._user_manager = getUtility(IUserManager)
def test_hold_chain(self):
msg = mfs("""\
@@ -133,6 +135,9 @@ A message body.
# Issue #144 - UnicodeEncodeError in the hold chain.
self._mlist.admin_immed_notify = True
self._mlist.respond_to_post_requests = False
+ bart = self._user_manager.create_user('bart@example.com', 'Bart User')
+ address = set_preferred(bart)
+ self._mlist.subscribe(address, MemberRole.moderator)
path = resource_filename('mailman.chains.tests', 'issue144.eml')
with open(path, 'rb') as fp:
msg = mfb(fp.read())
@@ -142,8 +147,8 @@ A message body.
# delivery to the moderators.
items = get_queue_messages('virgin', expected_count=1)
msgdata = items[0].msgdata
- self.assertTrue(msgdata['tomoderators'])
- self.assertEqual(msgdata['recipients'], {'test-owner@example.com'})
+ # Should get sent to moderators.
+ self.assertEqual(msgdata['recipients'], {'bart@example.com'})
# Ensure that the subject looks correct in the postauth.txt.
msg = items[0].msg
value = None
diff --git a/src/mailman/docs/NEWS.rst b/src/mailman/docs/NEWS.rst
index f72498a1d..fdde0589f 100644
--- a/src/mailman/docs/NEWS.rst
+++ b/src/mailman/docs/NEWS.rst
@@ -97,6 +97,8 @@ Bugs
(Closes: #283)
* Remove the digest mbox files after the digests are sent. Given by Aurélien
Bompard. (Closes: #259)
+ * Messages sent to the list's moderators now include the actual recipient
+ addresses. Given by Tom Briles. (Closes: #68)
Configuration
-------------
diff --git a/src/mailman/email/message.py b/src/mailman/email/message.py
index 994d44cce..ebfef9d9b 100644
--- a/src/mailman/email/message.py
+++ b/src/mailman/email/message.py
@@ -31,6 +31,7 @@ from email.header import Header
from email.mime.multipart import MIMEMultipart
from mailman import public
from mailman.config import config
+from mailman.interfaces.member import DeliveryStatus
COMMASPACE = ', '
@@ -131,7 +132,7 @@ class UserNotification(Message):
self['To'] = recipients
self.recipients = set([recipients])
- def send(self, mlist, add_precedence=True, **_kws):
+ def send(self, mlist, *, add_precedence=True, to_moderators=False, **_kws):
"""Sends the message by enqueuing it to the 'virgin' queue.
This is used for all internally crafted messages.
@@ -141,6 +142,9 @@ class UserNotification(Message):
:param add_precedence: Flag indicating whether a `Precedence: bulk`
header should be added to the message or not.
:type add_precedence: bool
+ :param to_moderators: Flag indicating whether the message should be
+ sent to the list's moderators instead of the list's membership.
+ :type to_moderators: bool
This function also accepts arbitrary keyword arguments. The key/value
pairs for **kws is added to the metadata dictionary associated with
@@ -158,6 +162,12 @@ class UserNotification(Message):
# don't override an existing Precedence: header.
if 'precedence' not in self and add_precedence:
self['Precedence'] = 'bulk'
+ if to_moderators:
+ self.recipients = set(
+ member.address.email
+ for member in mlist.moderators.members
+ if member.delivery_status is DeliveryStatus.enabled)
+ self['To'] = COMMASPACE.join(self.recipients)
self._enqueue(mlist, **_kws)
def _enqueue(self, mlist, **_kws):