def leave(self, list_id, email): """See `ISubscriptionService`.""" mlist = getUtility(IListManager).get_by_list_id(list_id) if mlist is None: raise NoSuchListError(list_id) # XXX for now, no notification or user acknowledgment. delete_member(mlist, email, False, False)
def handle_unsubscription(mlist, id, action, comment=None): requestdb = IListRequests(mlist) key, data = requestdb.get_request(id) address = data['address'] if action is Action.defer: # Nothing to do. return elif action is Action.discard: # Nothing to do except delete the request from the database. pass elif action is Action.reject: key, data = requestdb.get_request(id) _refuse(mlist, _('Unsubscription request'), address, comment or _('[No reason given]')) elif action is Action.accept: key, data = requestdb.get_request(id) try: delete_member(mlist, address) except NotAMemberError: # User has already been unsubscribed. pass slog.info('%s: deleted %s', mlist.fqdn_listname, address) else: raise AssertionError('Unexpected action: {0}'.format(action)) # Delete the request from the database. requestdb.delete_request(id)
def handle_unsubscription(mlist, id, action, comment=None): requestdb = IListRequests(mlist) key, data = requestdb.get_request(id) email = data['email'] if action is Action.defer: # Nothing to do. return elif action is Action.discard: # Nothing to do except delete the request from the database. pass elif action is Action.reject: key, data = requestdb.get_request(id) send_rejection( mlist, _('Unsubscription request'), email, comment or _('[No reason given]')) elif action is Action.accept: key, data = requestdb.get_request(id) try: delete_member(mlist, email) except NotAMemberError: # User has already been unsubscribed. pass slog.info('%s: deleted %s', mlist.fqdn_listname, email) else: raise AssertionError('Unexpected action: {0}'.format(action)) # Delete the request from the database. requestdb.delete_request(id)
def test_delete_member_not_a_member(self): # Try to delete an address which is not a member of the mailing list. with self.assertRaises(NotAMemberError) as cm: delete_member(self._mlist, '*****@*****.**') self.assertEqual( str(cm.exception), '[email protected] is not a member of [email protected]')
def leave(self, fqdn_listname, email): """See `ISubscriptionService`.""" mlist = getUtility(IListManager).get(fqdn_listname) if mlist is None: raise NoSuchListError(fqdn_listname) # XXX for now, no notification or user acknowledgment. delete_member(mlist, email, False, False)
def _remove_memberships(self, store): """Remove all the memberships for whom max number of warnings have been sent. """ manager = getUtility(IMembershipManager) for member in manager.memberships_pending_removal(): # We do not want to send duplicate notifications to the # administrators, so we send them a membership change event only if # the list is configured not to notify them about removal due to # bounces. # Although, note that if admin_notif is None, they will receive # notification only if the mailinglist is configured to notify on # membership changes, which is a different setting.. admin_notif = None send_admin_notif = False if member.mailing_list.bounce_notify_owner_on_removal: admin_notif = False send_admin_notif = True delete_member( mlist=member._mailing_list, email=member.address.email, admin_notif=admin_notif, userack=True) if send_admin_notif: send_admin_removal_notice( member.mailing_list, member.address.email, member.display_name) log.info('Removed %s as a member of %s mailing list due to ' 'excessive bounces', member.address.email, member._mailing_list.display_name)
def _step_do_unsubscription(self): try: delete_member(self.mlist, self.address.email) except NotAMemberError: # The member has already been unsubscribed. pass self.member = None assert self.token is None and self.token_owner is TokenOwner.no_one, ( 'Unexpected active token at end of subscription workflow')
def on_delete(self, request, response): """Delete the member (i.e. unsubscribe).""" # Leaving a list is a bit different than deleting a moderator or # owner. Handle the former case first. For now too, we will not send # an admin or user notification. if self._member is None: not_found(response) return mlist = getUtility(IListManager).get_by_list_id(self._member.list_id) if self._member.role is MemberRole.member: delete_member(mlist, self._member.address.email, False, False) else: self._member.unsubscribe() no_content(response)
def delete_members(mlists, memb_list, goodbye_msg, admin_notify): """Delete one or more members from one or more mailing lists.""" mlists = list(mlists) for mlist in mlists: for display_name, email in memb_list: try: delete_member(mlist, email, admin_notif=admin_notify, userack=goodbye_msg) except NotAMemberError: email = formataddr((display_name, email)) if len(mlists) == 1: print(_('Member not subscribed (skipping): $email'), file=sys.stderr)
def delete(self, request): """Delete the member (i.e. unsubscribe).""" # Leaving a list is a bit different than deleting a moderator or # owner. Handle the former case first. For now too, we will not send # an admin or user notification. if self._member is None: return http.not_found() mlist = getUtility(IListManager).get(self._member.mailing_list) if self._member.role is MemberRole.member: try: delete_member(mlist, self._member.address.email, False, False) except NotAMemberError: return http.not_found() else: self._member.unsubscribe() return no_content()
def delete_members(mlist, del_infp): for line in del_infp: # Ignore blank lines and lines that start with a '#'. if line.startswith('#') or len(line.strip()) == 0: continue # Parse the line and ensure that the values are unicodes. display_name, email = parseaddr(line) try: delete_member(mlist, email) except NotAMemberError: # It's okay if the address is not subscribed, just print a # warning and continue. if not display_name: print(_('Member not subscribed (skipping): $email')) else: print( _('Member not subscribed (skipping): ' '$display_name <$email>'))
def sync_members(mlist, in_fp, delivery, welcome_msg, goodbye_msg, admin_notify, no_change): """Add and delete mailing list members to match an input file.""" global email_validator subscribers = mlist.members addresses = list(subscribers.addresses) # Variable that shows if something was done to the original mailing list ml_changed = False # A list (set) of the members currently subscribed. members_of_list = set([address.email.lower() for address in addresses]) # A list (set) of all valid email addresses in a file. file_emails = set() # A list (dict) of (display name + address) for a members address. formatted_addresses = {} for line in in_fp: # Don't include newlines or whitespaces at the start or end line = line.strip() # Ignore blank lines and lines that start with a '#'. if line.startswith('#') or len(line) == 0: continue # Parse the line to a tuple. parsed_addr = parseaddr(line) # parseaddr can return invalid emails. E.g. parseaddr('foobar@') # returns ('', 'foobar@') in python 3.6.7 and 3.7.1 so check validity. if not email_validator.is_valid(parsed_addr[1]): print(_('Cannot parse as valid email address (skipping): $line'), file=sys.stderr) continue new_display_name, new_email = parsed_addr # Address to lowercase lc_email = new_email.lower() # Format output with display name if available formatted_addr = formataddr((new_display_name, new_email)) # Add the 'outputable' version to a dict formatted_addresses[lc_email] = formatted_addr file_emails.add(lc_email) addresses_to_add = file_emails - members_of_list addresses_to_delete = members_of_list - file_emails for email in sorted(addresses_to_add): # Add to mailing list if not dryrun. print(_("[ADD] %s") % formatted_addresses[email]) if not no_change: add_members(mlist, formatted_addresses[email], delivery, welcome_msg) # Indicate that we done something to the mailing list. ml_changed = True continue for email in sorted(addresses_to_delete): # Delete from mailing list if not dryrun. member = str(subscribers.get_member(email).address) print(_("[DEL] %s") % member) if not no_change: delete_member(mlist, email, admin_notif=admin_notify, userack=goodbye_msg) # Indicate that we done something to the mailing list. ml_changed = True continue # We did nothing to the mailing list -> We had nothing to do. if not ml_changed: print(_("Nothing to do"))
def delete(self, email): """Remove email from mailinglist.""" delete_member(self.list, email)