#! @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()