================ Managing members ================ The ``mailman members`` command allows a site administrator to display, add, and remove members from a mailing list. :: >>> mlist1 = create_list('test1@example.com') >>> class FakeArgs: ... input_filename = None ... output_filename = None ... listname = [] ... regular = False ... digest = None ... nomail = None >>> args = FakeArgs() >>> from mailman.commands.cli_members import Members >>> command = Members() Listing members =============== You can list all the members of a mailing list by calling the command with no options. To start with, there are no members of the mailing list. >>> args.listname = [mlist1.fqdn_listname] >>> command.process(args) test1@example.com has no members Once the mailing list add some members, they will be displayed. :: >>> from mailman.testing.helpers import subscribe >>> subscribe(mlist1, 'Anne', email='anne@example.com') on test1@example.com as MemberRole.member> >>> subscribe(mlist1, 'Bart', email='bart@example.com') on test1@example.com as MemberRole.member> >>> command.process(args) Anne Person Bart Person Members are displayed in alphabetical order based on their address. :: >>> subscribe(mlist1, 'Anne', email='anne@aaaxample.com') on test1@example.com as MemberRole.member> >>> command.process(args) Anne Person Anne Person Bart Person You can also output this list to a file. >>> from tempfile import mkstemp >>> fd, args.output_filename = mkstemp() >>> import os >>> os.close(fd) >>> command.process(args) >>> with open(args.output_filename) as fp: ... print(fp.read()) Anne Person Anne Person Bart Person >>> os.remove(args.output_filename) >>> args.output_filename = None The output file can also be standard out. >>> args.output_filename = '-' >>> command.process(args) Anne Person Anne Person Bart Person >>> args.output_filename = None Filtering on delivery mode -------------------------- You can limit output to just the regular non-digest members... >>> from mailman.interfaces.member import DeliveryMode >>> args.regular = True >>> member = mlist1.members.get_member('anne@example.com') >>> member.preferences.delivery_mode = DeliveryMode.plaintext_digests >>> command.process(args) Anne Person Bart Person ...or just the digest members. Furthermore, you can either display all digest members... >>> member = mlist1.members.get_member('anne@aaaxample.com') >>> member.preferences.delivery_mode = DeliveryMode.mime_digests >>> args.regular = False >>> args.digest = 'any' >>> command.process(args) Anne Person Anne Person ...just plain text digest members... >>> args.digest = 'plaintext' >>> command.process(args) Anne Person ...just MIME digest members. :: >>> args.digest = 'mime' >>> command.process(args) Anne Person # Reset for following tests. >>> args.digest = None Filtering on delivery status ---------------------------- You can also filter the display on the member's delivery status. By default, all members are displayed, but you can filter out only those whose delivery status is enabled... :: >>> from mailman.interfaces.member import DeliveryStatus >>> member = mlist1.members.get_member('anne@aaaxample.com') >>> member.preferences.delivery_status = DeliveryStatus.by_moderator >>> member = mlist1.members.get_member('bart@example.com') >>> member.preferences.delivery_status = DeliveryStatus.by_user >>> member = subscribe(mlist1, 'Cris', email='cris@example.com') >>> member.preferences.delivery_status = DeliveryStatus.unknown >>> member = subscribe(mlist1, 'Dave', email='dave@example.com') >>> member.preferences.delivery_status = DeliveryStatus.enabled >>> member = subscribe(mlist1, 'Elle', email='elle@example.com') >>> member.preferences.delivery_status = DeliveryStatus.by_bounces >>> args.nomail = 'enabled' >>> command.process(args) Anne Person Dave Person ...or disabled by the user... >>> args.nomail = 'byuser' >>> command.process(args) Bart Person ...or disabled by the list administrator (or moderator)... >>> args.nomail = 'byadmin' >>> command.process(args) Anne Person ...or by the bounce processor... >>> args.nomail = 'bybounces' >>> command.process(args) Elle Person ...or for unknown (legacy) reasons. >>> args.nomail = 'unknown' >>> command.process(args) Cris Person You can also display all members who have delivery disabled for any reason. :: >>> args.nomail = 'any' >>> command.process(args) Anne Person Bart Person Cris Person Elle Person # Reset for following tests. >>> args.nomail = None Adding members ============== You can add members to a mailing list from the command line. To do so, you need a file containing email addresses and full names that can be parsed by ``email.utils.parseaddr()``. :: >>> mlist2 = create_list('test2@example.com') >>> import os >>> path = os.path.join(config.VAR_DIR, 'addresses.txt') >>> with open(path, 'w') as fp: ... for address in ('aperson@example.com', ... 'Bart Person ', ... 'cperson@example.com (Cate Person)', ... ): ... print(address, file=fp) >>> args.input_filename = path >>> args.listname = [mlist2.fqdn_listname] >>> command.process(args) >>> from operator import attrgetter >>> dump_list(mlist2.members.addresses, key=attrgetter('email')) aperson@example.com Bart Person Cate Person You can also specify ``-`` as the filename, in which case the addresses are taken from standard input. :: >>> from io import StringIO >>> fp = StringIO() >>> for address in ('dperson@example.com', ... 'Elly Person ', ... 'fperson@example.com (Fred Person)', ... ): ... print(address, file=fp) >>> filepos = fp.seek(0) >>> import sys >>> sys.stdin = fp >>> args.input_filename = '-' >>> command.process(args) >>> sys.stdin = sys.__stdin__ >>> dump_list(mlist2.members.addresses, key=attrgetter('email')) aperson@example.com Bart Person Cate Person dperson@example.com Elly Person Fred Person Blank lines and lines that begin with '#' are ignored. :: >>> with open(path, 'w') as fp: ... for address in ('gperson@example.com', ... '# hperson@example.com', ... ' ', ... '', ... 'iperson@example.com', ... ): ... print(address, file=fp) >>> args.input_filename = path >>> command.process(args) >>> dump_list(mlist2.members.addresses, key=attrgetter('email')) aperson@example.com Bart Person Cate Person dperson@example.com Elly Person Fred Person gperson@example.com iperson@example.com Addresses which are already subscribed are ignored, although a warning is printed. :: >>> with open(path, 'w') as fp: ... for address in ('gperson@example.com', ... 'aperson@example.com', ... 'jperson@example.com', ... ): ... print(address, file=fp) >>> command.process(args) Already subscribed (skipping): gperson@example.com Already subscribed (skipping): aperson@example.com >>> dump_list(mlist2.members.addresses, key=attrgetter('email')) aperson@example.com Bart Person Cate Person dperson@example.com Elly Person Fred Person gperson@example.com iperson@example.com jperson@example.com Displaying members ================== With no arguments, the command displays all members of the list. >>> args.input_filename = None >>> command.process(args) aperson@example.com Bart Person Cate Person dperson@example.com Elly Person Fred Person gperson@example.com iperson@example.com jperson@example.com