diff options
Diffstat (limited to 'src/mailman/app')
| -rw-r--r-- | src/mailman/app/docs/bans.rst | 167 | ||||
| -rw-r--r-- | src/mailman/app/membership.py | 7 | ||||
| -rw-r--r-- | src/mailman/app/tests/test_membership.py | 57 |
3 files changed, 226 insertions, 5 deletions
diff --git a/src/mailman/app/docs/bans.rst b/src/mailman/app/docs/bans.rst new file mode 100644 index 000000000..bb6d5902e --- /dev/null +++ b/src/mailman/app/docs/bans.rst @@ -0,0 +1,167 @@ +======================= +Banning email addresses +======================= + +Email addresses can be banned from ever subscribing, either to a specific +mailing list or globally within the Mailman system. Both explicit email +addresses and email address patterns can be banned. + +Bans are managed through the `Ban Manager`. + + >>> from zope.component import getUtility + >>> from mailman.interfaces.bans import IBanManager + >>> ban_manager = getUtility(IBanManager) + +At first, no email addresses are banned, either globally... + + >>> ban_manager.is_banned('anne@example.com') + False + +...or for a specific mailing list. + + >>> ban_manager.is_banned('bart@example.com', 'test@example.com') + False + + +Specific bans +============= + +An email address can be banned from a specific mailing list by adding a ban to +the ban manager. + + >>> ban_manager.ban('cris@example.com', 'test@example.com') + >>> ban_manager.is_banned('cris@example.com', 'test@example.com') + True + >>> ban_manager.is_banned('bart@example.com', 'test@example.com') + False + +However, this is not a global ban. + + >>> ban_manager.is_banned('cris@example.com') + False + + +Global bans +=========== + +An email address can be banned globally, so that it cannot be subscribed to +any mailing list. + + >>> ban_manager.ban('dave@example.com') + +Dave is banned from the test mailing list... + + >>> ban_manager.is_banned('dave@example.com', 'test@example.com') + True + +...and the sample mailing list. + + >>> ban_manager.is_banned('dave@example.com', 'sample@example.com') + True + +Dave is also banned globally. + + >>> ban_manager.is_banned('dave@example.com') + True + +Cris however is not banned globally. + + >>> ban_manager.is_banned('cris@example.com') + False + +Even though Cris is not banned globally, we can add a global ban for her. + + >>> ban_manager.ban('cris@example.com') + >>> ban_manager.is_banned('cris@example.com') + True + +Cris is obviously still banned from specific mailing lists. + + >>> ban_manager.is_banned('cris@example.com', 'test@example.com') + True + >>> ban_manager.is_banned('cris@example.com', 'sample@example.com') + True + +We can remove the global ban to once again just ban her address from the test +list. + + >>> ban_manager.unban('cris@example.com') + >>> ban_manager.is_banned('cris@example.com', 'test@example.com') + True + >>> ban_manager.is_banned('cris@example.com', 'sample@example.com') + False + + +Regular expression bans +======================= + +Entire email address patterns can be banned, both for a specific mailing list +and globally, just as specific addresses can be banned. Use this for example, +when an entire domain is a spam faucet. When using a pattern, the email +address must start with a caret (^). + + >>> ban_manager.ban('^.*@example.org', 'test@example.com') + +Now, no one from example.org can subscribe to the test list. + + >>> ban_manager.is_banned('elle@example.org', 'test@example.com') + True + >>> ban_manager.is_banned('eperson@example.org', 'test@example.com') + True + >>> ban_manager.is_banned('elle@example.com', 'test@example.com') + False + +They are not, however banned globally. + + >>> ban_manager.is_banned('elle@example.org', 'sample@example.com') + False + >>> ban_manager.is_banned('elle@example.org') + False + +Of course, we can ban everyone from example.org globally too. + + >>> ban_manager.ban('^.*@example.org') + >>> ban_manager.is_banned('elle@example.org', 'sample@example.com') + True + >>> ban_manager.is_banned('elle@example.org') + True + +We can remove the mailing list ban on the pattern, though the global ban will +still be in place. + + >>> ban_manager.unban('^.*@example.org', 'test@example.com') + >>> ban_manager.is_banned('elle@example.org', 'test@example.com') + True + >>> ban_manager.is_banned('elle@example.org', 'sample@example.com') + True + >>> ban_manager.is_banned('elle@example.org') + True + +But once the global ban is removed, everyone from example.org can subscribe to +the mailing lists. + + >>> ban_manager.unban('^.*@example.org') + >>> ban_manager.is_banned('elle@example.org', 'test@example.com') + False + >>> ban_manager.is_banned('elle@example.org', 'sample@example.com') + False + >>> ban_manager.is_banned('elle@example.org') + False + + +Adding and removing bans +======================== + +It is not an error to add a ban more than once. These are just ignored. + + >>> ban_manager.ban('fred@example.com', 'test@example.com') + >>> ban_manager.ban('fred@example.com', 'test@example.com') + >>> ban_manager.is_banned('fred@example.com', 'test@example.com') + True + +Nor is it an error to remove a ban more than once. + + >>> ban_manager.unban('fred@example.com', 'test@example.com') + >>> ban_manager.unban('fred@example.com', 'test@example.com') + >>> ban_manager.is_banned('fred@example.com', 'test@example.com') + False diff --git a/src/mailman/app/membership.py b/src/mailman/app/membership.py index 32ba1ff42..8723fd781 100644 --- a/src/mailman/app/membership.py +++ b/src/mailman/app/membership.py @@ -34,6 +34,7 @@ from mailman.app.notifications import send_goodbye_message from mailman.core.i18n import _ from mailman.email.message import OwnerNotification from mailman.interfaces.address import IEmailValidator +from mailman.interfaces.bans import IBanManager from mailman.interfaces.member import ( AlreadySubscribedError, MemberRole, MembershipIsBannedError, NotAMemberError) @@ -71,10 +72,8 @@ def add_member(mlist, email, realname, password, delivery_mode, language): if mlist.members.get_member(email) is not None: raise AlreadySubscribedError( mlist.fqdn_listname, email, MemberRole.member) - # Check for banned email addresses here too for administrative mass - # subscribes and confirmations. - pattern = Utils.get_pattern(email, mlist.ban_list) - if pattern: + # Check to see if the email address is banned. + if getUtility(IBanManager).is_banned(email, mlist.fqdn_listname): raise MembershipIsBannedError(mlist, email) # See if there's already a user linked with the given address. user_manager = getUtility(IUserManager) diff --git a/src/mailman/app/tests/test_membership.py b/src/mailman/app/tests/test_membership.py index dc8009f65..b0e1bae5d 100644 --- a/src/mailman/app/tests/test_membership.py +++ b/src/mailman/app/tests/test_membership.py @@ -32,7 +32,8 @@ from zope.component import getUtility from mailman.app.lifecycle import create_list from mailman.app.membership import add_member from mailman.core.constants import system_preferences -from mailman.interfaces.member import DeliveryMode +from mailman.interfaces.bans import IBanManager +from mailman.interfaces.member import DeliveryMode, MembershipIsBannedError from mailman.interfaces.usermanager import IUserManager from mailman.testing.helpers import reset_the_world from mailman.testing.layers import ConfigLayer @@ -68,6 +69,60 @@ class AddMemberTest(unittest.TestCase): self.assertEqual(member.address.email, 'aperson@example.com') self.assertEqual(member.mailing_list, 'test@example.com') + def test_add_member_banned(self): + # Test that members who are banned by specific address cannot + # subscribe to the mailing list. + getUtility(IBanManager).ban('anne@example.com', 'test@example.com') + self.assertRaises( + MembershipIsBannedError, + add_member, self._mlist, 'anne@example.com', 'Anne Person', + '123', DeliveryMode.regular, system_preferences.preferred_language) + + def test_add_member_globally_banned(self): + # Test that members who are banned by specific address cannot + # subscribe to the mailing list. + getUtility(IBanManager).ban('anne@example.com') + self.assertRaises( + MembershipIsBannedError, + add_member, self._mlist, 'anne@example.com', 'Anne Person', + '123', DeliveryMode.regular, system_preferences.preferred_language) + + def test_add_member_banned_from_different_list(self): + # Test that members who are banned by specific address cannot + # subscribe to the mailing list. + getUtility(IBanManager).ban('anne@example.com', 'sample@example.com') + member = add_member(self._mlist, 'anne@example.com', + 'Anne Person', '123', DeliveryMode.regular, + system_preferences.preferred_language) + self.assertEqual(member.address.email, 'anne@example.com') + + def test_add_member_banned_by_pattern(self): + # Test that members who are banned by specific address cannot + # subscribe to the mailing list. + getUtility(IBanManager).ban('^.*@example.com', 'test@example.com') + self.assertRaises( + MembershipIsBannedError, + add_member, self._mlist, 'anne@example.com', 'Anne Person', + '123', DeliveryMode.regular, system_preferences.preferred_language) + + def test_add_member_globally_banned_by_pattern(self): + # Test that members who are banned by specific address cannot + # subscribe to the mailing list. + getUtility(IBanManager).ban('^.*@example.com') + self.assertRaises( + MembershipIsBannedError, + add_member, self._mlist, 'anne@example.com', 'Anne Person', + '123', DeliveryMode.regular, system_preferences.preferred_language) + + def test_add_member_banned_from_different_list_by_pattern(self): + # Test that members who are banned by specific address cannot + # subscribe to the mailing list. + getUtility(IBanManager).ban('^.*@example.com', 'sample@example.com') + member = add_member(self._mlist, 'anne@example.com', + 'Anne Person', '123', DeliveryMode.regular, + system_preferences.preferred_language) + self.assertEqual(member.address.email, 'anne@example.com') + def test_suite(): |
