Our company is evaluating mailman3 as an option for company internal list serving.
One of the requirements is that anyone with access to the list server be allowed to create and manage lists.
Is this possible? If so, how? Is there a "create list" role that can be added for all registered users?
I'm running a Mailman 3.1.0 installation on a CentOS 7 machine. Using
I do have problems with some lists occasionally going into some kind of
shunt mode, where alla mails sent to them gets shunted. In the Mailman
log I get entries for each shunted email:
Mar 17 11:54:11 2017 (6217) Uncaught runner exception: Multiple rows
were found for one_or_none()
Mar 17 11:54:11 2017 (6217) Traceback (most recent call last):
File "/usr/lib/python3.4/site-packages/mailman/core/runner.py", line
171, in _one_iteration
File "/usr/lib/python3.4/site-packages/mailman/core/runner.py", line
264, in _process_one_file
keepqueued = self._dispose(mlist, msg, msgdata)
line 37, in _dispose
process(mlist, msg, msgdata, pipeline)
line 53, in process
handler.process(mlist, msg, msgdata)
line 121, in process
process(mlist, msg, msgdata)
line 70, in process
archiver_set = IListArchiverSet(mlist)
line 33, in __call__
return self.__implementation(*args, **kw)
File "/usr/lib/python3.4/site-packages/zope/component/_api.py", line
156, in adapter_hook
return sitemanager.queryAdapter(object, interface, name, default)
line 348, in queryAdapter
return self.adapters.queryAdapter(object, interface, name, default)
85, in wrapper
return function(args, config.db.store, *args[1:], **kws)
line 607, in __init__
ListArchiver.name == archiver_name).one_or_none()
line 2733, in one_or_none
"Multiple rows were found for one_or_none()")
sqlalchemy.orm.exc.MultipleResultsFound: Multiple rows were found for
Mar 17 11:54:11 2017 (6217) SHUNTING:
And so far my Google-fu hasn't been good enough to give me any useful
answers to why this happens. If I dump one of the pickles using qfile I
cannot see any complaints.
Most of the times, if I remove and recreate a failing list and run
unshunt the shunted emails get processed and sent.
Anyone seen something similar?
Anders Nilsson, Ph.D. <andersn(a)control.lth.se>
Dep. of Automatic Control, Lund University
Phone: +46 (0)46 222 87 94, Fax: +46 (0)46 13 81 18
Mob: +46 (0)703 22 57 67
I have of course activated password login as it was not possible to get the
provider based logins to work (might be but not worth the time for me right
now). Is there any way for an user to request a new password when it is
I presume that the Persona login is removed now. I cannot hide it in my
version or at least I do not know how.
I saw in the docs:
> We have it! We just don’t have proper documentation here yet.
Could you please be more specific - can I switch Mailman 3 installation to
#129 says that private lists are visible in the archive overview only
but "archives aren't displayed".
However, I can browse a private list's archives and read the mail text
while not logged in. Shouldn't the private archive be hidden from
we are experiencing some issues trying to run mailman3 on our server.
First, when starting docker-compose up -d the mailman-web container is
not started. The log shows:
mailman-web | useradd: user 'mailman' already exists
If we start the container with docker-compose up (without -d), all
containers start accurately. Are there other files integrated /
processed when starting docker-compose up with -d?
in the web surface. In the mailman-web log we can see they aren't found
(Error 404), but trying with docker-compose exec -T mailman-web ls
/opt/mailman-.../static/.../... they actually can be found.
Can anybody tell me why these problems appear and how to solve them? Any
help would be highly appreciated.
Thanks & Regards,
(culturebase editorial staff)
As a beginner with the REST API, I found it necessary to read code and experiment to figure out how to get things done.
There are a number of implementation choices that are unusual.
There is some documentation in src/mailman/rest/docs. It's oriented toward Python and intermixes the mailman client & REST API, apparently trying to show equivalence.
Here are some notes that may help others to avoid repeating my research. They reflect Mailman 3.1. Some reflect issues that I've opened, but I think it's worth knowing how things work today. I attempted to tie together some of pieces that are in the documentation - and note some things that aren't.
I may have some things wrong, but this reflects my current understanding. (And client code.)
The REST API has a hybrid interface: Requests are made with application/x-www-form-urlencoded POST, PUT, PATCH and delete http requests. Requests are also accepted as parameter strings.
The responses are JSON. (This is rather surprising - one would expect JSON requests - and I hope someday they'll be accepted, as the split complicates clients. I suspect this evolved to simplify the initial Web GUI client (Postorious), but it precludes using standard JSON-in/JSON-out client libraries.)
Error responses are often misidentified as content-type: application/json, but actually contain a text/plain error message. This isn't universally true; for example the 401 response actually IS JSON. A client has to guess and handle decoding exceptions.
The API presents resources hierarchically, rooted at '/'. The top level resources include /users, /lists. /addresses, /domains, /system
The next level is a resource id. There is a an id which is stable for the lifetime of an object, and a current name (which can be changed). For example, a list has a name like mylist(a)example.com, and a list_id of mylist.example.com. But if you change the list name, it becomes mynewname(a)example.net, while the list_id remains mylist.example.com.
Lists are associated with "domains", which are the "domain part" of the list's address. That is, the part after the @. This is sometimes referred to as the "mail host", but there need not be a real host. Just something on the left side of a DNS MX record. Also, don't confuse the use of "mail host" with that of "SMTP Server", which is how Mailman sends mail. The domain is where Mailman expects to receive it. A fully qualified list name is the list name + domain - e.g. its posting address. One domain can (and usually does) support more than one list. If you delete the domain, all its lists go away too.
A domain has to be created before you can create a list with an address in that domain.
Resources are created with a POST to their top-level resource. To create a domain, post to /domains with mail_host => the domain, and (optionally) description => a description for the GUI. The response isn't JSON as one would expect. In fact, it's an empty application/json response with a 201 status.
To create a list, one POSTs to /lists. This post takes a restricted set of parameters; in the case of a list, just its fqdn_listname, (and an optional style - which isn't well defined). The response isn't JSON as one would expect. The Location header of the response contains a URL of the new list.
To configure the list, you have to follow up with a PUT or PATCH to that URL + /config This is where you can set the description, posting policy, etc. It's unrealistic to do a PUT; even if you're cloning another list, there's no programatic way to determine which attributes are writable. PATCH what you know...
Members are associated with e-mail addresses - which belong to Users. You create a user by posting to /users with email => the email address, and optionally display_name => the name string. (A user can also be implicitly created by subscribing an e-mail address, but that gets confusing.) The e-mail address is the primary email address for the user. More later. Again, you get a Location header in the response, which you can use to PATCH /preferences to set delivery_status, etc. .These preferences are part of a hierarchy - many have a system default, a list default, the user default, and a subscription to that list value. You can find the User associated with a list by a GET of /addresses/address(a)example.net. This GET returns two URLs: user => the user owning this address, and self_link => the address object. Note also that there are both an email and original_email attribute. The latter preserves case. The former is used internally by Mailman as a resource key, etc. (Though exactly what happens if John(a)example.net and john(a)example.net both subscribe is unclear.)
Once a list is configured, you can add members. This requires the list_id - which you don't (officially) have. So you do a GET on the list resource, to get the list_id. Then you can subscribe a member with list_id => (the list id), subscriber => email address. Optionally you can pre_verify/confirm/approve the member and/or add a display_name.. POST to /members. Again, you get a Location header back. You can't specify everything you might like. as a creation attribute. So you may have to PATCH the member to, for example, set the moderation_status.
You may also need to PATCH the member /preferences if you want to set list-level delivery status, etc.
Consider adding at least an owner when creating a list.
One challenge is that almost everything requires multiple REST operations to set up. But REST (by definition) is stateless. So the best you can do is order operations & hope. The mailman client examples refer to transactions (e.g in users.rst, there is 'transaction.commit(); - but REST can't hold state. It does appear that the server uses DB transactions to ensure that any given REST operation is ACID, but the composite operations (e.g. create a list and set it's config) can not be Atomic. This is an architectural flaw in the API.
Symbolic names (which are required) for attributes are in the src/mailman/interfaces/(class).py.
What you can get/set comes from src/mailman/rest/(class).py.
Trying to get mailman3 setup round three. Some notes from a first timer that I hope will be of use.
These are in order of experience, and unfiltered.
I'm a bit confused about why you have a release that pip should
be able to install, but the advice I get is to pretend I'm developing
from git. But off we go:
I'm using Fedora 25. Packaged Python is 2.7.13-2, 3.6.3-6,
2-setuptools 25.1.1-1, 2-virtualenv 15.0.3-2 nodejs-less 2.7.1-1 sassc 3.4.1-1
a) fedora now uses dnf rather than yum (and has for some time). Specify dnf install rather than yum install
b) sassc is packaged - just add it to the end of the dnf install string.
I'm using sendmail. Directly outbound. Inbound, a custom LMTP client.
It is possible to setup sendmail to use LMTP for local delivery - but if you do, it's the ONLY local delivery (or you're into some serious sendmail configuration hacking). Most installations use procmail and/or pipes. I could probably extract a pipe -> lmtp script from my project - but it's Perl, not Python.
The current install process assumes a lot of Python knowledge/interaction, which is a barrier to adoption.
Documentation should note that the virtualenv commands create directories of those names (I'm not a Python person, so everything is a surprise.)
To save typing, I defined:
alias p0='[ -n "$_OLD_VIRTUAL_PATH" ] && deactivate;cd ~mailman3'
alias p2='[ -n "$_OLD_VIRTUAL_PATH" ] && deactivate;cd ~/mailman3 && source venv-2.7/bin/activate'
alias p3='[ -n "$_OLD_VIRTUAL_PATH" ] && deactivate;cd ~/mailman3 && source venv-3.5/bin/activate'
I suggest using mailman3 as the top level in your examples, since there's also a mailman directory in the path, and mailman is easily confused with mailman/mailman Also, if you have mailman2 - or your distro has provision for it - 'mailman' has other semantics. (Including, but not limited to things like SeLinux contexts...)
I got tracebacks when I got to the "mailman info" command. After some experimentation/digging, resolved with
dnf install python3-dateutil
This was confusing because Python/pip seemed to think dateutil was installed - perhaps it fell back to the Python2 version?
mailman info works!
>> You can edit your mailman.cfg file
But which one? there's one in src/mailman/config and one in var/etc/mailman.cfg. Should specify. But var looks like the one to modify, the other.
The suggestion to look at the one in src for doc isn't very helpful, there are virtually no comments. So, look at the schema.
To get started, I set the following:
### Note: LMTP needs security, preferably SSL.. Thiis is probably a bunch of config items that get fed into the Python library (e.g. use ssl, cert files (current openssl includes key w/cert, but often multiple certs - rsa + ecdsa) verify client, ca bundle, ca path, client ca.) Despite the list, these are all pass-through parameters, so should not be much work. Once you have SSL, a simple shared secret (e.g. password) can be used. Or (my preference) client verification (certificate). Maybe a proxy, but who needs another process to manage?
FWIW, my MTA runs on a separate VM from the MM instance, so assuming "localhost" is secure doesn't work. It also doesn't work on a multiuser machine.
mailman start got some things running. Telnet & LHLO wakes up LMTP!
I guess I should try to setup my first list.
More as it develops.
I have been working on containerizing Mailman 3 so that it becomes
easier to test and try Mailman 3. There are two images in total:
* maxking/mailman-core : This consists of Mailman Core and includes the
plugin to enable the Hyperkitty Archiver.
* maxking/mailman-web : This consists of a full Django installation and
run the Mailman's Web UI components. It has Mailman Client, Postorius
The images are built from the Dockerfiles hosted on Github in case
you want to look at it. You can find most of the documentation about
these images at https://asynchronous.in/docker-mailman/. The version of
the internal components included in each image is available here.
The images are versioned and the process is documented, please have a
look before you use them. Also, the images are signed and I encourage
you to verify them before using. The process of how-to verify is also
Docker Compose is a tool written in Python makes is very easy to deploy
connected-images and take the pain out of writing long long commands for
spinning of containers. There is a sample `docker-compose.yml` file in
the Github repository mentioned above which is kind-of tested to be able
to spin off these images in vanilla condition (without any
You can report issues, comments or concerns in the Github repo.
Using the REST API, how do I get from a list / list configuration to the URL of the management GUI?
I've looked through the data returned by the API and even the SQL schemas; I don't see the path.
Am I missing something, or do I need to log an issue for this?
I'm not particularly interested in the subscriber pages, but it ought to be possible to get there too...