diff options
| author | Harshit Bansal | 2016-04-12 02:58:25 +0530 |
|---|---|---|
| committer | Barry Warsaw | 2016-04-18 17:13:01 -0400 |
| commit | 7559ce6dfdf2d569c91fea173968e46d6857d730 (patch) | |
| tree | 6443ba6deedf2dc315e964e8c9f35bddbd3b2f4b /src | |
| parent | d95f5d501623896ab239a94bda0954424a9d3127 (diff) | |
| download | mailman-7559ce6dfdf2d569c91fea173968e46d6857d730.tar.gz mailman-7559ce6dfdf2d569c91fea173968e46d6857d730.tar.zst mailman-7559ce6dfdf2d569c91fea173968e46d6857d730.zip | |
Diffstat (limited to 'src')
| -rw-r--r-- | src/mailman/interfaces/subscriptions.py | 15 | ||||
| -rw-r--r-- | src/mailman/model/docs/subscriptions.rst | 55 | ||||
| -rw-r--r-- | src/mailman/model/subscriptions.py | 27 | ||||
| -rw-r--r-- | src/mailman/model/tests/test_subscriptions.py | 121 |
4 files changed, 218 insertions, 0 deletions
diff --git a/src/mailman/interfaces/subscriptions.py b/src/mailman/interfaces/subscriptions.py index 157bf1b62..f712d33f7 100644 --- a/src/mailman/interfaces/subscriptions.py +++ b/src/mailman/interfaces/subscriptions.py @@ -162,3 +162,18 @@ class ISubscriptionService(Interface): :raises NotAMemberError: if the given address is not a member of the mailing list. """ + + def unsubscribe_members(list_id, emails): + """Unsubscribe a batch of members from a mailing list. + + :param list_id: The list id to operate on. + :type list_id: string + :param emails: A list of email addresses of the users getting + unsubscribed. + :type emails: list of strings + :return: A two item tuple whose first item is a list of all the + successfully unsubscribed email addresses and second item is + a list of all unsuccessfull email addresses. + :rtype: Tuple + :raises NoSuchListError: if the named mailing list does not exist. + """ diff --git a/src/mailman/model/docs/subscriptions.rst b/src/mailman/model/docs/subscriptions.rst index 6237a24b3..deaea36a1 100644 --- a/src/mailman/model/docs/subscriptions.rst +++ b/src/mailman/model/docs/subscriptions.rst @@ -209,3 +209,58 @@ Members can be removed via this service. on bee@example.com as MemberRole.owner> <Member: Anne Person <anne@example.com> on cat@example.com as MemberRole.member> + + +Mass Removal +============ + +The subscription service can be used to perform mass removals. You are +required to pass the list id of the respective mailing list and a list +of email addresses to be removed. + + >>> bart_2 = subscribe(ant, 'Bart') + >>> cris_2 = subscribe(ant, 'Cris') + >>> for member in service: + ... print(member) + <Member: Anne Person <aperson@example.com> + on ant@example.com as MemberRole.owner> + <Member: Bart Person <bperson@example.com> + on ant@example.com as MemberRole.moderator> + <Member: Anne Person <aperson@example.com> + on ant@example.com as MemberRole.member> + <Member: Bart Person <bperson@example.com> + on ant@example.com as MemberRole.member> + <Member: Cris Person <cperson@example.com> + on ant@example.com as MemberRole.member> + <Member: Bart Person <bperson@example.com> + on bee@example.com as MemberRole.owner> + <Member: Anne Person <anne@example.com> + on cat@example.com as MemberRole.member> + >>> len(service.get_members()) + 7 + >>> print(service.find_member('bogus@example.com')) + None + >>> success, fail = service.unsubscribe_members( + ... 'ant.example.com', ['aperson@example.com', + ... 'cperson@example.com', + ... 'bogus@example.com', + ... ]) + >>> dump_list(success) + aperson@example.com + cperson@example.com + >>> dump_list(fail) + bogus@example.com + >>> for member in service: + ... print(member) + <Member: Anne Person <aperson@example.com> + on ant@example.com as MemberRole.owner> + <Member: Bart Person <bperson@example.com> + on ant@example.com as MemberRole.moderator> + <Member: Bart Person <bperson@example.com> + on ant@example.com as MemberRole.member> + <Member: Bart Person <bperson@example.com> + on bee@example.com as MemberRole.owner> + <Member: Anne Person <anne@example.com> + on cat@example.com as MemberRole.member> + >>> len(service.get_members()) + 5 diff --git a/src/mailman/model/subscriptions.py b/src/mailman/model/subscriptions.py index 3d2bcbeb0..301bfd7d9 100644 --- a/src/mailman/model/subscriptions.py +++ b/src/mailman/model/subscriptions.py @@ -21,6 +21,7 @@ from mailman import public from mailman.app.membership import delete_member from mailman.database.transaction import dbconnection from mailman.interfaces.listmanager import IListManager, NoSuchListError +from mailman.interfaces.member import MemberRole from mailman.interfaces.subscriptions import ( ISubscriptionService, TooManyMembersError) from mailman.interfaces.usermanager import IUserManager @@ -146,3 +147,29 @@ class SubscriptionService: raise NoSuchListError(list_id) # XXX for now, no notification or user acknowledgment. delete_member(mlist, email, False, False) + + @dbconnection + def unsubscribe_members(self, store, list_id, emails): + """See 'ISubscriptionService'.""" + successful = [] + unsuccessful = [] + mlist = getUtility(IListManager).get_by_list_id(list_id) + if mlist is None: + raise NoSuchListError(list_id) + q_mem = store.query(Member).filter( + Member.list_id == list_id, Member.role == MemberRole.member) + for email in emails: + unsubscribed = False + q_addr = q_mem.join(Member._address).filter( + Address.email == email) + q_user = q_mem.join(Member._user).join( + User._preferred_address).filter(Address.email == email) + members = q_addr.union(q_user).all() + for member in members: + member.unsubscribe() + unsubscribed = True + if unsubscribed: + successful.append(email) + else: + unsuccessful.append(email) + return successful, unsuccessful diff --git a/src/mailman/model/tests/test_subscriptions.py b/src/mailman/model/tests/test_subscriptions.py index 6b884b22f..49db3cf62 100644 --- a/src/mailman/model/tests/test_subscriptions.py +++ b/src/mailman/model/tests/test_subscriptions.py @@ -239,3 +239,124 @@ class TestSubscriptionService(unittest.TestCase): # Trying to leave a nonexistent list raises an exception. self.assertRaises(NoSuchListError, self._service.leave, 'bogus.example.com', 'anne@example.com') + + def test_unsubscribe_members_no_such_list(self): + # Raises an exception if an invalid list_id is passed + self.assertRaises(NoSuchListError, self._service.unsubscribe_members, + 'bogus.example.com', 'anne@example.com') + + def test_unsubscribe_members(self): + # Check that memberships are properly unsubscribed + # Create lists for testing. + mlist1 = create_list('test1@example.com') + mlist1.admin_immed_notify = False + mlist2 = create_list('test2@example.com') + mlist2.admin_immed_notify = False + # Create users and addresses + user = self._user_manager.create_user( + 'anne1@example.com', 'Anne User') + address_1 = set_preferred(user) + address_2 = self._user_manager.create_address( + 'anne2@example.com', 'Anne User 2') + address_2.verified_on = now() + address_2.user = user + address_3 = self._user_manager.create_address( + 'anne3@example.com', 'Anne User 3') + address_3.verified_on = now() + address_3.user = user + address_4 = self._user_manager.create_address( + 'addr1@example.com', 'Address 1') + address_4.verified_on = now() + address_5 = self._user_manager.create_address( + 'addr2@example.com', 'Address 2') + address_5.verified_on = now() + address_6 = self._user_manager.create_address( + 'addr3@example.com', 'Address 3') + address_6.verified_on = now() + user_1 = self._user_manager.create_user( + 'user1@example.com', 'User 1') + set_preferred(user_1) + address_8 = self._user_manager.create_address( + 'user2@example.com', 'User 2') + address_8.verified_on = now() + address_8.user = user_1 + # Subscribe the addresses to mailing lists + mlist1.subscribe(user, MemberRole.member) + mlist1.subscribe(user, MemberRole.moderator) + mlist1.subscribe(user, MemberRole.owner) + mlist1.subscribe(address_1, MemberRole.member) + mlist1.subscribe(address_2, MemberRole.member) + mlist1.subscribe(address_2, MemberRole.moderator) + mlist1.subscribe(address_3, MemberRole.member) + mlist1.subscribe(address_4, MemberRole.member) + mlist1.subscribe(address_5, MemberRole.member) + mlist1.subscribe(address_5, MemberRole.moderator) + mlist1.subscribe(address_6, MemberRole.member) + mlist1.subscribe(user_1, MemberRole.member) + mlist1.subscribe(address_8, MemberRole.member) + mlist2.subscribe(user, MemberRole.member) + mlist2.subscribe(user, MemberRole.moderator) + mlist2.subscribe(address_1, MemberRole.member) + mlist2.subscribe(address_1, MemberRole.moderator) + mlist2.subscribe(address_2, MemberRole.member) + mlist2.subscribe(address_2, MemberRole.owner) + mlist2.subscribe(address_4, MemberRole.member) + mlist2.subscribe(address_5, MemberRole.member) + mlist2.subscribe(address_6, MemberRole.member) + mlist2.subscribe(address_6, MemberRole.moderator) + # Unsubscribe members from mlist1 + success, fail = self._service.unsubscribe_members(mlist1.list_id, + ['anne1@example.com', + 'anne2@example.com', + 'addr1@example.com', + 'addr2@example.com', + 'user2@example.com', + 'bogus@example.com', + ]) + self.assertListEqual(success, ['anne1@example.com', + 'anne2@example.com', + 'addr1@example.com', + 'addr2@example.com', + 'user2@example.com', + ]) + self.assertListEqual(fail, ['bogus@example.com']) + # Obtain rosters + members_1 = mlist1.get_roster(MemberRole.member) + moderators_1 = mlist1.get_roster(MemberRole.moderator) + owners_1 = mlist1.get_roster(MemberRole.owner) + members_2 = mlist2.get_roster(MemberRole.member) + moderators_2 = mlist2.get_roster(MemberRole.moderator) + owners_2 = mlist2.get_roster(MemberRole.owner) + self.assertListEqual( + [address.email for address in members_1.addresses], + ['anne3@example.com', + 'addr3@example.com', + 'user1@example.com', + ]) + self.assertListEqual( + [address.email for address in moderators_1.addresses], + ['anne1@example.com', + 'anne2@example.com', + 'addr2@example.com', + ]) + self.assertListEqual( + [address.email for address in owners_1.addresses], + ['anne1@example.com']) + self.assertListEqual( + [address.email for address in members_2.addresses], + ['anne1@example.com', + 'anne1@example.com', + 'anne2@example.com', + 'addr1@example.com', + 'addr2@example.com', + 'addr3@example.com', + ]) + self.assertListEqual( + [address.email for address in moderators_2.addresses], + ['anne1@example.com', + 'anne1@example.com', + 'addr3@example.com', + ]) + self.assertListEqual( + [address.email for address in owners_2.addresses], + ['anne2@example.com']) |
