summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAurélien Bompard2016-02-09 12:23:38 +0100
committerBarry Warsaw2016-03-31 18:29:27 -0400
commit71cfeda5fb51c49fd87b6d34e00221a3725b9ec0 (patch)
treed571db90e7010643ea7cca81ab91eaee89e0f378
parent011d278abcc25d417673f70a4eac0a8a78137d95 (diff)
downloadmailman-71cfeda5fb51c49fd87b6d34e00221a3725b9ec0.tar.gz
mailman-71cfeda5fb51c49fd87b6d34e00221a3725b9ec0.tar.zst
mailman-71cfeda5fb51c49fd87b6d34e00221a3725b9ec0.zip
-rw-r--r--src/mailman/chains/docs/moderation.rst29
-rw-r--r--src/mailman/model/docs/membership.rst23
-rw-r--r--src/mailman/model/member.py10
-rw-r--r--src/mailman/model/tests/test_member.py21
-rw-r--r--src/mailman/rest/docs/addresses.rst5
-rw-r--r--src/mailman/rest/docs/membership.rst50
-rw-r--r--src/mailman/rest/members.py4
-rw-r--r--src/mailman/rules/docs/moderation.rst17
-rw-r--r--src/mailman/rules/moderation.py9
-rw-r--r--src/mailman/rules/tests/test_moderation.py57
-rw-r--r--src/mailman/utilities/importer.py2
-rw-r--r--src/mailman/utilities/tests/test_import.py5
12 files changed, 144 insertions, 88 deletions
diff --git a/src/mailman/chains/docs/moderation.rst b/src/mailman/chains/docs/moderation.rst
index cd0a8eb26..2415b8f4b 100644
--- a/src/mailman/chains/docs/moderation.rst
+++ b/src/mailman/chains/docs/moderation.rst
@@ -33,12 +33,7 @@ determined by the mailing list's settings. By default, a mailing list is not
set to moderate new member postings.
::
- >>> from mailman.testing.helpers import subscribe
- >>> member = subscribe(mlist, 'Anne', email='anne@example.com')
- >>> member
- <Member: Anne Person <anne@example.com> on test@example.com
- as MemberRole.member>
- >>> print(member.moderation_action)
+ >>> print(mlist.default_member_action)
Action.defer
In order to find out whether the message is held or accepted, we can subscribe
@@ -58,6 +53,18 @@ to Zope events that are triggered on each case.
... for miss in event.msgdata.get('rule_misses', []):
... print(' ', miss)
+The user Anne will be a list member. A list member's default moderation action
+is ``None``, meaning that it will use the mailing list's
+``default_member_action``.
+
+ >>> from mailman.testing.helpers import subscribe
+ >>> member = subscribe(mlist, 'Anne', email='anne@example.com')
+ >>> member
+ <Member: Anne Person <anne@example.com> on test@example.com
+ as MemberRole.member>
+ >>> print(member.moderation_action is None)
+ True
+
Anne's post to the mailing list runs through the incoming runner's default
built-in chain. No rules hit and so the message is accepted.
::
@@ -173,8 +180,8 @@ Nonmembers
==========
Registered nonmembers are handled very similarly to members, the main
-difference being that they usually have a default moderation action. This is
-how the incoming runner adds sender addresses as nonmembers.
+difference being that the mailing list's default moderation action is
+different. This is how the incoming runner adds sender addresses as nonmembers.
>>> from zope.component import getUtility
>>> from mailman.interfaces.usermanager import IUserManager
@@ -211,5 +218,11 @@ moderator approval.
>>> nonmember = mlist.nonmembers.get_member('bart@example.com')
>>> nonmember
<Member: bart@example.com on test@example.com as MemberRole.nonmember>
+
+A nonmember's default moderation action is ``None``, meaning that it will use
+the mailing list's ``default_nonmember_action``.
+
>>> print(nonmember.moderation_action)
+ None
+ >>> print(mlist.default_nonmember_action)
Action.hold
diff --git a/src/mailman/model/docs/membership.rst b/src/mailman/model/docs/membership.rst
index 0fd748d6a..c8452abf0 100644
--- a/src/mailman/model/docs/membership.rst
+++ b/src/mailman/model/docs/membership.rst
@@ -273,23 +273,26 @@ automatically accepted for posting to the mailing list.
aperson@example.com MemberRole.owner Action.accept
bperson@example.com MemberRole.moderator Action.accept
-By default, members have a *deferred* action which specifies that the posting
-should go through the normal moderation checks.
+By default, members and nonmembers have their action set to None, meaning that
+the mailing list's ``default_member_action`` or ``default_nonmember_action``
+will be used.
>>> for member in sorted(mlist.members.members,
... key=attrgetter('address.email')):
... print(member.address.email, member.role, member.moderation_action)
- aperson@example.com MemberRole.member Action.defer
- bperson@example.com MemberRole.member Action.defer
- cperson@example.com MemberRole.member Action.defer
- hperson@example.com MemberRole.member Action.defer
- iperson@example.com MemberRole.member Action.defer
-
-Postings by nonmembers are held for moderator approval by default.
+ aperson@example.com MemberRole.member None
+ bperson@example.com MemberRole.member None
+ cperson@example.com MemberRole.member None
+ hperson@example.com MemberRole.member None
+ iperson@example.com MemberRole.member None
>>> for member in mlist.nonmembers.members:
... print(member.address.email, member.role, member.moderation_action)
- fperson@example.com MemberRole.nonmember Action.hold
+ fperson@example.com MemberRole.nonmember None
+
+The mailing list's default action for members is *deferred*, which specifies
+that the posting should go through the normal moderation checks. Its default
+action for nonmembers is to hold for moderator approval.
Changing subscriptions
diff --git a/src/mailman/model/member.py b/src/mailman/model/member.py
index 99f2de9b8..a6555c0fe 100644
--- a/src/mailman/model/member.py
+++ b/src/mailman/model/member.py
@@ -76,14 +76,10 @@ class Member(Model):
raise ValueError('subscriber must be a user or address')
if role in (MemberRole.owner, MemberRole.moderator):
self.moderation_action = Action.accept
- elif role is MemberRole.member:
- self.moderation_action = getUtility(IListManager).get_by_list_id(
- list_id).default_member_action
else:
- assert role is MemberRole.nonmember, (
- 'Invalid MemberRole: {}'.format(role))
- self.moderation_action = getUtility(IListManager).get_by_list_id(
- list_id).default_nonmember_action
+ assert role in (MemberRole.member, MemberRole.nonmember), (
+ 'Invalid MemberRole: {0}'.format(role))
+ self.moderation_action = None
def __repr__(self):
return '<Member: {} on {} as {}>'.format(
diff --git a/src/mailman/model/tests/test_member.py b/src/mailman/model/tests/test_member.py
index 3a24d9680..51402b659 100644
--- a/src/mailman/model/tests/test_member.py
+++ b/src/mailman/model/tests/test_member.py
@@ -20,6 +20,7 @@
import unittest
from mailman.app.lifecycle import create_list
+from mailman.interfaces.action import Action
from mailman.interfaces.member import MemberRole, MembershipError
from mailman.interfaces.user import UnverifiedAddressError
from mailman.interfaces.usermanager import IUserManager
@@ -100,3 +101,23 @@ class TestMember(unittest.TestCase):
member = self._mlist.members.get_member('anne@example.com')
member.unsubscribe()
self.assertEqual(len(list(self._mlist.members.members)), 0)
+
+ def test_default_moderation_action(self):
+ # Owners and moderators have their posts accepted, members and
+ # nonmembers default to the mailing list's action for their type.
+ anne = self._usermanager.create_user('anne@example.com')
+ bart = self._usermanager.create_user('bart@example.com')
+ cris = self._usermanager.create_user('cris@example.com')
+ dana = self._usermanager.create_user('dana@example.com')
+ set_preferred(anne)
+ set_preferred(bart)
+ set_preferred(cris)
+ set_preferred(dana)
+ anne_member = self._mlist.subscribe(anne, MemberRole.owner)
+ bart_member = self._mlist.subscribe(bart, MemberRole.moderator)
+ cris_member = self._mlist.subscribe(cris, MemberRole.member)
+ dana_member = self._mlist.subscribe(dana, MemberRole.nonmember)
+ self.assertEqual(anne_member.moderation_action, Action.accept)
+ self.assertEqual(bart_member.moderation_action, Action.accept)
+ self.assertIsNone(cris_member.moderation_action)
+ self.assertIsNone(dana_member.moderation_action)
diff --git a/src/mailman/rest/docs/addresses.rst b/src/mailman/rest/docs/addresses.rst
index c850503c4..e5dff0f7c 100644
--- a/src/mailman/rest/docs/addresses.rst
+++ b/src/mailman/rest/docs/addresses.rst
@@ -379,7 +379,6 @@ Elle can get her memberships for each of her email addresses.
http_etag: "..."
list_id: ant.example.com
member_id: 1
- moderation_action: defer
role: member
self_link: http://localhost:9001/3.0/members/1
user: http://localhost:9001/3.0/users/4
@@ -390,7 +389,6 @@ Elle can get her memberships for each of her email addresses.
http_etag: "..."
list_id: bee.example.com
member_id: 2
- moderation_action: defer
role: member
self_link: http://localhost:9001/3.0/members/2
user: http://localhost:9001/3.0/users/4
@@ -422,7 +420,6 @@ does not show up in the list of memberships for his other address.
http_etag: "..."
list_id: ant.example.com
member_id: 1
- moderation_action: defer
role: member
self_link: http://localhost:9001/3.0/members/1
user: http://localhost:9001/3.0/users/4
@@ -433,7 +430,6 @@ does not show up in the list of memberships for his other address.
http_etag: "..."
list_id: bee.example.com
member_id: 2
- moderation_action: defer
role: member
self_link: http://localhost:9001/3.0/members/2
user: http://localhost:9001/3.0/users/4
@@ -450,7 +446,6 @@ does not show up in the list of memberships for his other address.
http_etag: "..."
list_id: bee.example.com
member_id: 3
- moderation_action: defer
role: member
self_link: http://localhost:9001/3.0/members/3
user: http://localhost:9001/3.0/users/4
diff --git a/src/mailman/rest/docs/membership.rst b/src/mailman/rest/docs/membership.rst
index 3d2d9a010..ec8765d68 100644
--- a/src/mailman/rest/docs/membership.rst
+++ b/src/mailman/rest/docs/membership.rst
@@ -50,7 +50,6 @@ the REST interface.
http_etag: ...
list_id: bee.example.com
member_id: 1
- moderation_action: defer
role: member
self_link: http://localhost:9001/3.0/members/1
user: http://localhost:9001/3.0/users/1
@@ -67,7 +66,6 @@ Bart's specific membership can be accessed directly:
http_etag: ...
list_id: bee.example.com
member_id: 1
- moderation_action: defer
role: member
self_link: http://localhost:9001/3.0/members/1
user: http://localhost:9001/3.0/users/1
@@ -88,7 +86,6 @@ the REST interface.
http_etag: ...
list_id: bee.example.com
member_id: 1
- moderation_action: defer
role: member
self_link: http://localhost:9001/3.0/members/1
user: http://localhost:9001/3.0/users/1
@@ -99,7 +96,6 @@ the REST interface.
http_etag: ...
list_id: bee.example.com
member_id: 2
- moderation_action: defer
role: member
self_link: http://localhost:9001/3.0/members/2
user: http://localhost:9001/3.0/users/2
@@ -123,7 +119,6 @@ subscribes, she is returned first.
http_etag: ...
list_id: bee.example.com
member_id: 3
- moderation_action: defer
role: member
self_link: http://localhost:9001/3.0/members/3
user: http://localhost:9001/3.0/users/3
@@ -134,7 +129,6 @@ subscribes, she is returned first.
http_etag: ...
list_id: bee.example.com
member_id: 1
- moderation_action: defer
role: member
self_link: http://localhost:9001/3.0/members/1
user: http://localhost:9001/3.0/users/1
@@ -145,7 +139,6 @@ subscribes, she is returned first.
http_etag: ...
list_id: bee.example.com
member_id: 2
- moderation_action: defer
role: member
self_link: http://localhost:9001/3.0/members/2
user: http://localhost:9001/3.0/users/2
@@ -175,7 +168,6 @@ User ids are different than member ids.
http_etag: ...
list_id: ant.example.com
member_id: 4
- moderation_action: defer
role: member
self_link: http://localhost:9001/3.0/members/4
user: http://localhost:9001/3.0/users/3
@@ -186,7 +178,6 @@ User ids are different than member ids.
http_etag: ...
list_id: ant.example.com
member_id: 5
- moderation_action: defer
role: member
self_link: http://localhost:9001/3.0/members/5
user: http://localhost:9001/3.0/users/2
@@ -197,7 +188,6 @@ User ids are different than member ids.
http_etag: ...
list_id: bee.example.com
member_id: 3
- moderation_action: defer
role: member
self_link: http://localhost:9001/3.0/members/3
user: http://localhost:9001/3.0/users/3
@@ -208,7 +198,6 @@ User ids are different than member ids.
http_etag: ...
list_id: bee.example.com
member_id: 1
- moderation_action: defer
role: member
self_link: http://localhost:9001/3.0/members/1
user: http://localhost:9001/3.0/users/1
@@ -219,7 +208,6 @@ User ids are different than member ids.
http_etag: ...
list_id: bee.example.com
member_id: 2
- moderation_action: defer
role: member
self_link: http://localhost:9001/3.0/members/2
user: http://localhost:9001/3.0/users/2
@@ -238,7 +226,6 @@ We can also get just the members of a single mailing list.
http_etag: ...
list_id: ant.example.com
member_id: 4
- moderation_action: defer
role: member
self_link: http://localhost:9001/3.0/members/4
user: http://localhost:9001/3.0/users/3
@@ -249,7 +236,6 @@ We can also get just the members of a single mailing list.
http_etag: ...
list_id: ant.example.com
member_id: 5
- moderation_action: defer
role: member
self_link: http://localhost:9001/3.0/members/5
user: http://localhost:9001/3.0/users/2
@@ -276,7 +262,6 @@ page.
http_etag: ...
list_id: ant.example.com
member_id: 4
- moderation_action: defer
role: member
self_link: http://localhost:9001/3.0/members/4
user: http://localhost:9001/3.0/users/3
@@ -295,7 +280,6 @@ This works with members of a single list as well as with all members.
http_etag: ...
list_id: ant.example.com
member_id: 4
- moderation_action: defer
role: member
self_link: http://localhost:9001/3.0/members/4
user: http://localhost:9001/3.0/users/3
@@ -353,7 +337,6 @@ mailing list.
http_etag: ...
list_id: ant.example.com
member_id: 4
- moderation_action: defer
role: member
self_link: http://localhost:9001/3.0/members/4
user: http://localhost:9001/3.0/users/3
@@ -364,7 +347,6 @@ mailing list.
http_etag: ...
list_id: ant.example.com
member_id: 5
- moderation_action: defer
role: member
self_link: http://localhost:9001/3.0/members/5
user: http://localhost:9001/3.0/users/2
@@ -386,7 +368,6 @@ mailing list.
http_etag: ...
list_id: bee.example.com
member_id: 3
- moderation_action: defer
role: member
self_link: http://localhost:9001/3.0/members/3
user: http://localhost:9001/3.0/users/3
@@ -397,7 +378,6 @@ mailing list.
http_etag: ...
list_id: bee.example.com
member_id: 1
- moderation_action: defer
role: member
self_link: http://localhost:9001/3.0/members/1
user: http://localhost:9001/3.0/users/1
@@ -408,7 +388,6 @@ mailing list.
http_etag: ...
list_id: bee.example.com
member_id: 2
- moderation_action: defer
role: member
self_link: http://localhost:9001/3.0/members/2
user: http://localhost:9001/3.0/users/2
@@ -467,7 +446,6 @@ example, we can search for all the memberships of a particular address.
http_etag: ...
list_id: ant.example.com
member_id: 4
- moderation_action: defer
role: member
self_link: http://localhost:9001/3.0/members/4
user: http://localhost:9001/3.0/users/3
@@ -478,7 +456,6 @@ example, we can search for all the memberships of a particular address.
http_etag: ...
list_id: bee.example.com
member_id: 3
- moderation_action: defer
role: member
self_link: http://localhost:9001/3.0/members/3
user: http://localhost:9001/3.0/users/3
@@ -498,7 +475,6 @@ Or, we can find all the memberships for a particular mailing list.
http_etag: ...
list_id: bee.example.com
member_id: 3
- moderation_action: defer
role: member
self_link: http://localhost:9001/3.0/members/3
user: http://localhost:9001/3.0/users/3
@@ -509,7 +485,6 @@ Or, we can find all the memberships for a particular mailing list.
http_etag: ...
list_id: bee.example.com
member_id: 1
- moderation_action: defer
role: member
self_link: http://localhost:9001/3.0/members/1
user: http://localhost:9001/3.0/users/1
@@ -520,7 +495,6 @@ Or, we can find all the memberships for a particular mailing list.
http_etag: ...
list_id: bee.example.com
member_id: 2
- moderation_action: defer
role: member
self_link: http://localhost:9001/3.0/members/2
user: http://localhost:9001/3.0/users/2
@@ -553,7 +527,6 @@ list.
http_etag: ...
list_id: bee.example.com
member_id: 2
- moderation_action: defer
role: member
self_link: http://localhost:9001/3.0/members/2
user: http://localhost:9001/3.0/users/2
@@ -585,7 +558,6 @@ Or, we can find all the memberships for an address with a specific role.
http_etag: ...
list_id: ant.example.com
member_id: 5
- moderation_action: defer
role: member
self_link: http://localhost:9001/3.0/members/5
user: http://localhost:9001/3.0/users/2
@@ -596,7 +568,6 @@ Or, we can find all the memberships for an address with a specific role.
http_etag: ...
list_id: bee.example.com
member_id: 2
- moderation_action: defer
role: member
self_link: http://localhost:9001/3.0/members/2
user: http://localhost:9001/3.0/users/2
@@ -618,7 +589,6 @@ Finally, we can search for a specific member given all three criteria.
http_etag: ...
list_id: bee.example.com
member_id: 2
- moderation_action: defer
role: member
self_link: http://localhost:9001/3.0/members/2
user: http://localhost:9001/3.0/users/2
@@ -640,7 +610,6 @@ Search can also be performed using HTTP GET queries.
http_etag: ...
list_id: bee.example.com
member_id: 2
- moderation_action: defer
role: member
self_link: http://localhost:9001/3.0/members/2
user: http://localhost:9001/3.0/users/2
@@ -699,7 +668,6 @@ Elly is now a known user, and a member of the mailing list.
http_etag: ...
list_id: ant.example.com
member_id: 8
- moderation_action: defer
role: member
self_link: http://localhost:9001/3.0/members/8
user: http://localhost:9001/3.0/users/5
@@ -746,7 +714,6 @@ list with her preferred address.
http_etag: "..."
list_id: ant.example.com
member_id: 9
- moderation_action: defer
role: member
self_link: http://localhost:9001/3.0/members/9
user: http://localhost:9001/3.0/users/6
@@ -772,7 +739,6 @@ the new address.
http_etag: "..."
list_id: ant.example.com
member_id: 9
- moderation_action: defer
role: member
self_link: http://localhost:9001/3.0/members/9
user: http://localhost:9001/3.0/users/6
@@ -840,7 +806,6 @@ addresses.
http_etag: "..."
list_id: ant.example.com
member_id: 10
- moderation_action: defer
role: member
self_link: http://localhost:9001/3.0/members/10
user: http://localhost:9001/3.0/users/7
@@ -852,7 +817,6 @@ addresses.
http_etag: "..."
list_id: bee.example.com
member_id: 11
- moderation_action: defer
role: member
self_link: http://localhost:9001/3.0/members/11
user: http://localhost:9001/3.0/users/7
@@ -911,7 +875,6 @@ his membership ids have not changed.
http_etag: "..."
list_id: ant.example.com
member_id: 10
- moderation_action: defer
role: member
self_link: http://localhost:9001/3.0/members/10
user: http://localhost:9001/3.0/users/7
@@ -922,7 +885,6 @@ his membership ids have not changed.
http_etag: "..."
list_id: bee.example.com
member_id: 11
- moderation_action: defer
role: member
self_link: http://localhost:9001/3.0/members/11
user: http://localhost:9001/3.0/users/7
@@ -952,7 +914,6 @@ mode of delivery.
http_etag: "..."
list_id: bee.example.com
member_id: 11
- moderation_action: defer
role: member
self_link: http://localhost:9001/3.0/members/11
user: http://localhost:9001/3.0/users/7
@@ -970,9 +931,14 @@ The moderation action for a member can be changed by PATCH'ing the
>>> dump_json('http://localhost:9001/3.0/members/10')
address: http://localhost:9001/3.0/addresses/hperson@example.com
- ...
- moderation_action: defer
- ...
+ delivery_mode: regular
+ email: hperson@example.com
+ http_etag: "6d544208d60e578189fc023748f1ec467290abb5"
+ list_id: ant.example.com
+ member_id: 10
+ role: member
+ self_link: http://localhost:9001/3.0/members/10
+ user: http://localhost:9001/3.0/users/7
>>> dump_json('http://localhost:9001/3.0/members/10', {
... 'moderation_action': 'hold',
diff --git a/src/mailman/rest/members.py b/src/mailman/rest/members.py
index b56fa3c8d..c842ccd7d 100644
--- a/src/mailman/rest/members.py
+++ b/src/mailman/rest/members.py
@@ -61,10 +61,12 @@ class _MemberBase(CollectionMixin):
email=member.address.email,
list_id=member.list_id,
member_id=member_id,
- moderation_action=member.moderation_action,
role=role,
self_link=self.api.path_to('members/{}'.format(member_id)),
)
+ # Add the moderation action if there is one.
+ if member.moderation_action is not None:
+ response['moderation_action'] = member.moderation_action
# Add the user link if there is one.
user = member.user
if user is not None:
diff --git a/src/mailman/rules/docs/moderation.rst b/src/mailman/rules/docs/moderation.rst
index f5ceec29a..56602189b 100644
--- a/src/mailman/rules/docs/moderation.rst
+++ b/src/mailman/rules/docs/moderation.rst
@@ -2,9 +2,10 @@
Moderation
==========
-All members and nonmembers have a moderation action. When the action is not
-`defer`, the `moderation` rule flags the message as needing moderation. This
-might be to automatically accept, discard, reject, or hold the message.
+All members and nonmembers have a moderation action, which defaults to the
+list's default action. When the action is not `defer`, the `moderation` rule
+flags the message as needing moderation. This might be to automatically
+accept, discard, reject, or hold the message.
Two separate rules check for member and nonmember moderation. Member
moderation happens early in the built-in chain, while nonmember moderation
@@ -30,7 +31,7 @@ postings are not moderated.
as MemberRole.member>
>>> member = mlist.members.get_member('aperson@example.com')
- >>> print(member.moderation_action)
+ >>> print(mlist.default_member_action)
Action.defer
Because Anne is not moderated, the member moderation rule does not match.
@@ -44,9 +45,9 @@ Because Anne is not moderated, the member moderation rule does not match.
>>> member_rule.check(mlist, member_msg, {})
False
-Once the member's moderation action is set to something other than `defer`,
-the rule matches. Also, the message metadata has a few extra pieces of
-information for the eventual moderation chain.
+Once the member's moderation action is set to something other than `defer` or
+``None``, the rule matches. Also, the message metadata has a few extra pieces
+of information for the eventual moderation chain.
>>> from mailman.interfaces.action import Action
>>> member.moderation_action = Action.hold
@@ -78,7 +79,7 @@ Bart, who is not a member of the mailing list, sends a message to the list.
as MemberRole.nonmember>
>>> nonmember = mlist.nonmembers.get_member('bperson@example.com')
- >>> print(nonmember.moderation_action)
+ >>> print(mlist.default_nonmember_action)
Action.hold
When Bart is registered as a nonmember of the list, his moderation action is
diff --git a/src/mailman/rules/moderation.py b/src/mailman/rules/moderation.py
index fdecd1d5f..9c89cf0b2 100644
--- a/src/mailman/rules/moderation.py
+++ b/src/mailman/rules/moderation.py
@@ -42,8 +42,10 @@ class MemberModeration:
"""See `IRule`."""
for sender in msg.senders:
member = mlist.members.get_member(sender)
- action = (None if member is None
- else member.moderation_action)
+ if member is None:
+ return False
+ action = (member.moderation_action
+ or mlist.default_member_action)
if action is Action.defer:
# The regular moderation rules apply.
return False
@@ -112,7 +114,8 @@ class NonmemberModeration:
_record_action(msgdata, action, sender,
reason.format(action))
return True
- action = nonmember.moderation_action
+ action = (nonmember.moderation_action
+ or mlist.default_nonmember_action)
if action is Action.defer:
# The regular moderation rules apply.
return False
diff --git a/src/mailman/rules/tests/test_moderation.py b/src/mailman/rules/tests/test_moderation.py
index df1658792..3e80aeeb5 100644
--- a/src/mailman/rules/tests/test_moderation.py
+++ b/src/mailman/rules/tests/test_moderation.py
@@ -144,3 +144,60 @@ A message body.
self.assertEqual(
msgdata['moderation_action'], action_name,
'Wrong action for {}: {}'.format(address, action_name))
+
+ def test_nonmember_fallback_to_list_defaults(self):
+ # https://gitlab.com/mailman/mailman/issues/189
+ self._mlist.default_nonmember_action = Action.hold
+ user_manager = getUtility(IUserManager)
+ user_manager.create_address('anne@example.com')
+ rule = moderation.NonmemberModeration()
+ msg = mfs("""\
+From: anne@example.com
+To: test@example.com
+Subject: A test message
+Message-ID: <ant>
+MIME-Version: 1.0
+
+A message body.
+""")
+ # First, the message should get held
+ msgdata = {}
+ result = rule.check(self._mlist, msg, msgdata)
+ self.assertTrue(result)
+ self.assertEqual(msgdata.get('moderation_action'), 'hold')
+ # Then the list's default nonmember action is changed
+ self._mlist.default_nonmember_action = Action.discard
+ msg.replace_header('Message-ID', '<ant2>')
+ # This time, the message should be discarded
+ result = rule.check(self._mlist, msg, msgdata)
+ self.assertTrue(result)
+ self.assertEqual(msgdata.get('moderation_action'), 'discard')
+
+ def test_member_fallback_to_list_defaults(self):
+ # https://gitlab.com/mailman/mailman/issues/189
+ self._mlist.default_member_action = Action.accept
+ user_manager = getUtility(IUserManager)
+ anne = user_manager.create_address('anne@example.com')
+ self._mlist.subscribe(anne, MemberRole.member)
+ rule = moderation.MemberModeration()
+ msg = mfs("""\
+From: anne@example.com
+To: test@example.com
+Subject: A test message
+Message-ID: <ant>
+MIME-Version: 1.0
+
+A message body.
+""")
+ # First, the message should get held
+ msgdata = {}
+ result = rule.check(self._mlist, msg, msgdata)
+ self.assertTrue(result)
+ self.assertEqual(msgdata.get('moderation_action'), 'accept')
+ # Then the list's default nonmember action is changed
+ self._mlist.default_member_action = Action.hold
+ msg.replace_header('Message-ID', '<ant2>')
+ # This time, the message should be discarded
+ result = rule.check(self._mlist, msg, msgdata)
+ self.assertTrue(result)
+ self.assertEqual(msgdata.get('moderation_action'), 'hold')
diff --git a/src/mailman/utilities/importer.py b/src/mailman/utilities/importer.py
index 9a5684d9c..da19613d8 100644
--- a/src/mailman/utilities/importer.py
+++ b/src/mailman/utilities/importer.py
@@ -576,8 +576,6 @@ def import_roster(mlist, config_dict, members, role, action=None):
# option to know which action should be taken.
action = member_moderation_action_mapping(
config_dict.get("member_moderation_action"))
- else:
- action = Action.accept
if action is not None:
# Either this was set right above or in the function's arguments
# for nonmembers.
diff --git a/src/mailman/utilities/tests/test_import.py b/src/mailman/utilities/tests/test_import.py
index 637f78585..83161bf1f 100644
--- a/src/mailman/utilities/tests/test_import.py
+++ b/src/mailman/utilities/tests/test_import.py
@@ -1112,9 +1112,10 @@ class TestPreferencesImport(unittest.TestCase):
self._do_test(128, dict(moderation_action=Action.discard))
def test_no_moderate(self):
- # If option flag Moderate is not set, action is accept
+ # If option flag Moderate is not set, action is None (fallback to the
+ # mailing list's action).
self._pckdict['member_moderation_action'] = 1 # reject
- self._do_test(0, dict(moderation_action=Action.accept))
+ self._do_test(0, dict(moderation_action=None))
def test_multiple_options(self):
# DontReceiveDuplicates & DisableMime & SuppressPasswordReminder