DragonFly MTA v0.14 常用 CLI 命令详解
DragonFly MTA v0.14 常用 CLI 命令详解:dma 与 sendmail/mailq/newaliases 三个马甲的注入、-t/-i/-f、mailq 查队、-q 冲刷、-bq/-D 调试、退出码,以及「队列清不掉」锁排查三步定位法全回显实录。
DragonFly MTA v0.14 常用 CLI 命令详解
本文为命令篇。dma 没有 daemon 就没有 service 命令,全部运维动作落在四个可执行名字上:
dma本体与它的三个马甲sendmail/mailq/newaliases。本文逐条给出实测命令与逐行回显(实验机 Ubuntu 22.04,deb 0.13-1build1 与源码 v0.14 并存验证),实测日期 2026-10-25。
一、命令地图
| 命令 | 实际身份 | 用途 |
|---|---|---|
sendmail | -> dma 的符号链接 | 注入邮件(兼容接口,绝大多数场景只用它) |
mailq | -> dma 的符号链接 | 查看队列(等价 dma -bp) |
newaliases | -> dma 的符号链接 | 重建别名(实际是重读校验,dma 现读现投) |
dma | 本体 | 注入 + 队列操作 + 调试全功能 |
dma-mbox-create | setuid 助手 | 本地投递时以收件人身份开箱,不经人工调用 |
链接关系实测(安装篇已验证,此处回顾):
$ ls -la /usr/bin/mailq /usr/bin/newaliases /usr/sbin/sendmail
lrwxrwxrwx 1 root root 11 Nov 23 2021 /usr/bin/mailq -> ../sbin/dma
lrwxrwxrwx 1 root root 11 Nov 23 2021 /usr/bin/newaliases -> ../sbin/dma
lrwxrwxrwx 1 root root 3 Nov 23 2021 /usr/sbin/sendmail -> dma
二、注入邮件:sendmail 的两种姿势
2.1 姿势一:收件人放命令行(推荐)
printf 'From: root@mail.example.net\nTo: ops@example.com\nSubject: relay-test\n\nbody\n' | sendmail ops@example.com
命令行上的收件人就是信封收件人,报文头域里的 To: 只是展示。信封发件人默认取 发起用户@MAILNAME 域(实测中继侧收到 MAIL FROM: root@mail.example.net)。
2.2 姿势二:-t 从头域解析收件人
printf 'From: root@mail.example.net\nTo: ops@example.com\nCc: cc@example.com\nBcc: bcc@example.com\nSubject: t-flag-test\n\nbody\n' | dma -t
手册语义:-t 让 dma 解析报文的 To:、Cc:、Bcc: 三个头作为收件人,且无论是否加 -t,Bcc: 头都会从报文中删除——这是隐私保护的关键行为。适合收件人列表由上游程序动态生成的场景。
2.3 与文件/管道配合:-i 忽略孤立点
dma -i ops@example.com < 报文文件
手册语义:SMTP 协议里单独一个 . 表示报文结束,从文件读取报文时若正文里恰有孤立的点行,会被截断;-i(-oi 等价)忽略之。管道注入时同理。
三、查队列:mailq / dma -bp
队列有货时(实测,向不可达中继发信后):
# mailq
ID : 4a496d.58a74b63d200
From : root@mail.example.net
To : ops@example.com
队列清空时:
# mailq
Mail queue is empty
ID 就是 spool 目录里 Q/M 文件对的后缀(Q4a496d.58a74b63d200、M4a496d.58a74b63d200),两套输出可互相印证。
四、冲刷队列:dma -q
-q 处理队列中所有滞留邮件(可选参数被忽略,为 sendmail 兼容而留)。实测它会把正在处理的条目打印出来:
# dma -q
ID : 4a496d.58a74b63d200
From : root@mail.example.net
To : ops@example.com
成功后队列归零(Mail queue is empty),中继侧收到信。发行版包默认带每 5 分钟的 cron:
# cat /etc/cron.d/dma
# Flush the dma mail transfer agent's queue every five minutes.
#
*/5 * * * * root [ -x /usr/sbin/dma ] && /usr/sbin/dma -q
一个实测过的坑:-q 不能与发信混在一条命令里——
# dma -q -f root@mail.example.net ops@example.com
dma: sending mail and queue operations are mutually exclusive
-q 与注入互斥,必须分开执行。
五、只入队不投递:dma -bq 与 DEFER
dma -bq 收件人:本次注入只落队列、不做任何投递尝试(命令级);- 配置
DEFER:所有注入都只入队(主机级),统一靠dma -q冲刷。
两者配合 cron 定时冲刷,就是手册推荐给「非永久在线机器」的攒批模式。-b 的其余 mode(除 -bp/-bq)被忽略,同样是 sendmail 兼容设计。
六、发件人控制:-f / -r / EMAIL
三个来源按优先级:MASQUERADE > -f(-r 等价)> EMAIL > 默认。EMAIL 环境变量实测(配置篇四级优先链的第三级):
EMAIL=alerts@example.net sh -c "printf 'Subject: email-env-test\n\nvia EMAIL env\n' | dma ops@example.com"
中继侧对拍结果:
[01:17:16] MAIL FROM: alerts@example.net
而同机 root 的默认注入是 MAIL FROM: root@mail.example.net——EMAIL 生效无疑。-f 与 MASQUERADE 的覆盖关系同手册,验收方法一致:注入后在中继侧看 MAIL FROM 实际值。
七、调试:-D 前台运行与 syslog 定位
-D 让 dma 不转入后台、错误直接打到当前终端,配合 -q 就是队列冲刷的前台模式:
# dma -Dq
(正常时静默,exit 0;对端报错时会直接回显 SMTP 错误)
更完整的轨迹在 syslog(装了 rsyslog 的主机上是 /var/log/mail.log)。实测一封「STARTTLS + AUTH LOGIN 外发成功」信的完整链路原文:
Oct 25 01:17:00 mail01 dma[4a6c2b]: new mail from user=root uid=8 envelope_from=<root@mail.example.net>
Oct 25 01:17:00 mail01 dma[4a6c2b]: mail to=<ops@example.com> queued as 4a6c2b.5889c3198200
Oct 25 01:17:00 mail01 dma[4a6c2b.5889c3198200]: <ops@example.com> trying delivery
Oct 25 01:17:00 mail01 dma[4a6c2b.5889c3198200]: using smarthost (smtp.relay.internal:8025)
Oct 25 01:17:00 mail01 dma[4a6c2b.5889c3198200]: trying remote delivery to smtp.relay.internal [10.89.56.2] pref 0
Oct 25 01:17:00 mail01 dma[4a6c2b.5889c3198200]: Server greeting successfully completed
Oct 25 01:17:00 mail01 dma[4a6c2b.5889c3198200]: Server supports STARTTLS
Oct 25 01:17:00 mail01 dma[4a6c2b.5889c3198200]: Server supports LOGIN authentication
Oct 25 01:17:00 mail01 dma[4a6c2b.5889c3198200]: SSL initialization successful
Oct 25 01:17:00 mail01 dma[4a6c2b.5889c3198200]: using SMTP authentication for user admin
Oct 25 01:17:00 mail01 dma[4a6c2b.5889c3198200]: <ops@example.com> delivery successful
日志的两段 ID 规律:dma[短ID] 是注入阶段,dma[短ID.队列ID] 是投递阶段,按队列 ID 串联即可还原一封邮件的一生。
八、sendmail 兼容旗标速览
手册明确的兼容项,调用方无感但值得知道:
-A c:sendmail 兼容占位(忽略);-L tag:自定义 syslog 标识符(兼容 sendmail 的-L);-O:占位(忽略);-o i等价-i,其余-o参数忽略;-bp、-bq见上文;-q可带参数但被忽略;-r sender等价-f sender。
九、退出码与错误信息
实测采集到的两种:
# dma -Z
invalid argument: `-Z'
(exit 64 —— 用法错误)
注入与队列操作互斥时(见第四节)同样立即报错退出。mailq 空队列、newaliases 成功等正常路径 exit 0。手册约定错误路径下 dma 不会吞掉报文——失败邮件要么留在队列、要么退回 postmaster,二选一。
十、排障实录:队列清不掉的三步定位法
真实复现 + 完整回显,按顺序执行即可解决「dma -q 无声无息但队列不减」的经典问题。
第一步:确认队列还在,且 -q 「假装」成功了
# dma -Dq
(无任何输出)
echo exit=$? → exit=0
# mailq
ID : 4a496d.58a74b63d200
From : root@mail.example.net
To : ops@example.com
退出码 0、无报错、队列原封不动——这不是 dma 的 bug,是队列文件锁。
第二步:找出持锁的残留投递进程
dma 投递失败(尤其对端不可达、TCP connect 挂起)时,后台投递子进程可能存活数分钟并持有 Q 文件的 flock;此后所有 -q 都会静默跳过这封邮件。进程表里一眼可见:
# ps -ef | grep dma | grep -v grep
mail 4285 1 0 01:23 ? 00:00:00 dma -f root@mail.example.net ops@example.com
第三步:清掉持锁进程,重试冲刷
# kill -9 4285
# dma -q
(静默完成)
# mailq
Mail queue is empty
对端中继侧确认信件补投到位(该测试信在接收端计数 +1,实测验证)。整个定位过程不需要重启任何东西——dma 本来就没有可重启的东西。
延伸:如何避免复现
- 给 SMARTHOST 配置一个会快速拒绝(RST)而不是黑洞的地址;
- 对不可达目标,宁可让它进队列等 cron 冲刷,也不要在脚本里手动循环重试;
- 长时间挂起的 connect 本质是网络问题,防火墙 REJECT 与 DROP 的行为差异在这里会直接变成「队列卡 1 分钟还是卡 5 分钟」。
十一、命令速查卡
| 想做什么 | 命令 |
|---|---|
| 发一封邮件 | printf '...' | sendmail 收件人 |
| 收件人从头域来 | ... | dma -t |
| 正文含孤立点 | ... | dma -i 收件人 |
| 指定信封发件人 | dma -f 地址 收件人 |
| 只入队不投递 | dma -bq 收件人 |
| 查队列 | mailq(= dma -bp) |
| 立即冲刷 | dma -q |
| 前台调试冲刷 | dma -Dq |
| 别名生效 | newaliases |
| 看投递轨迹 | tail /var/log/mail.log |
| 自定义日志标识 | dma -L 标识 ... |
参考来源(查询日期:2026-10-25)
- dma(8) 手册 SYNOPSIS/DESCRIPTION 全节(仓库
dma.8,.Dd February 15, 2026):https://raw.githubusercontent.com/corecode/dma/master/dma.8 - 全部回显采集自实验机实测(Ubuntu 22.04 / dma 0.13-1build1 / 源码 v0.14)
- 站内相关:《DragonFly MTA v0.14 安装指南》、《DragonFly MTA v0.14 配置参数详解》、《DragonFly MTA v0.14 介绍与选型指南》