mailman/README.md

84 lines
3.6 KiB
Markdown

# mailman
The site-wide antispam defaults are deliberately empty:
```yaml
mailman_antispam_header_checks: []
mailman_antispam_chain_behaviour: discard
```
Mailing-list owners can manage list-specific header matches and select their
action (`accept`, `discard`, `hold`, or `reject`) from Postorius. The global
chain is used only when a matching rule has no explicit action.
Existing lists without any header matches can be initialized through the
Mailman database model by enabling the optional seed operation:
```yaml
mailman_seed_empty_list_header_matches: true
mailman_empty_list_header_matches:
- header: 'X-Spam-Flag'
pattern: '^YES$'
action: 'discard'
```
The operation is idempotent. A list is modified only when its header-match
collection is empty; lists with one or more existing rules are left untouched.
## Verified weekly restart
The optional weekly restart performs separate stop and start operations. It
waits for systemd, `mailman status`, and the configured LMTP listener to confirm
that Mailman has stopped before starting it. It then requires the master and
the LMTP port to become available before considering startup successful:
```yaml
mailman_enable_weekly_verified_restart: true
mailman_weekly_verified_restart_on_calendar: 'Sun *-*-* 04:00:00'
mailman_service_stop_timeout: 30
mailman_weekly_verified_restart_stop_timeout: 120
mailman_weekly_verified_restart_start_timeout: 120
```
The timer is deliberately not persistent, so a missed run is not executed
immediately after a server boot. Failures are recorded by systemd in the
`mailman-verified-restart.service` journal.
The managed `mailman.service` uses `KillMode=control-group` and an explicit
`TimeoutStopSec`. If Mailman's own stop command hangs, systemd terminates the
whole service cgroup and removes a stale master PID file. The weekly job still
verifies the real stopped state and does not start a second instance until the
master and LMTP listener are gone.
The normal role execution also waits for the configured LMTP port and fails if
the listener does not become available after starting or restarting Mailman.
## Legacy HyperKitty compatibility fixes
The optional compatibility patcher addresses three failures observed with the
legacy Python 3.6 web stack: malformed `From`/`Subject` headers, nested
`message/rfc822` parts without `Content-Transfer-Encoding`, and unreadable
gettext catalogs. It also normalizes non-ASCII sender addresses and backports
the byte-oriented delivery used by newer `mailman-hyperkitty` releases, so
surrogate-escaped message bytes do not pass through Requests as Unicode text.
Enable it only for the known package versions:
```yaml
mailman_enable_legacy_hyperkitty_compatibility_patches: true
mailman_legacy_hyperkitty_version: '1.3.3'
mailman_legacy_django_mailman3_version: '1.3.4'
mailman_legacy_mailman_hyperkitty_version: '1.1.0'
```
The Python source patches are idempotent, compiled before any file is replaced,
and installed atomically. The task fails without changing any source file if
the installed versions or expected source fragments do not match. Invalid
`django_extensions` `.mo` files are preserved beside the original name with a
`.disabled-by-ansible` suffix, allowing Django to fall back to another locale.
The uWSGI and Mailman services are restarted only when a source file or catalog
actually changes. After restarting Mailman, the handler requires the configured
LMTP listener to become available.
Disable this option before upgrading HyperKitty, django-mailman3, or
mailman-hyperkitty, then review whether the compatibility patches are still
needed with the new versions.