Hello.

I attach a program do delete subscription per list. Someone send it to me some time ago, when I had the same problem.


On 26/4/2021 1:53 μ.μ., John Elliot V | ProgClub wrote:
Thanks to the advice of Mark Sapiro I have managed to stop the deluge of
subscriptions to my lists, but I am left with the problem of having over
20,000 pending subscriptions awaiting my administration.

What would be great is if there were a command line program I could run
to delete all pending subscription requests, is there such a thing?

Regards,
John Elliot V
#! /usr/bin/python
#
# Copyright (C) 1998-2015 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.

"""Check for pending admin requests and print the results.

Usage: %(PROGRAM)s [options]

Options:

    -l <listname>/--list=<listname>
        List requests for the <listname> list.  May be repeated for multiple
        lists.  The default is to do all lists.

    -v/--verbose
        Adds the request ID to the output for each request.

    -H/--handle
        Lists requests one by one and prompts for a (S)kip, (A)ccept,
        (R)eject or (D)iscard response which is then handled immediately.
        Optionally, add 'all' to the response to apply it to all remaining
        requests of the same type for the current list or reply (Q)uit to
        stop after having handled a subset of the requests.

    -h/--help
        Print this message and exit.

This script must run from Mailman's bin/ directory.
"""

import sys
import time
import getopt
from types import UnicodeType

import paths

# Import this after paths so we get Mailman's copy of the email package
from email.Charset import Charset

from Mailman import mm_cfg
from Mailman import Errors
from Mailman import Utils
from Mailman import MailList
from Mailman import Message
from Mailman import i18n
from Mailman.ListAdmin import HELDMSG, SUBSCRIPTION, UNSUBSCRIPTION

NL = '\n'
PROGRAM = sys.argv[0]

_ = i18n._
i18n.set_language(mm_cfg.DEFAULT_SERVER_LANGUAGE)
scset = Charset(Utils.GetCharSet(mm_cfg.DEFAULT_SERVER_LANGUAGE))
outcodec = scset.output_codec or 'ascii'

now = time.time()



def usage(code, msg=''):
    if code:
        fd = sys.stderr
    else:
        fd = sys.stdout
    print >> fd, _(__doc__)
    if msg:
        print >> fd, msg
    sys.exit(code)



def main():
    global verbose
    try:
        opts, args = getopt.getopt(sys.argv[1:], 'l:vHh',
                                   ['list=', 'verbose', 'handle', 'help'])
    except getopt.error, msg:
        usage(1, msg)

    lists = []
    verbose = handle = False
    for opt, arg in opts:
        if opt in ('-h', '--help'):
            usage(0)
        if opt in ('-l', '--list'):
            lists.append(arg.lower())
        if opt in ('-v', '--verbose'):
            verbose = True
        if opt in ('-H', '--handle'):
            handle = True

    if args:
        usage(1)

    if not lists:
        lists = Utils.list_names()
    for name in lists:
        ret = 0
        # the list must be locked in order to open the requests database
        try:
            mlist = MailList.MailList(name)
        except Errors.MMUnknownListError:
            print >> sys.stderr, '%s: Unknown List' % name
            continue
        try:
            count = mlist.NumRequestsPending()
            if count:
                i18n.set_language(mlist.preferred_language)
                realname = mlist.real_name
                reqs = pending_requests(mlist)
                print _(
                    '%(count)d %(realname)s moderator request(s) waiting\n')
                changed = 0
                alltype = None
                for message, id in reqs:
                    print message
                    if id and handle:
                        # Get record type before losing it.
                        rtype = mlist.GetRecordType(id)
                        ret = handle_req(mlist, id, alltype)
                        changed += ret % 100
                        if ret == 200:
                            break
                        if ret >= 100:
                            alltype = rtype
                        else:
                            alltype = None
                if changed:
                    mlist.Save()
        finally:
            mlist.Unlock()
        if ret == 200:
            break



def pending_requests(mlist):
    # Must return a byte string
    lcset = Utils.GetCharSet(mlist.preferred_language)
    pending = []
    first = 1
    for id in mlist.GetSubscriptionIds():
        if first:
            pending.append((_('Pending subscriptions:'), None))
            first = 0
        when, addr, fullname, passwd, digest, lang = mlist.GetRecord(id)
        if fullname:
            if isinstance(fullname, UnicodeType):
                fullname = fullname.encode(lcset, 'replace')
            fullname = ' (%s)' % fullname
        message = '    %s%s %s' % (addr, fullname, time.ctime(when))
        if verbose:
            message += '\n        %s' % id
        pending.append((message, id))
    first = 1
    for id in mlist.GetUnsubscriptionIds():
        if first:
            pending.append((_('Pending unsubscriptions:'), None))
            first = 0
        addr = mlist.GetRecord(id)
        message = '    %s' % addr
        if verbose:
            message += '\n        %s' % id
        pending.append((message, id))
    first = 1
    for id in mlist.GetHeldMessageIds():
        if first:
            pending.append((_('\nPending posts:'), None))
            first = 0
        info = mlist.GetRecord(id)
        when, sender, subject, reason, text, msgdata = mlist.GetRecord(id)
        subject = Utils.oneline(subject, lcset)
        date = time.ctime(when)
        reason = _(reason)
        message = _("""\
From: %(sender)s on %(date)s
Subject: %(subject)s
Cause: %(reason)s""")
        if verbose:
            message += '\n        %s' % id
        message += '\n'
        pending.append((message, id))
    # Coerce all items in pending to a Unicode so we can join them
    newpending = []
    for s, id in pending:
        if isinstance(s, UnicodeType):
            umessage = s
        else:
            umessage = unicode(s, lcset, 'replace')
        # Encode the message in the charset of the default server language.
        message = umessage.encode(outcodec, 'replace')
        newpending.append((message, id))
    return newpending



def handle_req(mlist, id, alltype):
    global reply, ret
    rtype = mlist.GetRecordType(id)
    listname = mlist.real_name
    if rtype == HELDMSG:
        typemsg = 'messages'
    elif rtype == SUBSCRIPTION:
        typemsg = 'subscriptions'
    elif rtype == UNSUBSCRIPTION:
        typemsg = 'unsubscriptions'
    if rtype != alltype:
        reply = ''
    while reply not in ('s', 'a', 'r', 'd'):
        inp = raw_input(
_("""(S)kip, (A)ccept, (R)eject, (D)iscard this request or (Q)uit to stop now.
To apply the response to all held %(typemsg)s for the %(listname)s list,
append 'all' to your reply. E.g., reply 'd all' to discard the rest of
the held %(typemsg)s for the %(listname)s list.
""")).lower()
        reply = inp[:1]
        if reply not in ('s', 'a', 'r', 'd', 'q'):
            print _('Invalid response; enter s, a, r, d or q')
        if reply == 'q':
            return 200
        if inp.endswith('all'):
            ret = 100
        else:
            ret = 0
    if reply == 'a':
        if rtype == HELDMSG:
            mlist.HandleRequest(id, mm_cfg.APPROVE)
        elif rtype == SUBSCRIPTION:
            mlist.HandleRequest(id, mm_cfg.SUBSCRIBE)
        elif rtype == UNSUBSCRIPTION:
            mlist.HandleRequest(id, mm_cfg.UNSUBSCRIBE)
        if ret:
            print 'Approved.\n'
    elif reply == 'r':
        mlist.HandleRequest(id, mm_cfg.REJECT)
        if ret:
            print 'Rejected.\n'
    elif reply == 'd':
        mlist.HandleRequest(id, mm_cfg.DISCARD)
        if ret:
            print 'Discarded.\n'
    else:
        if ret:
            print 'Skipped.\n'
        return ret
    return ret + 1



if __name__ == '__main__':
    main()
------------------------------------------------------
Mailman-Users mailing list -- mailman-users@python.org
To unsubscribe send an email to mailman-users-le...@python.org
https://mail.python.org/mailman3/lists/mailman-users.python.org/
Mailman FAQ: http://wiki.list.org/x/AgA3
Security Policy: http://wiki.list.org/x/QIA9
Searchable Archives: https://www.mail-archive.com/mailman-users@python.org/
    https://mail.python.org/archives/list/mailman-users@python.org/

Reply via email to