Syncing members
The mailman syncmembers
command allows a site administrator to sync the
membership of a mailing list with an input file.
>>> from mailman.testing.documentation import cli
>>> command = cli('mailman.commands.cli_syncmembers.syncmembers')
Usage
Here is the complete usage for the command.
>>> command('mailman syncmembers --help')
Usage: syncmembers [OPTIONS] FILENAME LISTSPEC
Add and delete members as necessary to syncronize a list's membership with
an input file. FILENAME is the file containing the new membership, one
member per line. Blank lines and lines that start with a '#' are ignored.
Addresses in FILENAME which are not current list members will be added to
the list with delivery mode as specified with -d/--delivery. List members
whose addresses are not in FILENAME will be removed from the list.
FILENAME can be '-' to indicate standard input.
Options:
-d, --delivery [regular|mime|plain|summary|disabled]
Set the added members delivery mode to
'regular', 'mime', 'plain', 'summary' or
'disabled'. I.e., one of regular, three
modes of digest or no delivery. If not
given, the default is regular.
-w, --welcome-msg / -W, --no-welcome-msg
Override the list's setting for
send_welcome_message to added members.
-g, --goodbye-msg / -G, --no-goodbye-msg
Override the list's setting for
send_goodbye_message to deleted members.
-a, --admin-notify / -A, --no-admin-notify
Override the list's setting for
admin_notify_mchanges.
-n, --no-change Don't actually make the changes. Instead,
print out what would be done to the list.
--help Show this message and exit.
Examples
You can synchronize all member addresses of a mailing list with the
member addresses found in a file from the command line. To do so, you
need a file containing email addresses and optional display names that can be
parsed by email.utils.parseaddr()
. All mail addresses not contained in
the file will be deleted from the mailing list. Every address found in the
specified file will be added to the specified mailing list.
First we create a list and add a few members.
>>> from mailman.app.lifecycle import create_list
>>> bee = create_list('bee@example.com')
>>> from mailman.testing.helpers import subscribe
>>> subscribe(bee, 'Fred')
<Member: Fred Person <fperson@example.com> on bee@example.com
as MemberRole.member>
>>> subscribe(bee, 'Greg')
<Member: Greg Person <gperson@example.com> on bee@example.com
as MemberRole.member>
>>> subscribe(bee, 'Jeff')
<Member: Jeff Person <jperson@example.com> on bee@example.com
as MemberRole.member>
Note that only changes of the mailing list will be written to output so in the first example, Fred is a member who remains on the list and isn’t reported.
>>> from tempfile import NamedTemporaryFile
>>> filename = cleanups.enter_context(NamedTemporaryFile()).name
>>> with open(filename, 'w', encoding='utf-8') as fp:
... print("""\
... aperson@example.com
... cperson@example.com (Cate Person)
... Fred Person <fperson@example.com>
... """, file=fp)
>>> command('mailman syncmembers ' + filename + ' bee.example.com')
[ADD] aperson@example.com
[ADD] Cate Person <cperson@example.com>
[DEL] Greg Person <gperson@example.com>
[DEL] Jeff Person <jperson@example.com>
>>> from operator import attrgetter
>>> from mailman.testing.documentation import dump_list
>>> dump_list(bee.members.addresses, key=attrgetter('email'))
aperson@example.com
Cate Person <cperson@example.com>
Fred Person <fperson@example.com>
You can also specify -
as the filename, in which case the addresses are
taken from standard input.
>>> stdin = """\
... dperson@example.com
... Elly Person <eperson@example.com>
... """
>>> command('mailman syncmembers - bee.example.com', input=stdin)
[ADD] dperson@example.com
[ADD] Elly Person <eperson@example.com>
[DEL] aperson@example.com
[DEL] Cate Person <cperson@example.com>
[DEL] Fred Person <fperson@example.com>
>>> dump_list(bee.members.addresses, key=attrgetter('email'))
dperson@example.com
Elly Person <eperson@example.com>
Blank lines and lines that begin with ‘#’ are ignored.
>>> with open(filename, 'w', encoding='utf-8') as fp:
... print("""\
... #cperson@example.com
... eperson@example.com
...
... bperson@example.com
... """, file=fp)
>>> command('mailman syncmembers ' + filename + ' bee.example.com')
[ADD] bperson@example.com
[DEL] dperson@example.com
>>> dump_list(bee.members.addresses, key=attrgetter('email'))
bperson@example.com
Elly Person <eperson@example.com>
If there is nothing to do, it will output just that.
>>> with open(filename, 'w', encoding='utf-8') as fp:
... print("""\
... bperson@example.com
... eperson@example.com
... """, file=fp)
>>> command('mailman syncmembers ' + filename + ' bee.example.com')
Nothing to do
>>> dump_list(bee.members.addresses, key=attrgetter('email'))
bperson@example.com
Elly Person <eperson@example.com>