Hansen's ink

Back

一、整体架构说明#

Postfix  -->  Mailman Core  -->  HyperKitty (Archiver)
                  |
                  +--> REST API (8001)
                  |
                  +--> Postorius (Web 管理)
css
  • Mailman Core:负责邮件列表逻辑、投递、归档调度
  • Postorius:列表管理 Web UI
  • HyperKitty:邮件归档与 Web 展示
  • Mailman-Web:Django 项目,包含 Postorius + HyperKitty
  • Nginx:对外 Web 入口(8090)

关键端口规划

服务端口说明
Mailman REST8001仅本机访问
Mailman Web8000Gunicorn 内部
Nginx Web8090对外访问

二、Mailman Core 安装#

2.1 安装系统依赖(Rocky Linux 10)#

sudo dnf update -y
sudo dnf install -y \
  git gcc make \
  python3 python3-devel python3-pip \
  libffi-devel openssl-devel \
  postfix \
  mariadb-connector-c-devel \
  nginx
bash

说明:Mailman Core/ Web 都是 Python 项目;生产环境强烈建议用独立虚拟环境专用系统用户

2.2 创建专用用户与目录#

sudo useradd -r -m -d /opt/mailman -s /sbin/nologin mailman
sudo mkdir -p /opt/mailman/{venv,core,web,var,logs,etc}
sudo chown -R mailman: mailman /opt/mailman
shell

2.3 建虚拟环境#

sudo -u mailman python3 -m venv /opt/mailman/venv
sudo -u mailman /opt/mailman/venv/bin/pip install -U pip wheel setuptools
bash

clone 仓库再安装

sudo -u mailman git clone https://gitlab.com/mailman/mailman.git /opt/mailman/core
sudo -u mailman /opt/mailman/venv/bin/pip install -e /opt/mailman/core
bash

Mailman Core 的安装与运行结构、命令行(mailman start|stop|shell)以官方安装文档为基准。


2.4 配置 Mailman Core(mailman. Cfg)#

把主配置放到 /opt/mailman/etc/mailman.cfg(自建目录更清晰)。 最终配置为:

此处应注意 var_dir: /opt/mailman/var ,设置为本地默认路径,避免路径错误。另外,直接运行 mailman 3 不要在 root 目录下,可能会是程序将当前路径加载进程序,导致权限问题或其他问题。

三、Mailman 3 与原有邮件服务器协同工作#

Postfix / Dovecot 基于虚拟用户使用

3.1 整体架构#

虚拟用户环境 下,正确的职责划分是:

外部邮件

Postfix
   ├─ 普通邮箱(user@example.com) → virtual_mailbox_maps → Dovecot
   └─ 列表邮箱(list@lists.example.com)
         → transport_maps → lmtp:127.0.0.1:8024 → Mailman Core
css
  • transport_maps 把“列表域 / 列表地址”优先交给 Mailman
  • Mailman 自动生成 Postfix maps
  • Postfix 只“引用”这些 map,不自己维护列表

3.2 Mailman 3 生成 Postfix map#

Mailman Core 在运行后,会在它的 var_dir 下生成 Postfix 可用的映射文件

在Mailman 侧:启用 Postfix MTA 接口#

[mta]
incoming: mailman.mta.postfix.LMTP
outgoing: mailman.mta.deliver.deliver
# Postfix 投递给 Mailman 用 LMTP(推荐 8024 之类高端口)
lmtp_host: 127.0.0.1
lmtp_port: 8024

# Mailman 发信走 Postfix(本机 25)
smtp_host: 127.0.0.1
smtp_port: 25
ini

然后确认 Mailman 正常运行后,生成了 map:

ls -l /opt/mailman/var/data/

total 72
-rw-rw----. 1 mailman mailman   349 Feb  3 10:42 postfix_domains
-rw-r-----. 1 mailman mailman 32768 Feb  3 10:42 postfix_domains.lmdb
-rw-rw----. 1 mailman mailman   988 Feb  3 10:42 postfix_lmtp
-rw-r-----. 1 mailman mailman 32768 Feb  3 10:42 postfix_lmtp.lmdb
bash

如果这个目录不存在,说明 Mailman 还没真正启动成功。 也可以指定生成 map 文件:

sudo -u mailman -H /opt/mailman/venv/bin/mailman -C /opt/mailman/etc/mailman.cfg aliases
bash

Postfix 侧:正确引用 Mailman 生成的 map#

在虚拟用户场景下:

  • virtual_mailbox_maps:只管真实邮箱
  • transport_maps优先级更高,用来“劫持”列表地址
  • local_recipient_maps:要么关闭,要么确保不拒绝列表地址 修改 Postfix /etc/postfix/main.cf 推荐配置
# for mailman
local_recipient_maps =                                                                 lmdb:/opt/mailman/var/data/postfix_lmtp,
	$alias_maps,
    lmdb:/etc/postfix/virtual-mailbox

relay_domains =                                                                        lmdb:/opt/mailman/var/data/postfix_domains
transport_maps =                                                                       lmdb:/opt/mailman/var/data/postfix_lmtp
ini

在 Rocky/RHEL 系现在更推荐 lmdb:,而不是 hash:(db3/bdb 经常被拆包或默认不带)

生成 map#

Mailman 生成的是 文本文件,Postfix 用时必须 postmap:

sudo postmap lmdb:/opt/mailman/var/data/postfix_domains
sudo postmap lmdb:/opt/mailman/var/data/postfix_lmtp
bash

验证 Postfix transport 是否命中:

postmap -q lists.example.com /opt/mailman/var/data/postfix_domains
bash

也可查看日志:

tail -f /var/log/maillog
bash

systemd 管理 Mailman Core#

创建 systemd unit:/etc/systemd/system/mailman.service

重载并重启:

sudo systemctl daemon-reload
sudo systemctl reset-failed mailman
sudo systemctl restart mailman
sudo systemctl status mailman --no-pager
bash

四、部署 Mailman Web#

Mailman Web 实际是一个 Django 项目,由三部分组成:

┌──────────────┐
│  Postorius   │  ← 列表管理 UI
├──────────────┤
│  HyperKitty  │  ← 邮件归档 UI
├──────────────┤
mailman-web  │  ← Django 项目本体
└──────┬───────┘
       │ REST

┌──────────────────┐
│   Mailman Core   │  ← 你已经跑起来了
└──────────────────┘
css

4.1 安装 web#

直接复用 /opt/mailman/venv,这样版本和依赖最干净。

sudo -u mailman -H /opt/mailman/venv/bin/pip install -U \
  mailman-web \
  postorius \
  hyperkitty
# 验证
sudo -u mailman -H /opt/mailman/venv/bin/pip show mailman-web postorius hyperkitty
plaintext

创建 mailman-web Django 项目配置 1、 创建配置目录

sudo mkdir -p /opt/mailman/web
sudo chown -R mailman:mailman /opt/mailman/web

sudo mkdir -p /opt/mailman/web/logs
sudo chown -R mailman:mailman /opt/mailman/web/logs
sudo chmod 750 /opt/mailman/web/logs

sudo mkdir -p /opt/mailman/var/logs
sudo chown -R mailman:mailman /opt/mailman/var/logs
sudo chmod 750 /opt/mailman/var/logs
bash

2、生成默认 Django 配置 /opt/mailman/web/settings.py

3、PostgreSQL 创建 mailmanweb 数据库(如果还没建)

sudo -u postgres psql -c "CREATE DATABASE mailmanweb OWNER mailman;"
plaintext

4、 初始化 Django(迁移 + 管理员 + 静态文件) 后面所有命令都用同一个环境变量:

export MAILMAN_WEB_CONFIG=/opt/mailman/web/settings.py
bash

迁移数据库

sudo -u mailman -H env MAILMAN_WEB_CONFIG=/opt/mailman/web/settings.py \
  /opt/mailman/venv/bin/mailman-web migrate
bash

创建 Web 超级管理员

sudo -u mailman -H env MAILMAN_WEB_CONFIG=/opt/mailman/web/settings.py \
  /opt/mailman/venv/bin/mailman-web createsuperuser
bash

收集静态文件 :

sudo -u mailman -H \
  PYTHONPATH=/opt/mailman/web \
  DJANGO_SETTINGS_MODULE=settings \
  /opt/mailman/venv/bin/django-admin collectstatic
bash

尝试运行:

sudo -u mailman -H \
  PYTHONPATH=/opt/mailman/web \
  DJANGO_SETTINGS_MODULE=settings \
  /opt/mailman/venv/bin/django-admin runserver 127.0.0.1:8000
bash

5、用 gunicorn 跑 mailman-web(systemd) 创建 systemd 服务文件 /etc/systemd/system/mailman-web.service

启动:

sudo systemctl daemon-reload
sudo systemctl enable --now mailman-web
systemctl status mailman-web --no-pager
bash

4.2 Nginx 反向代理#

创建 /etc/nginx/conf.d/mailman-web.conf

重启 nginx :

sudo nginx -t
sudo systemctl reload nginx
bash

4 .3 HyperKitty 与 mailman 互通#

Mailman 的配置文件需要配置 HyperKitty 信息,/opt/mailman/etc/mailman.cfg

[archiver.hyperkitty]
class: mailman_hyperkitty.Archiver
enable: yes
configuration: /opt/mailman/etc/hyperkitty.cfg
ini

其中,/opt/mailman/etc/hyperkitty.cfg 中内容为:

[general]
base_url: http://127.0.0.1:8090/hyperkitty/
api_key: 59ebff6c-3f00-4991-8125-e3a3b28907c7
ini

Django 也需配置 /opt/mailman/web/settings.py

# 归档页面 URL
HYPERKITTY_URL = "http://127.0.0.1/hyperkitty/"
#HYPERKITTY_API_KEY = "59ebff6c-3f00-4991-8125-e3a3b28907c7"

MAILMAN_ARCHIVER_KEY = "59ebff6c-3f00-4991-8125-e3a3b28907c7"
python
Mailman3 安装与部署
https://astro-pure.js.org/blog/mailserver/mailman3-install
Author Hansen W.
Published at February 19, 2026
Comment seems to stuck. Try to refresh?✨