Mailman 3


Staff member

Reaction score: 9,824
Messages: 35,001

Looks like it hasn't reached the ports yet. However, you can install 2.1.x: mail/mailman.


Son of Beastie

Reaction score: 166
Messages: 3,377

I'm trying to log my progress for anyone interested in installing Mailman 3..

pkg install python3

pkg install py36-sqlite3

python3 -m ensurepip

pip3 install mailman

mailman info - this creates the mailman subdirectory tree in the current directory.



Son of Beastie

Reaction score: 166
Messages: 3,377

Trying to figure out the directory structure that Mailman 3 on FreeBSD should adopt. Here is what is used on Linux:-

I'd be interested in the FreeBSD Gurus view on how this should be configured on FreeBSD:-

bin_dir: /sbin
var_dir: /var/lib/mailman
queue_dir: /var/spool/mailman
log_dir: /var/log/mailman
lock_dir: /var/lock/mailman
etc_dir: /etc
ext_dir: /etc/mailman.d
pid_file: /var/run/mailman/


New Member

Reaction score: 2
Messages: 2


I have followed your notes and installed MM3 on my FreeBSD 11.2.
I have opted to use /opt/mailman3 as the directory for MM3.
So I did:

cd /opt
mkdir mailman3
cd mailman3
mailman info

The directory has been populated with some data.

# Then from
pip3 install postorius
pip3 install hyperkitty
pip3 install mailman-hyperkitty
pip3 install uwsgi

All those installed successfully. However, I am not sure where they installed into :)

What next now?? Edit the var/etc/mailman.cfg??

Then how to launch the queue runner? Postorius? HyperKitty? etc?



Son of Beastie

Reaction score: 166
Messages: 3,377

I gave up over a year ago, but following your post I will rekindle my interest :)



Reaction score: 1
Messages: 59

I tried mailman3 today. The story now is even shorter, when installing on 12.1-RELEASE-p10 after installing the pkg. It advises to execute service mailman oneinfo to set configuration etc. That already fails:

The port itself shows this:

To initialise Mailman's runtime directories, log files and database for
the first time, run service mailman info You can then start Mailman by
running: service mailman start

After doing so , I get this error:

root@vm1:/zroot/zdata/howdoyoudo/freebsd # service mailman oneinfo
Traceback (most recent call last):
"[I]/usr/local/lib/python3.7/site-packages/pkg_resources/[/I]", line
583, in _build_master
"[I]/usr/local/lib/python3.7/site-packages/pkg_resources/[/I]", line
900, in require
    needed = self.resolve(parse_requirements(requirements))
"[I]/usr/local/lib/python3.7/site-packages/pkg_resources/[/I]", line
791, in resolve
    raise VersionConflict(dist, req).with_context(dependent_req)
pkg_resources.ContextualVersionConflict: (zope.interface 4.6.0
Requirement.parse('zope.interface>=5.0'), {'mailman'})

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/local/bin/mailman", line 6, in <module>
    from pkg_resources import load_entry_point
"[I]/usr/local/lib/python3.7/site-packages/pkg_resources/[/I]", line
3251, in <module>
"[I]/usr/local/lib/python3.7/site-packages/pkg_resources/[/I]", line
3235, in _call_aside
    f(*args, **kwargs)
"[I]/usr/local/lib/python3.7/site-packages/pkg_resources/[/I]", line
3264, in _initialize_master_working_set
    working_set = WorkingSet._build_master()
"[I]/usr/local/lib/python3.7/site-packages/pkg_resources/[/I]", line
585, in _build_master
    return cls._build_from_requirements(__requires__)
"[I]/usr/local/lib/python3.7/site-packages/pkg_resources/[/I]", line
598, in _build_from_requirements
    dists = ws.resolve(reqs, Environment())
"[I]/usr/local/lib/python3.7/site-packages/pkg_resources/[/I]", line
786, in resolve
    raise DistributionNotFound(req, requirers)
pkg_resources.DistributionNotFound: The 'zope.interface>=5.0'
distribution was not found and is required by mailman

It's a fresh install and it fails on the first command, I wonder what I
should do next...



Reaction score: 1
Messages: 59

Ah ok, nice to know next time i check the bug list before i launch something. Thanks for your reply Elazar!


Aspiring Daemon

Reaction score: 80
Messages: 587

PR 225543 put Mailman 3 into the ports tree.

I have recently updated PR 250362 with a list of how to get Mailman running, but not necessarily functional.

My next step, porting Postorius to FreeBSD. If anyone is available to help, please let me know.


Active Member

Reaction score: 34
Messages: 148

We just moved/migrated our MM2 over to mail/sympa. We only had a handful of lists, so it wasn't too painful. List moderators like the interface better.


New Member

Reaction score: 3
Messages: 3

Hi everybody :
I've just finished the migration from mailman2 to a mailman3 for two servers and a bunch of lists (17 in one server 2 in the other). The servers are running 12.2-RELEASE (with python 3.7 -and 2.7- installed from ports).
I begun trying to install it from ports, following Mr. Langille recommendations but I faced a hell of dependencies issues. Then I followed the installation guide in, but out of docker or virtualenv environment. I made a mix of ports and pip installs as long I need.
The servers are jailed and both running apache24 but are proxied from a nginx server each one acting as firewall/proxy (that hosted the jails). For the wsgi process I installed mod-wsgi and uwsgi for hyperkitty
All is working like a charm now, but It was really difficult to find the correct config for all the processes involved.
If there is interest in this aproximation I will polish my notes and put them here.


New Member

Reaction score: 3
Messages: 3

Yes, please especially the missing dependencies and the configurations.
Well.. first of all I need to express my thankfulness to all of you who work in making FreeBSD the better and solid platform, and in this moment, with python 2.7 in its EOL, the migration of mailman2 to mailman3 was a big thing. Thanks a lot [USER=730]dvl@[/USER].
(and beg all of you your pardon if my english is misspelled or confusing: I think in spanish)

The start point:
2 servers upgraded to 12.2-RELEASE acting as firewalls/proxies in separated lines (one ADSL, the other optic fiber), with static IPs. Each of them had running sendmail + mailman2 + nginx and are the hosts of a number of jailed servers who serve Drupal or Wordpress sites (with apache24). The two had identical configurations. They have letsencrypt certificates (but some of them are proxied by cloudflare, too)
For each jailed server there is a mount point to mailman2 (/usr/local/mailman), the ports(/usr/ports) and the certificate from the host server(/usr/local/etc/letsencrypt).
All the mail treatment occurs in the main host with sendmail (by the way: I changed to sendmail from ports, as some time ago, two or three years ago if I recall it well, it was easier to config for auth mail and other things), but you can access to the web config in the jailed servers as they have mailman2 installed an accessible via the mount point. In the jailed servers the MTA was sendmail, but only with submit activated.
Lets say I have (ADSL line) as the main host(local IP, and as jailed host (local IP with 2 mailman lists. For the optic fiber line I have (local IP and as its jailed host (local IP with 17 mailman lists.

I hope it pictures well the panorama from I started...

As I said in my first comment, one of the jailed servers had just 2 lists in mailman, and it was the "target" to try and test the migration: they have not much email traffic. It served a Drupal site with apache24 (which means that I have to combine the new mailman3 Django project underlying).

[[[ I'm going to focus in this post in the tryings and "what didn't work well" things and in a separate post I will list the steps in the other server which work well at the end without all the frustration]]]

- The first thing I thought I had to do was to change the MTA in the jailed server ( - mostly all the help guides are prepared to use postfix as MTA, so I did a "portsnap fetch update" and installed postfix form ports. I followed . It needed some adjusts for mailman3 but I applied them after (we'll come back to the postfix and sendmail in the main server config in the "all went well" post)

(WARNING: all the python installs from ports where with FLAVOR=py37 as I have a running python 2.7 apps yet)

- I followed the post of dvl@ in this thread, made a make install of /usr/ports/mail/mailman3 and
it went well. As he mentioned, I was expecting dependencies problems ( For the steps in the whole installation I tried to follow, but out the virtualenv enviroment (I've noticed some folks having serious problems with virtualenv in freebsd, and I have no experience with it).
After I had mailman3 running I tried to install and config the Django ports. I found that the perl version was too low (5.26), and then upgraded all perl dependencias to 5.30. And here I fell into hell: it needed upgrade rust (which I upgrade from pkg, because from ports it will take DAYS to compile). It had conflicts with ImageMagick and php-gd... and many many more in a loop.

This was the moment I decided to uninstall Django from ports and try to "pip install" what I need. At the end I reinstalled all the mailman apps from pip and configured all thereafter.
Next post I show the steps that went well from the beginning.
Last edited:


New Member

Reaction score: 3
Messages: 3

As I said in my previous post (please review the first part of it to see all the picture), after I made a succesfull mailman3 installation in one server with 2 mailman2 lists, I did it again with a jailed server with 17 mailman2 lists.
The servers: (local IP and as its jailed host (local IP with 17 mailman lists.
The scope:
postfix config files in /usr/local/etc/postix (I attach as postfix-main.conf with all comment lines stripped)
postfix virtual users in /usr/local/etc/postfix/virtusertable
mailman3 services in /usr/local/mailman3
/usr/local/bin/python3.7 has a ln -s to /usr/local/bin/python3 (I had python linked to the 2.7 version yet)

In the jailed server (
- portsnap fetch update

- install /usr/ports/mail/postfix

- followed the changing MTA from sendmail (only submit) to postfix guide

- created user for sasl2 authentication in /usr/local/etc/postfix/sasl_passwd and postmap it
[]:587 mailoutuser: passoutuser
(there is no space after the colon, but this wysiwyg translate as a :p, so I put one here)
(you have to create the user in the main server with "saslpasswd2 -c" )

- installed /usr/ports/devel/py-pip with FLAVOR=py37

- did a "ln -s /usr/local/bin/py37-pip to /usr/local/bin/pip" in order to clarity and follow guides

- pip install mailman

- installed /usr/ports/textproc/sassc and did an "ln -s /usr/local/bin/sassc /usr/bin/sassc" for django to find it (important)

- pip install mailmanclient

- created user mailman3 with the same gid and uid as mailman (1113:1113 in my system) and with /usr/local/mailman3 as home .

- mkdir /usr/local/mailman3 & chown mailman3:mailman /usr/local/mailman3

- install /usr/ports/devel/git

- cd /usr/local

- git clone
That clones mailman-suite and bring us some files to get config

- cd mailman-suite/mailman-suite_project
- su -m mailman3 -c " cp, and /usr/local/mailman3"
(you can now delete /usr/local/mailman-suite as is no longer needed)

I attach the mailman.conf file that would be /usr/local/mailman3/var/etc/mailman.cfg

[[[Post edition 12/27/20:
I've found that I missed to define one important thing in mailman.cfg
The site owner as it is the "from" address which sends you the unsuscribe notifications, etc.
You can see all the config possibilities in
I've added these lines in the top of my mailman.cfg file
default_language: es
(the second line, obviously, is not necessary for your config)

- installed /usr/ports/databases/py-pymysql as I want that mailman uses mysql database (and let Django with Sqlite3)

- Created a "mailman" database in mysql and granted permissions for IP, localhost and host "" accessing with "mysql -p -u root" and executing (I just put here the last grant)
"GRANT all privileges on mailman.* to 'mailman3'@'' IDENTIFIED BY 'databasepass' WITH GRANT OPTION;"

- installed
pip install postorius
pip install hyperkitty
pip install mailman-hyperkitty
pip install whoosh
"python3 -m django --version" shows 3.0.11 (that's it)

- installed /usr/ports/databases/py-sqlite3

I attached the needed that would be /usr/local/mailman3/ for Django
(Obtained and modified from the previous git run)

su -m mailman3 -c "mkdir /usr/local/mailman3/logs"
su -m mailman3 -c "touch /usr/local/mailman3/logs/mailmansuite.log"

Last thing:
As I installed postfix in /usr/local, mailman cannot find the postmap command to hash de virtual tables, then I did (using bash)
for fic in `ls /usr/local/sbin/post*`; do ln -s $fic /usr/sbin/`basename $fic`; done

- cd /usr/local/mailman3

- su -m mailman3 -c "python3 migrate"
(This creates all the things needed)

- su -m mailman3 -c "python3 collectstatic"

- su -m mailman3 -c "python3 createsuperuser"
(the admin: in my example is

**** at this point you have all the django settings made. Before doing the apache24 part I have to say a couple of things:
In the virtualenv install guide stated you can start an instance of server with a
"python3 runserver". That's good to test the settings... but can confuse you because it's not needed at all if you have a "real server" like apache or nginx serving http. At least it have me missleaded for many days.
The hyperkitty config base path: it took me much frustrating time of confusion as in the guides it stated just as "http://localhost/hyperkitty"... and it not archives any mail at all untill I understand that it have to be as it shows in my config file (well, I changed the access for "mailman3" but it would be preferable if it was noted as, say, "http://localhost/hyperkitty/hiperkitty"
For the apache24 part I decided to use the mod-wsgi (and uswgi binary).
- pip install mod-wsgi
(with "mod_wsgi-express module-config" it shows the conf needed.)

- pip install uwsgi

- Included these lines in the "loadmodule" part of /usr/local/etc/apache24/httpd.conf
LoadModule wsgi_module "/usr/local/lib/python3.7/site-packages/mod_wsgi/server/"
WSGIPythonHome "/usr/local"
WSGIDaemonProcess hyperkitty threads=25 python-path=/usr/local/mailman3 user=mailman3 group=mailman
WSGIProcessGroup hyperkitty
- Included this line in the correct places of my /usr/local/etc/apache24/extra/httpd-vhosts.conf (in the listen 80 and 443 servers)
Include "/usr/local/mailman3/apache24.uwsgi.conf"
(I attach my apache24.uwsgi.conf. Remember I have a Drupal site enabled here)

- service apache24 restart

- initiated the uwsgi with a
/usr/local/bin/uwsgi --ini /usr/local/mailman3/uwsgi.ini &
(beware the "&" backgrounding it)
As I can only attach 5 files I put it here
####### start of /usr/local/mailman3/uwsgi.ini
# uwsgi.ini
# Port on which uwsgi will be listening.
http-socket =
# Move to the directory wher the django files are.
chdir = /usr/local/mailman3/
# Use the wsgi file provided with the django project.
wsgi-file =
# Setup default number of processes and threads per process.
master = true
process = 2
threads = 2
# Drop privielges and don't run as root.
uid = www
gid = www
# Setup the django_q related worker processes.
attach-daemon = ./ qcluster
# Setup the request log.
req-logger = file://usr/local/mailman3/logs/uwsgi.log
# Log cron seperately.
logger = cron file://usr/local/mailman3/logs/uwsgi-cron.log
log-route = cron uwsgi-cron
# Log qcluster commands seperately.
logger = qcluster file://usr/local/mailman3/logs/uwsgi-qcluster.log
log-route = qcluster uwsgi-daemons
# Last log and it logs the rest of the stuff.
logger = file://usr/local/mailman3/logs/uwsgi-error.log
####### end of /usr/local/mailman3/uwsgi.ini

And thats all about mailman 3 configuration. You can start all with two commands
/usr/bin/su -m mailman3 -c "/usr/local/bin/mailman -C /usr/local/mailman3/var/etc/mailman.cfg start"
/usr/local/bin/uwsgi --ini /usr/local/mailman3/uwsgi.ini &
I created a to start, stop and restart all when needed if someone wants it I'll attach it in other post.

Then you have to create the lists in postorious and migrate following the guide in
It works very very well (I migrated all the lists without any problem)

One thing I did is declare as domain "" and as alias "" in the postorious config for adding domains.

You do remember that was jailed, isn't it? And the MX server in DNSs for is That implies that we need to "resend" the mail for the lists from to (as with mailman2 was mercurio the server that manages mailman2 lists).

To do that I use a virtual user table in postfix I named "virtusertable" (like in sendmail). That's why I append in muy destinations in postfix.

Say you have the list one_list@

I created in /usr/local/etc/postfix/virtusertable the following lines:

# Virtual mappings for the domain.
I did not copied here all the lineas needed, but you can get them easily doing a
"cat /usr/local/mailman3/var/data/postfix_vmap >> /usr/local/etc/postfix/virtusertable"
and adding the "" entries for each list.

And don't forget to postmap /usr/local/etc/postfix/virtusertable (and service postfix reload after that)

That sends all email for lists to the correct addresses

To manage that in I configured the local-unbound process, and, for sendmail, configured /etc/mail/mailertable and /etc/mail/virtusertable.

in mercurio:
# local zone
private-domain: ""
local-zone: "" static
local-data: " IN A"
local-data: " IN A"
local-data: " IN MX 10"
local-data-ptr: ""

/etc/mail/mailertable: smtp:[]

... (rest of the hooks for the list)

The reason to do it this way (using a "fake" server) is because I didn't achieve to resend emails in other way as mailertable did not work.

And that's all...


  • potsfix-main.conf
    2.3 KB · Views: 10
  • mailman.conf
    1.9 KB · Views: 8
  • mailman-hyperkitty.conf
    173 bytes · Views: 6
    8.3 KB · Views: 8
  • apache24.uwsgi.conf
    1.4 KB · Views: 6
Last edited: