I'm going go into a lot of detail. You probably don't need all of it, but I plan to integrate it into the documentation "soon-ish", so you get it too. ;-)
Ibiam Chihurumnaya via Mailman-users writes:
Yes, the major reason I did this [through the REST API] was because I wrote some helper scripts to do some things like create and delete a list, which the only domain in the mailing list selected.
I'm assuming any other way to communicate with the rest API would automatically select the only domain that exists.
Not quite true, but for all of the operations where a list is not an argument (eg, editing an Address), the domain is irrelevant, while if a list is an argument, its domain is part of its identification.
In Mailman 2, the identity of a mailing list was its localpart, and the domain was auxiliary data. In Mailman 3, the public identity of a mailing list is its List-Id, which is usually its List-Post address with the '@' replaced by '.'. The List-Post address always contains the domain of the mailing list by definition. The List-Id and List-Post address are equivalent ways to identify the list in all the Mailman API and UI contexts I can think of. (It's possible there are some where only one of them works, but scripting applications should always accept either.)
So in Mailman 3 it's not possible to operate on a list without *explicitly* specifying the domain in the List-Post address, or implicitly by using the list_id and accessing list_host.
You could write functions to check for a unique domain and then append it to the localpart to match against the List-Post address, but we don't provide any. You could also do that for the localpart and query list_id or List-Post for .startswith(localpart), and check that for uniqueness, but again we don't provide functions like that.
It also seems to give more granular control over lists and members.
In some sense, yes, on the other hand, it provides no access controls at all.
Can mailman directly provide most of this functionality?
mailman shell cannot access the Django databases, so it can't help
you with "can't confirm a user" issues directly (eg, it can't do the
SQL UPDATE command Mark recommended). (You don't need confirmation
for the superuser created by mailman-web createsuperuser, though, so
I don't understand why you had trouble logging in.)[1]
The mailman shell command can only be used on the host where the
mailman instance runs.[2] It starts a Python process which has direct
access to *all* of the data and functions that any Mailman process
does, configures it according to the mailman.cfg it finds[3], and
returns to the Python prompt. This means that you can bypass some
validation if you're skillful (or careless) enough, but if you stick
to the APIs defined in the classes defined in interfaces/*.py you
should be quite safe.
With the -l LIST_ID option, it opens a database transaction. Then
it finds that list's MailingList object and binds the identifier 'm'
to it, and finally returns to the prompt. This requires a running
database process (PostgreSQL, etc), so you *will* be able to change
the instance. Be careful when playing around! I *think* that if you
don't use -l there is no database transaction opened, unless you do
it explicitly.
From there, there are three ways to operate on the Mailman 3 instance.
Directly from Python, using the Python objects such as MailingLists, subscriptions, Users, and Addresses. You can do anything that Python can do (although there are validation methods so Really Stupid operations, like setting an Address's display name to float NaN will raise an exception ... at least I think it will <shudder/>). This does *not* require a running instance of the Mailman system, but *will* make changes to a *stopped* instance if you used the
-l LIST_IDoption or otherwise commit a transaction (eg, using "config.db.commit()"). It can also make changes to a *running* instance.If there is no REST API URL in the arguments of examples on docs.mailman3.org, then this is what is being shown. (There are a few cases where a Python callable is created that implicitly uses a REST API, so be careful. It's always easy to see where this is so.)
Using the documentation helpers such as dump_json to access a *running* instance directly via the REST API.
Using a mailmanclient Client object to access a *running* instance via *proxy objects*. These appear to be standard Python objects defined by Mailman such as addresses, users, subscriptions, and lists, but in fact use the REST API to access the objects in the running Mailman instance (a separate process).
In fact, the data of the Mailman instance is stored in the backing database (and some on disk, such as queues and digests), and these are being accessed both by the running daemons and your mailman shell process with equal privilege and equal priority. Sanity is preserved by database transactions and file locking.
Bottom line: if you have access to the instance host, the "direct from
Python" approach is most powerful and fastest, especially for common
cases of list modification operations with mailman shell -l LIST_ID.
And you can make scripts very concisely by using -r SCRIPT and placing
SCRIPT in the virtual environment "bin" directory.
Footnotes:
[1] There is also a mailman-web command is very powerful and
flexible. It has shell and dbshell subcommands, but I don't think
these are as useful to Mailman admins as mailman shell can be.
(mailman-web dbshell just runs the database's command-line client,
but you can do that more easily, as dbshell needs a --settings SETTINGS.PY option or environment variable to find the right database
manager and database!)
[2] It needs a full Mailman core installation and a mailman.cfg[2]). In theory, the REST API can operate across the Internet. In practice, that is an Extremey Bad Idea, Do NOT Do This. Also in practice, cross- node operation is used in many Docker-based instances, but that's on a private network, usually a non-routable LAN in a single host or VM.
[3] There is a complicated search process which in some cases may
create a new mailman.cfg. Always check if the mailman info command
finds the mailman.cfg you expect, usually /etc/mailman3/mailman.cfg.
If not, use the -C /path/to/mailman.cfg option. In my environments,
$ su - mailman # obviously
$ . .v/bin/activate # .v = the virtual environment
$ mailman info
always gives the expected output.
Regards, Steve
-- GNU Mailman consultant (installation, migration, customization) Sirius Open Source https://www.siriusopensource.com/ Software systems consulting in Europe, North America, and Japan