Mailing-Lists
- Introduction
- Requirements
- Deployment
- Customization
- Automation using the Python Console
- Known problems and limitations
- Resources
Introduction
This documentation focuses on the deployment of the Mailman 3 suite (core daemon, Hyperkitty and Postorius UIs).
Requirements
Mailman 3 requires (respectively for a small instance, a big one like lists.ovirt.org, and a huge one like lists.jboss.org (estimated, WIP)):
- RAM: at least 2GB / 9GB / 17GB
- CPU: 1/4/4
- storage (add some more to grow):
- database: ~50-100MB / ~5GB / ~15GB
- mailman data: ~10-50MB / 2-3GB / 150M-5GB
- search index: 10-100MB / ~25GB / ~60-90GB
- Mailman 2 archives (for migration and to keep the old URLs alive, thus permanent): ~100MB / 10GB / ~150GB
- swap: 1GB should be enough
Deployment
Using the mailing-lists-server
super-role it is very easy to deploy a ML instance:
- hosts: lists.example.com
roles:
- role: swap_file
size: 1G
path: /var/swap
- role: mailing-lists-server
display_name: "The Open Data Hub List Archives"
domain: lists.example.com
admin_users:
- duck
- misc
mail_aliases:
root: "{{ ['root'] + comminfra_tech_emails }}"
listmaster: root
use_simple_tls: True
whitelist_clients:
- redhat.com
tags: mailinglists
Then if you want to migration from Mailman 2 then please follow the Migration Notes. You can add this to the playbook to make the old archives available at the old URLs:
- name: "Configure web access to old ML archives"
copy:
src: "{{ data_dir }}/old_ml_archives.conf"
dest: "{{ _vhost_confdir }}/"
owner: root
group: root
mode: 0644
notify: reload httpd
With old_ml_archives.conf
containing:
# Ansible managed
Alias "/pipermail" "/srv/data/mailman2/archives/public"
<Directory "/srv/data/mailman2/archives/public">
Require all granted
Options Indexes SymLinksIfOwnerMatch
IndexIgnore .??*
IndexOptions FancyIndexing HTMLTable IconsAreLinks SuppressSize SuppressDescription NameWidth=*
</Directory>
RedirectMatch ^/mailman/listinfo/(.*) /archives/list/$1@lists.example.com/
RedirectMatch ^/mailman.* /archives/
Log into the UI and create your admin account, then rerun the playbook to get elevated to administrator of the instance (you need to have set admin_users
properly with your user handle, but that can be done now).
Customization
Email Templates
New templates can be installed in /var/lib/mailman3/templates/
in the site/<lang>
subdirectory for global templates and lists/<list-name>/<lang>
subdirectory for per-lists templates. The list-name
is the list address with the @
replaced by a dot.
Custom Assets
Custom logo, images, favicon or CSS can be stored in {{ webapp_path }}/static-extra/
.
Custom Content
Hyperkitty pages can be customized by overriding Django templates into {{ webapp_path }}/templates/hyperkitty/
.
For example the navbar-brand.html
template can be overriden to add you own logo or alter the top bar visual:
{% load static from staticfiles %}
<a class="navbar-brand" href="{% url 'hk_root' %}" title="{{ site_name }}">
<img alt="{{ site_name|title }}" src="{% static 'my_custom_logo.png' %}" style="float: left; margin-right: 30px; height: 60px; padding: 0; margin-top: -20px;" />
{{ site_name }}
</a>
It is possible to add specific headers, which can be used to inject your specific theme CSS, by overriding headers.html
:
{% load static from staticfiles %}
<link rel="stylesheet" href="{% static 'my_custom_theme.css' %}" type="text/css" media="all" >
Automation using the Python Console
These are examples to show what’s possible to make mass modifications without editing each list one by one in the UI.
These scripts needs to be run under Python 2 and require the following extra dependencies:
- python-configparser (to be able to parse the configuration)
Modification of list parameters
Method to display and modify a parameter
This script first display the original value of the key
for each list and then modify the value
:
import configparser
config = configparser.ConfigParser()
config.read('/etc/mailman.cfg')
from mailmanclient import Client
client = Client('http://localhost:8001/3.1', config['webservice']['admin_user'], config['webservice']['admin_pass'])
d = client.get_domain('example.com')
for ml in d.lists:
print("{}: {}".format(ml.list_name, ml.settings['key']))
for ml in d.lists:
ml.settings['key'] = 'value'
ml.settings.save()
Useful parameters not available in the UI (at least in our version)
- Adding DMARC mitigation: update
dmarc_mitigate_action
tomunge_from
-
Get rid ofin our version it is not yet exposed in the API, instead use the following SQL statement on theUncaught bounce notification
messages: updateforward_unrecognized_bounces_to
to0
mailman
database:UPDATE mailinglist SET forward_unrecognized_bounces_to=0;
Set List to be moderated by default
This script ensures that all new list members are moderated, but allows existing members to skip the moderation:
import configparser
config = configparser.ConfigParser()
config.read('/etc/mailman.cfg')
from mailmanclient import Client
client = Client('http://localhost:8001/3.1', config['webservice']['admin_user'], config['webservice']['admin_pass'])
ml = client.get_list('infra@ovirt.org')
print(ml.settings['default_member_action'])
# ensure previous members are not moderated, unless explicitely set
for mem in ml.members:
if not mem.moderation_action:
mem.moderation_action = 'defer'
mem.save()
# change the ML default processing for members to moderation
ml.settings['default_member_action'] = 'hold'
ml.settings.save()
List moderators can use this setting to filter out trolls. Once a person has posted several valuable messages then the moderators can disable moderation for this specific user in the UI.
Known problems and limitations
Hyperkitty is not at the latest version
Previously the packaging was kindly done my Aurelien Bompard, but he now lacks time to maintain it. We decided to take over and try to help push the various bits to be one day available in Fedora and later RHEL 9.
We ported the latest version of Mailman 3 Core (the server routing the messages) for EL7 to get various fixes but the UI is blocked at and older version as it requires a more recent Python version, many many dependencies, and various patches. Aside from fixes we have no plan to deliver newer version for EL7 (read below).
We are currently working on packaging the lastest version of the whole suite into Fedora as well as EPEL8. The goal is to move our work into official repositories.
Admin settings
A few list and site-wide settings are not yet available in the web UI (global bans, maybe others).
Member options appear not visible when the user has not made a choice and global defaults are in use.
Cannot delete list archive
Deleting a list removes the configuration in the routing daemon, thus it is not possible anymore to post, and the archives are kept (read-only). This is usually what most people want but sometimes you made a mistake or wish to get rid of some tests but unfortunately it is not possible to remove archives in the web UI.
With shell access it is possible though, with this procedure:
cd /var/www/mailman/config/
export DJANGO_SETTINGS_MODULE=settings
python
import django
django.setup()
from hyperkitty.models import MailingList
ml = MailingList.objects.get(name="<list-email>")
ml.delete()
Resources
Documentation:
Packaging:
- RPM packaging sources
- current production-ready RPM repository with latest Mailman 3.2 core daemon but slightly older UI (targeted at EL7)
- development RPM repository to work on latest Mailman suite supporting API 3.1 (targeted on EL8 and Fedora)
- (abandonned in favor of EL8 + Fedora above) development RPM repository to work on latest Mailman suite (targeted on EL7 and Fedora)
Ansible roles:
- Mailman 3 role (depends on other roles like PostgreSQL)
- Mailing-Lists role (depends on the Mailman 3 role as well as Postfix and anti-spam related roles)