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/