mlmmj 2.2.2 介绍与选型指南
mlmmj 2.2.2 轻量邮件列表管理器介绍与选型:C 语言零依赖零守护进程架构、文件即配置的控制面、Postfix/Exim/Qmail/Sendmail 四 MTA 对接、与 Mailman 3/Sympa/ezmlm-idx/Listmonk 量化对比,数据于 2026-10-26 联网溯源。
mlmmj 2.2.2 介绍与选型指南
目标:说清 mlmmj 这款轻量级开源邮件列表管理器(Mailing List Manager)是什么、能做什么、适合谁用、与 Mailman 3 / Sympa 等同类软件如何取舍。本篇为认知与选型篇,全部信息通过官方网站、官方仓库与公开渠道联网溯源(查询日期 2026-10-26),不做本地实测;部署实操与命令验证见本专栏后续各篇。
一、环境信息
本篇是软件介绍与选型篇,不涉及本地部署实验,本节记录取证口径与版本基线,便于读者复核数据时效。
- 取证日期:2026-10-26(文中所有版本号、社区数据均为此日实查)
- mlmmj 最新稳定版:2.2.2(官方仓库 Releases 实查,发布于 2026-10-09,变更内容为 "add support for list-id phrase")
- 官方网站:mlmmj.org(首页 "Latest version" 标注为 2.2.1,较仓库 Releases 滞后一个补丁版,以仓库为准)
- 官方代码仓库:
codeberg.org/mlmmj/mlmmj(Codeberg 平台,2021-10-15 创建,MIT 许可证) - 重要更正:不少旧资料(含本篇写作前的任务线索)指向
github.com/mlmmj/mlmmj,经 2026-10-26 实查该 GitHub 地址已返回 404,官方开发平台已收敛到 Codeberg,引用时请以 Codeberg 为准 - 数据来源:Codeberg Releases/API、mlmmj.org 官网与 README.html、Docker Hub 搜索接口、2.2.2 版源码包(tar 包 291781 字节,sha256
7c38047e681738cefc6e4eb2c13355e6d418cdacec20d39ad773167bb40fd047)、Debian 12 软件源
各对比软件版本基线(2026-10-26 实查):
| 软件 | 最新/打包版本 | 运行时依赖 | 许可证 | 定位 |
|---|---|---|---|---|
| mlmmj | 2.2.2(2026-10-09) | 无(C 语言,仅需 libc/iconv) | MIT | 经典讨论组邮件列表 |
| Mailman 3 | 3.3.8(Debian 12 源打包 3.3.8-2~deb12u2) | Python + 数据库 + 独立 Web 组件 | GPLv3 | 功能全量的大型列表套件 |
| Sympa | 6.2.70(Debian 12 源打包 6.2.70~dfsg-2+deb12u1) | Perl + 关系数据库 | GPL | 企业级列表套件 |
| ezmlm-idx | Debian 12 未收录(qmail 生态) | C + qmail MTA | GPL | qmail 原生轻量列表 |
| Listmonk | 稳定线 v6.2.0(同日实查) | Go 单二进制 + PostgreSQL | AGPL-3.0 | Newsletter 群发(非讨论组) |
表格解读:这五款软件同处「邮件列表」大类但并不等价——Mailman 3 与 Sympa 是带数据库、带 Web 管理端的重量级套件;ezmlm-idx 功能与 mlmmj 最接近但深度绑定 qmail;Listmonk 解决的是「营销群发」而非「讨论组往复通信」;mlmmj 的差异化在于零外部依赖、零守护进程、MTA 中立。mlmmj 的社区体量(Codeberg 27 stars / 29 forks)与 Mailman 等不可比,但它已连续 10 个月保持高频发布(详见 7.2 节),属于典型的「小而坚」基础软件。
二、软件概述
mlmmj 的全称是 My Little Mailing List Manager,是一个用 C 语言实现的、精简单依赖的邮件列表管理器。官方 README 开宗明义:这是一个以 ezmlm 为蓝本、复刻其功能特性的项目,但换上了「体面的许可证(MIT)」和「与邮件服务器解耦」两个关键改进。
- 核心能力:围绕一个邮件地址(如
mlmmj-test@lists.example.com)完成订阅/退订管理、邮件分发、存档、摘要(Digest)、自动化退信处理、审批 moderation、主题前缀等经典邮件列表功能;订阅与退订通过给列表名+subscribe@域名、列表名+unsubscribe@域名这类扩展地址发邮件完成,无需注册账号。 - 架构哲学:mlmmj 自身没有常驻守护进程,也没有数据库。收信靠 MTA 的别名管道(alias pipe)触发
mlmmj-receive,发信直接交给本机 MTA 的 SMTP 服务(默认127.0.0.1:25),唯一的周期性维护任务mlmmj-maintd用 cron 或 systemd 定时器拉起即可。官方明确表示它「非常适合资源有限的系统,例如 VPS」。 - MTA 中立:官方文档为 Postfix、Exim4、Qmail、Sendmail 四种 MTA 提供了对接说明(源码包内 README.postfix/README.exim4/README.qmail/README.sendmail),核心对接点是配置「收件人扩展分隔符(recipient delimiter,默认
+)」和别名管道,不依赖任何特定 MTA 的扩展功能。 - 开源协议:MIT(仓库 LICENSE 与源码包 COPYING 实查)。对商业使用、二次开发、内部分发几乎无约束,这是它与 GPL 系 Mailman/Sympa 的显著差异之一。
- 维护现状:官方开发在 Codeberg 进行,仓库 2026-10-22 仍有提交活动;2026 年节奏为每月 1-2 个 release(详见 7.2 节版本节奏)。
💡 技术拓展:「邮件列表管理器(MLM)」与「邮件营销平台」「邮件服务器(MTA)」是三类常被混淆的软件——
类型 代表软件 核心职责 典型交互方式 邮件列表管理器(本文) mlmmj / Mailman 3 / Sympa / ezmlm-idx 管理「讨论组」:多成员互发、往复讨论、订阅关系维护 成员间邮件往复,人人可回帖 邮件营销平台 Listmonk / Keila / phpList 管理「广播」:单方向批量触达、打开率统计 一对多群发,收件人不回帖 邮件服务器(MTA) Postfix / Exim / Stalwart 收发互联网邮件、队列与投递路由 与对方 MX 服务器通信 mlmmj 属于第一类:它依赖一台已配好的 MTA 帮它收发信(自身不发信),解决的是「一组人通过一个地址互相通信」的问题。如果你的需求是给几千订阅者发刊不收回复,选 Listmonk 一类更合适;如果要建技术社区/项目组讨论列表,mlmmj 才是对口工具。
三、核心架构
本节基于 2.2.2 官方源码包与官方 README.html(2026-10-26 取证)描述 mlmmj 的进程模型、数据组织与邮件流。
3.1 组件构成:九个短生命周期命令而非守护进程
mlmmj 不以服务形式常驻,而是拆成一组「按需执行、干完即退」的命令(全部随 2.2.2 源码编译产出,实查 /usr/local/bin/):
| 命令 | 角色 | 触发方式 |
|---|---|---|
mlmmj-receive | 收信入口:从标准输入读取 MTA 管道投来的邮件,落 incoming 队列 | MTA 别名管道 |
mlmmj-process | 列表策略引擎:检查订阅/审批/访问规则,改写头与主题,派发到 queue | 由 receive 链式调用 |
mlmmj-send | 发信出口:与 relayhost(默认 127.0.0.1:25)对话投递给订阅者 | 由 process 链式调用 |
mlmmj-maintd | 唯一的维护进程:退信处理、超时清理、重排队、摘要发送、老版本归档迁移 | cron 或 systemd 定时/常驻 |
mlmmj-list | 查询:列出订阅者/审批人/属主/摘要订阅者等 | 管理员手工 |
mlmmj-sub / mlmmj-unsub | 订阅/退订管理(管理员模式或处理邮件订阅请求) | 管理员手工或邮件触发 |
mlmmj-bounce | 登记退信(+bounces 扩展地址管道调用) | MTA 别名管道 |
mlmmj-make-ml | 建列表脚手架:生成目录树、写别名、可选写 crontab | 管理员手工 |
表格解读:整个系统只有
mlmmj-maintd一个「类服务」组件,且它按官方推荐以 cron 每 2 小时跑一次即可(0 */2 * * * /usr/bin/mlmmj-maintd -F -L /var/spool/mlmmj/列表名,官方 README 原文)。没有 socket 监听、没有内存常驻状态,崩溃面与攻击面都很小,这是它能在低配 VPS 上稳定运行的根源。
3.2 数据组织:一个列表 = 一棵文件树
mlmmj 把每个列表的全部状态放在一个 spool 目录树下(官方 README 以 /var/spool/mlmmj/mlmmj-test 为例,2.2.2 实建目录清单):
/var/spool/mlmmj/mlmmj-test/
├── archive/ # 邮件存档(编号文件;2.x 支持 YYYY/MM 分区布局)
├── bounce/ # 退信记录(VERP 地址回收的退信证据)
├── control/ # 全部配置:扁平文本文件(详见本专栏配置参数详解篇)
├── digesters.d/ # 摘要(Digest)订阅者
├── incoming/ # 收信队列(mlmmj-receive 落点)
├── moderation/ # 待审批邮件
├── nomailsubs.d/ # 不收信仅存档的订阅者
├── queue/ # 派发队列(含 discarded 子目录)
├── requeue/ # 重新排队目录
├── subconf/ # 订阅确认 pending 区
├── subscribers.d/ # 正式订阅者(每地址一个小文件)
├── text/ # 本列表可定制文本(确认信、退订信等)
└── unsubconf/ # 退订确认 pending 区
- 订阅者存储:
subscribers.d/下每个订阅地址一个文件(文件名经哈希/转义),mlmmj-list -L ...就是在读这批文件——没有 SQL 表,备份与迁移等于「复制目录」。 - 配置即文件:
control/目录下的每个文件名对应一个运行时开关(TUNABLES),存在即生效(布尔型)、首行为值(普通型)、每行一条(列表型)。例如创建control/moderated空文件列表即进入审批模式,echo "[mlmmj-test]" > control/prefix即加主题前缀。 - 内置多语言文本:2.2.2 源码包
listtexts/实查含 ast/cs/de/en/fi/fr/gr/it/pt/sk/zh-cn 十一套模板,中文确认信/欢迎信可开箱使用。
3.3 邮件流:一封信从投递到分发
以「alice 向列表投帖、bob 订阅」为例,一封邮件的完整路径如下:
- 收:MTA(如 Postfix)收到发往
mlmmj-test@lists.example.com的邮件,按/etc/aliases中mlmmj-test: "|/usr/local/bin/mlmmj-receive -L /var/spool/mlmmj/mlmmj-test/"把邮件体通过管道交给mlmmj-receive,邮件进入incoming/。 - 审:
mlmmj-process读取 incoming 队列,依次检查:列表地址是否在 To/Cc(tocc)、发件人是否允许发帖(subonlypost/modonlypost/access正则规则)、是否需审批(moderated),然后做头改写——默认注入 RFC 2919/2369 头(List-Id/List-Post/List-Help/List-Subscribe/List-Unsubscribe/List-Owner/Precedence: list,2.0.0 起)、追加主题前缀、追加control/footer页脚,并把收件人展开为订阅者清单,落queue/。 - 发:
mlmmj-send从 queue 取件,逐个(或按verp/maxverprecips分组)与 relayhost 完成 SMTP 会话投递。每个订阅者使用独立 VERP 信封地址(如mlmmj-test+bounces-1-bob=example.com@lists.example.com),退信会被+bounces扩展地址捕获并登记到bounce/。 - 养:
mlmmj-maintd周期运行:解析 bounce 记录、超过bouncelife(默认 5 天)自动退订失效地址、发送到期的摘要邮件、清理过期审批件、把退信邮件重新排队或丢弃。
💡 技术拓展:mlmmj 默认对每个收件人单独发一封信(自身实现 VERP,可精确知道哪个地址退信)。同类投递策略对比——
策略 原理 取舍 逐收件人 + VERP(mlmmj 默认) 每人一封信,信封地址含收件人指纹 退信定位精准,收件多时 SMTP 会话数高 分组 VERP( control/verp填 postfix)借 Postfix XVERP 能力按组投递( maxverprecips默认 100 人/组)减少会话数,退信定位精度由 MTA 保证 单信多收件人(Bcc 广播) 一封信塞全部收件人 最省资源,但无法定位退信且易被判垃圾 mlmmj 的默认选择优先「退信自动化」而非「投递省资源」,这正是它宣称「全自动退信处理(类似 ezmlm)」的实现基础。
四、功能特性
功能清单来自官网功能列表、官方 README 与 1.6.0→2.2.2 各 Release Notes(2026-10-26 实查)归纳。
4.1 订阅与成员管理
- 邮件自订阅/自退订:向
列表名+subscribe@、列表名+unsubscribe@发信触发,默认需回信确认(double opt-in);nosubconfirm可关确认(官方注明 "HANDLE WITH CARE")。 - 订阅变体:支持摘要订阅(
+subscribe+digest,凑批合发)、nomail 订阅(+subscribe+nomail,保留成员身份不收信,常用于「只发言不看信」的 项目成员)。 - 封闭策略:
closedlist(订阅退订全部关闭)、closedlistsub(只关订阅)、submod(订阅需审批)三档可配。 - 名单通知:
notifysub开启后,有人订阅/退订时列表属主会收到通知邮件。
4.2 发帖管控与审批
- 仅订阅者可发帖(
subonlypost):按 From 头校验;非订阅者发帖会收到拒绝信,并附带「回信即同时订阅并释放该帖」的自助通道(subrelease,1.8.0 引入;2.2.0 新增subreleaseall支持一批多信一次性释放,官方注明适合补丁系列场景)。 - 审批制(
moderated+moderators文件):全部帖子进入 moderation 队列等审批,审批人回信同意即放行;modnonsubposts可只审非订阅者的帖子;modreqlife控制待审邮件存活期(默认 7 天)。 - 正则访问控制(
access,见源码 README.access.md):对邮件头按规则表做允许/拒绝匹配,可实现按主题、按来源拦截。 - 仅版主发帖(
modonlypost):公告型列表用,与subonlypost同用时后者优先。
4.3 邮件改写与投递
- 标准列表头:2.x 默认注入 List-Id/List-Post/List-Help/List-Subscribe/List-Unsubscribe/List-Owner/Precedence: list(可用
nolistheaders关闭);2.2.2 新增listidphrase支持List-Id: 短语 <list-id>的展示名。 - 主题前缀与页脚:
control/prefix(如[mlmmj-test])与control/footer两个文件即配即用。 - 自定义头注入与删除:
customheaders/delheaders两个文件控制出入站头;官方在 README 中给出了完整的 DKIM/From 改写配方(用$disarmedfrom$/$posteraddr$变量重写 From、Reply-To 保留原作者),专门解决「外部发件人域名不归你签 DKIM 导致被判垃圾」这一现代邮件列表痛点。 - 投递细节:VERP 全自动退信处理;RFC 1891 DSN 支持;
maxmailsize限收信大小;mimedeny对不想要的 MIME 类型(如 text/html)打标记而非拒收;notmetoo避免发件人收到自己帖子副本;xforwardedto/dara(2.x 新增)为 Gmail 转发识别与 ARC 类重放防护提供专用头。
4.4 存档与检索
- 自动存档:每帖编号存
archive/,2.0.0 起支持archivepartition(YYYY/MM 目录分区,老归档由 maintd 按文件 mtime 自动迁移);noarchive可关。 - 老帖检索:向
列表名+get-N@发信可取回第 N 期存档原帖,subonlyget/noget控制权限。 - 完整重排队:queue/requeue 机制支持把积压邮件按序重放,官方列为功能卖点(Complete requeueing functionality)。
4.5 Web 与管理面
- 官网功能列表列有 "Web interface":经 2.2.2 源码树实查(2026-10-26),核心仓库仅含 contrib/receivestrip 一个可选附件剥离工具,未随附 Web 管理端;该能力指历史贡献的独立 Web 项目,日常管理以 CLI(mlmmj-list/sub/unsub/maintd)+ 邮件指令为主。
- 管理动作双通道:既可用管理员命令(
mlmmj-sub -a直加订阅者),也可走邮件指令流(+subscribe/+help/+get/+owner 扩展地址),后者让「无 shell 权限的列表属主」也能自助管理。
五、快速开始(最小可用示例)
本篇为认知篇,仅给出官方 README 的最小搭建主线以建立直观认识,本节内容为官方形态引用而非本地实测;逐命令的实测安装与回显见本专栏「Debian 12 安装 mlmmj 2.2.2 指南」篇。
5.1 官方四步搭建主线
官方 README.html 给出的完整接入路径(以列表 mlmmj-test@lists.example.com 为例):
- 编译安装:源码包
./configure && make && make install(二进制发行版如 dpkg/rpm/BSD ports 可跳过); - 配分隔符:Postfix 在
/etc/postfix/main.cf加recipient_delimiter = +(Exim/Qmail/Sendmail 各有对应写法,官方 README 逐一给出); - 建列表挂别名:
mlmmj-make-ml生成/var/spool/mlmmj/mlmmj-test目录树并输出别名行mlmmj-test: "|/usr/bin/mlmmj-receive -L /var/spool/mlmmj/mlmmj-test",写入/etc/aliases后执行newaliases;README 特别强调列表目录属主必须是 MTA 写文件的用户(Postfix 场景常见 nobody:nogroup); - 维护任务:cron 每 2 小时跑一次
mlmmj-maintd -F -L /var/spool/mlmmj/mlmmj-test(多列表可用-d /var/spool/mlmmj)。
随后 mlmmj-sub -L /var/spool/mlmmj/mlmmj-test/ -a joe@domain.tld 静默添加第一个订阅者,向列表地址发信即可完成首次分发。
5.2 最小控制面定制
官方 README 给出的三个最常用定制(均只写一个文件):
# 主题前缀:Subject: [mlmmj-test] how are we doing?
echo "[mlmmj-test]" > control/prefix
# 页脚:每封信尾部追加退订指引
# control/footer 写入:To unsubscribe send a mail to mlmmj-test+unsubscribe@lists.domain.net
# 审批制:创建空文件即生效
touch control/moderated
六、适用场景与限制
6.1 适合用 mlmmj 的场景
- 低配 VPS / 小内存主机的项目自建列表:无守护进程、无数据库、C 静态编译产物,几十 MB 内存即可服务多个列表,官方定位即如此。
- 多 MTA 环境或 MTA 可替换的运维体系:不与某个 MTA 的私有特性绑定,Postfix/Exim/Qmail/Sendmail 四套对接文档齐备。
- MIT 许可诉求:需要把列表能力嵌入商业产品/设备固件、或对 GPL 传染性敏感的场景,MIT 是同类中最宽松的。
- 喜欢「文件即配置、目录即数据」的运维风格:备份 = rsync 目录,迁移 = 拷目录 + 改别名,排查 = 直接看文本文件。
6.2 限制与不适用场景
- 无官方 Web 管理界面:订阅者导入、审批、退信处理全走命令行与邮件回信;需要 Web 控制台的团队应直接选 Mailman 3(Postorius/HyperKitty)或 Sympa。
- 无 REST/管理 API:自动化集成只能靠 CLI + 文件系统,或第三方封装项目。
- 存档仅文件级:默认无全文搜索、无在线浏览界面,需要可浏览可检索的公开归档时应搭配 Mailman 3 的 HyperKitty 或第三方归档前端。
- 中文场景需自查文本模板:内置 zh-cn 列表文本可用,但邮件头编码、正文 charset 等细节建议部署后按真实客户端验证(本专栏部署篇做了实测)。
- 小众社区体量:Codeberg 27 stars/29 forks,遇冷门问题主要靠官方邮件列表与源码阅读,没有 Mailman 级别的社区生态。
七、同类选型对比
7.1 五款邮件列表软件横向对比
| 维度 | mlmmj 2.2.2 | Mailman 3 | Sympa | ezmlm-idx | Listmonk |
|---|---|---|---|---|---|
| 实现语言 | C | Python | Perl | C | Go |
| 外部依赖 | 无(libc/iconv) | Python 栈 + 数据库 + Web 服务 | Perl 栈 + 关系数据库 | qmail MTA | PostgreSQL |
| 常驻进程 | 无(maintd 定时跑) | mailman core 等 | sympa 进程族 | 无 | web/api 单进程 |
| Web 管理 | 无 | Postorius + HyperKitty | 内置 WWSympa | 无 | 自带 Web |
| 数据存储 | 文件树 | SQL 数据库 | SQL 数据库 | 文件 | PostgreSQL |
| 订阅确认 | 邮件 double opt-in | 邮件 + Web | 邮件 + Web | 邮件 | 邮件/Web 表单 |
| 退信处理 | VERP 全自动(+bounces 链) | 内建退信引擎 | 内建退信引擎 | VERP(qmail) | 硬退/软退标记 |
| 讨论组/群发 | 讨论组 | 讨论组 | 讨论组 | 讨论组 | 群发广播 |
| 许可证 | MIT | GPLv3 | GPL | GPL | AGPL-3.0 |
| Debian 12 打包 | 1.3.0-4(滞后两代) | 3.3.8-2~deb12u2 | 6.2.70~dfsg-2+deb12u1 | 未收录 | 未收录(Go 单二进制) |
表格解读:「有没有数据库、有没有 Web」是第一分水岭——需要自助门户、公开归档、大规模运营选 Mailman 3 或 Sympa;「MTA 绑定」是第二分水岭——qmail 环境里 ezmlm-idx 最顺手,其余环境 mlmmj 的 MTA 中立性更优;Listmonk 与四者不是同一物种,仅在「发刊不讨论」需求下作为替代考虑。mlmmj 在 Debian 12 源里打包的是 1.3.0-4(上游 2016 年前后老版本),与 2.2.2 相差两个大版本,生产部署建议按本专栏安装篇用源码编译 2.2.x 或评估发行版新包。
7.2 版本节奏与社区活跃度(2026-10-26 实查)
mlmmj 近期 Release 线(Codeberg Releases 实查):
| 版本 | 发布日期 | 关键变更 |
|---|---|---|
| 1.6.0 | 2025-06-13 | customheaders 前缀去空格、$bouncenumbers$ 探针扩展 |
| 1.7.0 | 2026-01-11 | 新增 autosubscribe、selfmoderate 功能 |
| 1.7.1 | 2026-02-13 | 修老 GCC 构建、+owner 崩溃、投递失败丢信、内存/FD 泄漏清理 |
| 1.8.0 | 2026-03-14 | 新增 subrelease(回信即订阅并释放被拒帖) |
| 2.0.0 | 2026-04-23 | 里程碑:默认生成 RFC 2919/2369 全套 List-* 头、归档 YYYY/MM 分区 |
| 2.0.1 | 2026-04-23 | configure --mandir 等构建修复 |
| 2.1.0 | 2026-06-12 | 新增 $disarmedfrom$ 变量(DKIM/From 改写配方核心) |
| 2.2.0 | 2026-09-24 | 新增 subreleaseall 批量释放待审帖 |
| 2.2.1 | 2026-10-09 | 清理死代码、customheaders 变量展开增强 |
| 2.2.2 | 2026-10-09 | List-Id 支持 phrase 展示名 |
解读:10 个月 9 个 release、2.0 大版本重写头生成逻辑,说明项目处于活跃维护期且维护者对现代投递合规(DKIM/DMARC、RFC 头)持续投入;但社区盘子小(Codeberg 27 stars/29 forks/12 watchers),没有发行版新包跟进(Debian 12 停在 1.3.0),升级主要靠源码自编译——这决定了选 mlmmj 的团队最好具备基本的 C 构建与 MTA 运维能力。
7.3 选型建议
- 如果你要的是给开源项目/小团队建低资源讨论组,且团队有 MTA 运维能力 → mlmmj 是最轻、许可最松的答案。
- 如果你要的是几百到几十万成员、需要 Web 门户/自助管理/公开可检索归档 → Mailman 3(生态最全)或 Sympa(企业功能如 LDAP 同步更成熟)。
- 如果你的服务器是 qmail 且偏好极简 → ezmlm-idx。
- 如果你的需求其实是发 Newsletter/产品通告而非讨论组 → 走 Listmonk/Keila 一类营销平台,mlmmj 的「回信给全组」模型反而是负担。
八、参考链接
- 官方网站:https://mlmmj.org/
- 官方文档(README 全文):https://mlmmj.org/README.html
- 官方代码仓库(Codeberg):https://codeberg.org/mlmmj/mlmmj
- 版本发布页:https://codeberg.org/mlmmj/mlmmj/releases
- MIT 许可证文本:https://mlmmj.org/LICENSE.html
- 支持与求助渠道:https://mlmmj.org/support.html
- Docker Hub 第三方镜像检索证据(无官方镜像):https://hub.docker.com/search?q=mlmmj
- 本专栏系列文章: