List suspended members

Listing all members is pretty easy; it’s just a matter of making Mailman pretend that there aren’t so many members as to need chunking alphabetically. But what about seeing just the suspended members? People get suspended for all sorts of automatic reasons. Sometimes it’s useful to see who in the mailing list is currently suspended.

This requires modifying Mailman/Gui/Membership.py and Mailman/Cgi/admin.py.

Changing Membership.py is just a matter of adding a new entry to GetConfigSubCategories(self, category):

  • ('listnomail', _('List Suspended')),

This will cause “List Suspended” to appear as an option on the Membership Management page. See List all Mailman members for more info.

In Mailman/Cgi/admin.py, around line 494, you have something like:

[toggle code]

  • # Figure out which subcategory we should display
  • subcat = Utils.GetPathPieces()[-1]
  • if subcat not in ('list', 'add', 'remove''):
    • subcat = 'list'

Add the new option code (listnomail) to the list of valid subcats:

[toggle code]

  • # Figure out which subcategory we should display
  • subcat = Utils.GetPathPieces()[-1]
  • if subcat not in ('list', 'add', 'remove', 'listnomail'):
    • subcat = 'list'

Around line 901, you’ve got something like:

[toggle code]

  • bucket = None
  • actionurl = None
  • if len(all) < chunksz:
    • members = all

Remember that you might have modified the chunksz line if you’ve added the “listall” feature.

Between “actionurl = None” and “if len(all) < chunksz:”, add some code to filter out all but suspended members if that option was selected:

[toggle code]

  • bucket = None
  • actionurl = None
  • if subcat == 'listnomail':
    • newall = []
    • for addr in all:
      • status = mlist.getDeliveryStatus(addr)
      • if status != MemberAdaptor.ENABLED:
        • newall.append(addr)
    • all = newall
  • if len(all) < chunksz:
    • members = all

That will change the behavior so that on initially choosing “List Suspended”, only the suspended members are shown. But if there are a lot of suspended members that will trigger chunking. That’s not a bad thing, but all of the links to different letters don’t include the listnomail option.

The letter links get set in two different places. Around line 930, look for:

[toggle code]

  • members = buckets[bucket]
  • action = adminurl + '/members?letter=%s' % bucket
  • if len(members) <= chunksz:
    • form.set_action(action)

Around line 970, look for:

[toggle code]

  • if regexp:
    • findfrag = '&findmember=' + urllib.quote(regexp)
  • url = adminurl + '/members?letter=' + letter +findfrag
  • if letter == bucket:
    • show = Bold('[%s]' % letter.upper()).Format()

In both places, the offending line is the one that sets the action or url to “adminurl + '/members?letter=…”. Replace each with an if/then that adds the subcat to the URL if the subcat is not “list”:

[toggle code]

  • if subcat == 'list':
    • action = adminurl + '/members?letter=%s' % bucket
  • else:
    • action = adminurl + '/members/' + subcat + '/letter=%s' % bucket

And for the second one:

[toggle code]

  • if subcat == 'list':
    • url = adminurl + '/members?letter=' + letter + findfrag
  • else:
    • url = adminurl + '/members/' + subcat + '?letters' + letter + findfrag

Finally, around line 849 there’s a line that adds the title “Membership List” above the table of members. Let’s add a little better feedback that they’re looking at a subset of the membership list:

Change:

  • header.AddRow([Center(Header(2, _('Membership List')))])

to:

[toggle code]

  • if subcat == 'listnomail':
    • header.AddRow([Center(Header(2, _('Suspended Member List')))])
  • else:
    • header.AddRow([Center(Header(2, _('Membership List')))])

And the big blue title bar now displays “Suspended Member List” if that’s what the list manager is viewing.