# Copyright (C) 2022 by the Free Software Foundation, Inc. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, # USA. # Sometimes the same address gets subscribed to a list as both an address and # as a user. This causes various issues. This script finds those cases and # unsubscribes the address, leaving the user subscribed. # # This is run with # mailman shell -r delete_dup_sub xxx # after saving it as # /opt/mailman/mm/venv/bin/delete_dup_sub.py # xxx is Yes to actually do the unsubscribe, anything else or nothing # only reports. from mailman.database.transaction import transactional from mailman.interfaces.listmanager import IListManager from mailman.model.address import Address from mailman.model.user import User from zope.component import getUtility listmanager = getUtility(IListManager) @transactional def unsubscribe(doit, member): print(f'Unsubscribing {member}') if doit: member.unsubscribe() def do_dup(doit, mlist, val): if type(val[0].subscriber) is Address: if type(val[1].subscriber) is User: unsubscribe(doit, val[0]) else: print(f'Anomalous types: ' f'{mlist.list_id} {val[0].subscriber} {val[1].subscriber}') elif type(val[0].subscriber) is User: if type(val[1].subscriber) is Address: unsubscribe(doit, val[1]) else: print(f'Anomalous types: ' f'{mlist.list_id} {val[0].subscriber} {val[1].subscriber}') else: print(f'Anomalous types: ' f'{mlist.list_id} {val[0].subscriber} {val[1].subscriber}') def delete_dup_sub(*arg): if len(arg) == 1 and arg[0] == 'Yes': doit = True else: doit = False for mlist in listmanager.mailing_lists: membs = dict() for memb in mlist.members.members: membs.setdefault(memb.address.email, []).append(memb) for key, val in membs.items(): if len(val) == 1: continue elif len(val) != 2: print(f'How can this be: {mlist.list_id} {key} {val}') continue else: do_dup(doit, mlist, val)