Mail-in-a-Box v77 管理 API 使用详解

Mail-in-a-Box v77 管理守护进程 API 实测详解:API 密钥与面板 Basic 双认证通道、约 40 个端点全景、用户/别名/DNS/证书/系统核心端点 curl 实测回显与官方 CLI 映射。

Mail-in-a-Box邮件服务器Mail-in-a-Box2026/10/21

Mail-in-a-Box v77 管理 API 使用详解

目标:讲清 Mail-in-a-Box 管理守护进程(management daemon)HTTP API 的认证通道、端点全景与核心用法,所有请求/响应均来自本站在 v77 实机上的 curl 实测(2026-10-21)。掌握这套 API 即可把面板里的所有操作脚本化——官方命令行 management/cli.py 本身就是它的薄封装。

一、环境信息

项目值
组件版本Mail-in-a-Box v77(2026-10-21 实测)
守护进程mailinabox.service(gunicorn 承载的 Python3/Flask 应用)
监听地址127.0.0.1:10222(仅本机;对外经 nginx /admin/ 反代)
认证方式通道 A:API 密钥(仅本机直连);通道 B:管理员账号 Basic 认证(经 HTTPS)
API 规范仓库随附 OpenAPI 3.0 规范 api/mailinabox.yml(约 40 个端点)
测试账号me@example.com(管理员,示例密码 q1w2e3r4)

二、API 形态与认证

2.1 架构:一条链路、两个入口

浏览器/脚本 ──HTTPS(443)──> nginx location /admin/ ──反代(去 /admin 前缀)──> 127.0.0.1:10222 (Flask)
本机脚本 ──────────── HTTP 直连 ──────────────────────────────────────────> 127.0.0.1:10222 (Flask)

nginx 侧配置(/etc/nginx/conf.d/local.conf 实测节选):

rewrite ^/admin$ /admin/;
location /admin/ {
        proxy_pass http://127.0.0.1:10222/;
        proxy_set_header X-Forwarded-For $remote_addr;
        add_header X-Frame-Options "DENY";
        ...
}

即同一个 API 有两个入口:本机脚本直连 http://127.0.0.1:10222/...(API 密钥认证),远程脚本走 https://<主机名>/admin/...(管理员账号 Basic 认证)。路径在反代时剥掉 /admin 前缀,端点本身一致。

2.2 通道 A:API 密钥(本机 root 专用)

密钥文件 /var/lib/mailinabox/api.key,守护进程每次重启都会重新生成(cron 定时任务调用 CLI 的场景要注意重新读取)。认证格式为 Basic,用户名=密钥内容、密码留空:

curl -s --user "$(cat /var/lib/mailinabox/api.key):" http://127.0.0.1:10222/mail/users

实测回显:

me@example.com

2.3 通道 B:面板账号 Basic 认证(远程可用)

用管理员邮箱账号走 HTTPS,与登录面板等价(账号需有 admin 权限):

curl -sk -u "me@example.com:q1w2e3r4" https://box.example.com/admin/mail/users

实测回显:

me@example.com

⚠️ 说明:-k 是因为测试环境证书为自签。正式环境域名解析与 Let's Encrypt 证书就绪后去掉 -k。

三、端点全景(v77 实查,源自 management/daemon.py 路由表)

分组端点方法用途
面板/、/login、/logoutGET/POST面板首页与登录态
邮件·用户/mail/usersGET列出全部邮箱账号
/mail/users/addPOST建号
/mail/users/passwordPOST改密
/mail/users/quotaGET/POST查询/设置配额
/mail/users/removePOST删号
/mail/users/privileges、/privileges/add、/privileges/removeGET/POST权限(admin)管理
邮件·别名/mail/aliases、/aliases/add、/aliases/removeGET/POST别名管理
邮件·域名/mail/domainsGET托管邮件域名
DNS/dns/zonesGET托管 DNS 区域
/dns/updatePOST全量重建并重载区域
/dns/custom/<qname>[/<rtype>]GET/PUT/DELETE自定义记录 CRUD
/dns/dump、/dns/zonefile/<zone>GET区域调试转储 / 标准区域文件
/dns/secondary-nameserverGET/POST辅助 DNS 设置
证书/ssl/status、/ssl/csr/<domain>、/ssl/installGET/POST证书状态/CSR/安装
网站/web/domains、/web/updateGET/POST静态站点与重生成
系统/system/versionGET当前版本
/system/latest-upstream-version、/system/updates、/system/update-packagesPOST/GET/POST新版本与系统更新
/system/statusPOST全量健康检查(面板首页数据源)
/system/rebootGET/POST重启计划/执行
/system/backup/status、/system/backup/configGET/POST备份状态与配置
/system/privacyGET/POST匿名统计开关
MFA/mfa/status、/mfa/totp/enable、/mfa/disablePOST双因素管理
监控/munin/...GETmunin 图表代理

四、核心端点实测

以下命令均在服务器本机以 root 执行,AK 即 API 密钥。全部回显照抄实测。

4.1 用户管理

AK=$(cat /var/lib/mailinabox/api.key); H=http://127.0.0.1:10222
# 建号
curl -s --user "$AK:" -X POST $H/mail/users/add -d "email=test.user@example.com" -d "password=q1w2e3r4"
mail user added
# 查询/设置配额(0=不限额)
curl -s --user "$AK:" "$H/mail/users/quota?text=1&email=me@example.com"
0
curl -s --user "$AK:" -X POST $H/mail/users/quota -d "email=me@example.com" -d "quota=2G"
OK
# 删号
curl -s --user "$AK:" -X POST $H/mail/users/remove -d "email=test.user@example.com"
mail user removed

4.2 别名管理

curl -s --user "$AK:" $H/mail/aliases

实测(节选)——安装时自动生成的 RFC 2142 标准别名,全部指向管理员:

abuse@box.example.com   administrator@box.example.com
admin@box.example.com   administrator@box.example.com
administrator@box.example.com   me@example.com
hostmaster@box.example.com      administrator@box.example.com
postmaster@box.example.com      administrator@box.example.com
abuse@example.com       administrator@box.example.com
admin@example.com       administrator@box.example.com
postmaster@example.com  administrator@box.example.com
curl -s --user "$AK:" -X POST $H/mail/aliases/add -d "address=sales@example.com" -d "forwards_to=me@example.com"
alias added
curl -s --user "$AK:" -X POST $H/mail/aliases/remove -d "address=sales@example.com"
alias removed

4.3 DNS:区域、重建与自定义记录 CRUD

curl -s --user "$AK:" $H/dns/zones
[
  "example.com"
]

自定义记录是脚本化 DNS 的核心(DDNS、临时验证记录都靠它)。⚠️ 实测要点:PUT 的记录值是裸请求体而非表单字段:

# PUT:值直接放请求体
curl -s --user "$AK:" -X PUT $H/dns/custom/lab.example.com/A -d "10.0.0.3" -w "[http %{http_code}]"
updated DNS: example.com
[http 200]

反例(实测会报错):-d "value=10.0.0.3" 会被当作字面值,返回 400:'value=10.0.0.3' does not appear to be an IPv4 or IPv6 address。

# GET:查询刚写入的记录
curl -s --user "$AK:" $H/dns/custom/lab.example.com/A
[
  {
    "qname": "lab.example.com",
    "rtype": "A",
    "sort-order": { "created": 0, "qname": 0 },
    "value": "10.0.0.3",
    "zone": "example.com"
  }
]
# DELETE:删除
curl -s --user "$AK:" -X DELETE $H/dns/custom/lab.example.com/A -w "[http %{http_code}]"
updated DNS: example.com
[http 200]

拉取标准区域文件(含 SOA/DNSSEC 相关记录,可对接外部 DNS 同步):

curl -s --user "$AK:" $H/dns/zonefile/example.com | head -12
$ORIGIN example.com.
$TTL 86400          ; default time to live

@ IN SOA ns1.box.example.com. hostmaster.box.example.com. (
           2026102103     ; serial number
           7200     ; Refresh (secondary nameserver update interval)
           3600     ; Retry (when refresh fails, how often to try again, should be lower than the refresh)
           1209600  ; Expire (when refresh fails, how long secondary nameserver will keep records around anyway)
           86400    ; Negative TTL (how long negative responses are cached)
           )
        IN      NS      ns1.box.example.com.

4.4 证书状态

curl -s --user "$AK:" $H/ssl/status | head -14

实测(新装机器、域名未解析到本机时的真实状态):

{
  "can_provision": [],
  "status": [
    {
      "domain": "box.example.com",
      "status": "warning",
      "text": "Self-signed. Get a signed certificate to stop warnings. The domain name does not resolve to this machine: [Not Set] (A)."
    },
    {
      "domain": "mta-sts.box.example.com",
      "status": "danger",
      "text": "No certificate installed. The domain name does not resolve to this machine: [Not Set] (A)."
    },

4.5 系统信息与备份

curl -s --user "$AK:" $H/system/version
v77
curl -s --user "$AK:" $H/system/backup/status
{
  "backups": [],
  "unmatched_file_size": 0
}

(backups 为空 = 尚未到每日备份时间点;首次备份后此数组将列出各日期快照。)

4.6 空响应端点备忘

实测中两个端点"成功但无响应体",脚本化时勿把空输出当失败:POST /dns/update(HTTP 200,空 body)、GET /system/updates(无待更新包时空 body)。需要判成败时加 -w "%{http_code}" 看 HTTP 状态码。

五、与官方 CLI 的映射关系

management/cli.py 是这套 API 的命令行封装(同样吃 /var/lib/mailinabox/api.key 认证),二者可按需替换:

CLI 命令等价 API 调用
management/cli.py user(无子命令列出全部)GET /mail/users
user add <邮箱> <密码>POST /mail/users/add
user password <邮箱> <密码>POST /mail/users/password
user remove <邮箱>POST /mail/users/remove
user quota <邮箱> [配额]GET/POST /mail/users/quota
user make-admin / remove-admin <邮箱>POST /mail/users/privileges/add / remove
user adminsGET /mail/users + 过滤 admin 权限
user mfa show <邮箱>POST /mfa/status
alias / alias add / removeGET/POST /mail/aliases(/add)(/remove)

💡 注意 v77 的 CLI 语法:列用户是裸命令 management/cli.py user(user list 反而报 Invalid command-line arguments.),列别名同理用裸命令 alias。

六、常见坑

  1. /var/lib/mailinabox/api.key 每次守护进程重启都会轮换——cron 长期任务里应每次现场 cat,不要缓存到文件。
  2. PUT /dns/custom 的值走裸请求体,不是 value= 表单字段(见 4.3 实测反例)。
  3. 空响应 ≠ 失败:/dns/update、/system/updates 成功时也是空 body(见 4.6)。
  4. /admin/ 反代会剥前缀:经 HTTPS 入口调用时端点前多一层 /admin(如 https://box.example.com/admin/mail/users),直连 10222 时没有;写通用脚本时建议封装一层 base URL。
  5. 面板账号 ≠ API 密钥的权限域:通道 B 要求账号有 admin 权限;被降权为普通用户的账号无法调用管理端点。

七、参考链接

  1. 官方 OpenAPI 3.0 规范:https://raw.githubusercontent.com/mail-in-a-box/mailinabox/api-spec/api/mailinabox.yml
  2. 本站部署篇:《Ubuntu 22.04 安装 Mail-in-a-Box 指南》
  3. 本站配置篇:《Mail-in-a-Box v77 配置参数详解》
  4. 官方仓库 management/ 目录(daemon.py 即全部端点源码):https://github.com/mail-in-a-box/mailinabox