#! @PYTHON@ # # Copyright (C) 1998-2018 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. """Find all lists that a member's address is on. Usage: find_member [options] regex [regex [...]] Where: --listname=listname -l listname Include only the named list in the search. --exclude=listname -x listname Exclude the named list from the search. --owners -w Search list owners as well as members. --help -h Print this help message and exit. regex A Python regular expression to match against. The interaction between -l and -x is as follows. If any -l option is given then only the named list will be included in the search. If any -x option is given but no -l option is given, then all lists will be search except those specifically excluded. Regular expression syntax is Perl5-like, using the Python re module. Complete specifications are at: https://docs.python.org/2/library/re.html Address matches are case-insensitive, but case-preserved addresses are displayed. """ import sys import re import getopt import paths from Mailman import Utils from Mailman import MailList from Mailman import Errors from Mailman.i18n import C_ AS_MEMBER = 0x01 AS_OWNER = 0x02 def usage(code, msg=''): if code: fd = sys.stderr else: fd = sys.stdout print >> fd, C_(__doc__) if msg: print >> fd, msg sys.exit(code) def scanlists(options): cres = [] for r in options.regexps: cres.append(re.compile(r, re.IGNORECASE)) # # dictionary of {address, (listname, ownerp)} matches = {} for listname in options.listnames: try: mlist = MailList.MailList(listname, lock=0) except Errors.MMListError: print C_('No such list: %(listname)s') continue if options.owners: owners = mlist.owner else: owners = [] for cre in cres: for member in mlist.getMembers(): if cre.search(member): addr = mlist.getMemberCPAddress(member) entries = matches.get(addr, {}) aswhat = entries.get(listname, 0) aswhat |= AS_MEMBER entries[listname] = aswhat matches[addr] = entries for owner in owners: if cre.search(owner): entries = matches.get(owner, {}) aswhat = entries.get(listname, 0) aswhat |= AS_OWNER entries[listname] = aswhat matches[owner] = entries return matches class Options: listnames = Utils.list_names() owners = None def main(): try: opts, args = getopt.getopt(sys.argv[1:], 'l:x:wh', ['listname=', 'exclude=', 'owners', 'help']) except getopt.error, msg: usage(1, msg) options = Options() loptseen = 0 excludes = [] for opt, arg in opts: if opt in ('-h', '--help'): usage(0) elif opt in ('-l', '--listname'): if not loptseen: options.listnames = [] loptseen = 1 options.listnames.append(arg.lower()) elif opt in ('-x', '--exclude'): excludes.append(arg.lower()) elif opt in ('-w', '--owners'): options.owners = 1 for ex in excludes: try: options.listnames.remove(ex) except ValueError: pass if not args: usage(1, C_('Search regular expression required')) options.regexps = args if not options.listnames: print C_('No lists to search') return matches = scanlists(options) addrs = matches.keys() addrs.sort() for k in addrs: hits = matches[k] lists = hits.keys() print k, C_('found in:') for name in lists: aswhat = hits[name] if aswhat & AS_MEMBER: print ' ', name if aswhat & AS_OWNER: print ' ', name, C_('(as owner)') if __name__ == '__main__': main()