Mailu 2024.06.65 常用 CLI 命令详解

Mailu 官方管理命令行 flask mailu 逐命令详解:admin/user/domain/alias/password/user-delete/user-import 与 config-export/config-import/config-update 增删改查实测回显,setlimits/setmanager 等未文档化命令,以及 CLI 与 Web 管理台、RESTful API 的分工建议。

Mailu邮件服务器2026/10/21

Mailu 2024.06.65 常用 CLI 命令详解

目标:详解 Mailu 官方管理命令行(flask mailu 系列命令)的账号/域/别名管理、配置导出导入、域级策略设置等用法,全部命令与回显来自 2024.06.65 实际部署的逐行实测;同时给出官方 CLI 与 Web 管理台、RESTful API 三条管理通道的分工建议。部署过程见《Mailu Docker Compose 部署指南》,配置参数见《Mailu 2024.06.65 配置参数详解》。

一、环境信息

  • Mailu:2024.06.65(2024.06 稳定分支锁定版)
  • 操作系统:Ubuntu 22.04(x86_64)
  • 实测环境:本专栏部署指南篇搭建的 mail.example.com(主域 example.com,另有实测副域 example.net),管理员 admin@example.com
  • CLI 依据:官方管理命令行文档 https://mailu.io/2024.06/cli.html(查询日期 2026-10-21)+ 实际部署验证

二、CLI 概览

Mailu 官方以多服务协作栈发行(见《Mailu 2024.06.65 介绍与选型指南》第三章),管理命令行内置于其中的 admin 服务(Flask 应用自带 CLI),因此官方调用方式是进入 admin 服务执行 flask mailu <命令>:

docker compose exec admin flask mailu <子命令> [参数]

(后续命令均在部署目录 /opt/data/quzuo/tmp/mailu/compose/ 下执行;交互式终端可省略 -T,脚本/管道场景必须加 -T。)

顶层帮助(flask mailu --help)实测回显:

Usage: flask mailu [OPTIONS] COMMAND [ARGS]...

  Mailu command line

Options:
  -e, --env-file FILE   Load environment variables from this file. python-
                        dotenv must be installed.
  -A, --app IMPORT      The Flask application or factory function to load, in
                        the form 'module:name'. Module can be a dotted import
                        or file path. Name is not required if it is 'app',
                        'application', 'create_app', or 'make_app', and can be
                        'name(args)' to pass arguments.
  --debug / --no-debug  Set debug mode.
  --version             Show the Flask version.
  -h, -?, --help        Show this message and exit.

Commands:
  admin          Create an admin user
  advertise      Advertise this server against statistic services.
  alias          Create an alias
  alias-delete   delete alias
  config-export  Export configuration as YAML or JSON to stdout or file
  config-import  Import configuration as YAML or JSON from stdin or file
  config-update  Sync configuration with data from YAML (deprecated)
  db             Perform database migrations.
  domain         Create a domain
  mailu          Mailu command line
  password       Change the password of an user
  routes         Show the routes for the app.
  run            Run a development server.
  setlimits      Set domain limits
  setmanager     Make a user manager of a domain
  shell          Run a shell in the app context.
  user           Create a user
  user-delete    disable or delete user
  user-import    Import a user along with password hash

命令全景(★=官方 cli.html 文档收录;☆=官方文档未收录但实测存在):

命令用途关键参数
★ admin创建全局管理员(连带自动建域)localpart domain password + --mode
★ user创建用户localpart domain password 及可选属性
★ domain创建域domain_name
★ password改用户口令user domain password
★ alias / alias-delete建/删别名目标地址列表逗号分隔
★ user-delete停用/删除用户email + -r/--really
★ user-import按口令哈希导入用户(迁移场景)localpart domain hash scheme
★ config-export导出全部配置为 YAML/JSON--full --secrets --dns --json -o
★ config-import从 YAML/JSON 导入配置--update --dry-run --verbose
★ config-updateYAML 增量同步(已标记 deprecated)--delete-objects
☆ setlimits设置域级限制(邮箱数/别名数/配额)domain_name max_users max_aliases max_quota_bytes
☆ setmanager把用户设为域管理员user domain
☆ advertise向统计服务声明本服务器无参数
☆ shell进入应用上下文 shell—
☆ db数据库迁移Flask-Migrate 子命令
☆ routes / run / mailuFlask 自带:路由表/开发服务器/CLI 入口别名—

💡 说明:user-import 与 user 的核心区别——前者把传入值当作已存在的口令哈希直接写入(迁移其他邮件系统时有用),后者把传入值当作明文口令现场哈希。setlimits/setmanager 虽未见于官方 cli.html,但实测存在且可用,管理多域时可作 Web 界面的命令行替代。

三、账号与域管理命令

3.1 创建域:domain

$ docker compose exec -T admin flask mailu domain example.net

成功时静默无输出。创建全局管理员时也会连带建域(见 3.2)。

3.2 创建全局管理员:admin

$ docker compose exec -T admin flask mailu admin <localpart> <domain> <password> --mode <mode>

--mode 取值 create(默认,已存在报错)/ifmissing(存在则跳过)/update(存在则更新口令)——与 mailu.env 的 INITIAL_ADMIN_MODE 同一套语义。本专栏部署即由 INITIAL_ADMIN_* 变量在首启时执行了等价命令,admin 日志留痕:INFO:root:Creating initial admin account admin@example.com with mode ifmissing。

3.3 创建用户:user

$ docker compose exec -T admin flask mailu user user1 example.com 'q1w2e3r4'

成功时静默。可用属性与 config-update 的 user 段一致(comment、quota_bytes、global_admin、enable_imap、enable_pop、forward_enabled、forward_destination、reply_enabled、displayed_name、spam_enabled、spam_threshold 等)。

3.4 修改口令:password

$ docker compose exec -T admin flask mailu password user2 example.net 'q1w2e3r4'

同样静默成功。口令立即生效,不影响该用户已登录的会话。

3.5 停用/删除用户:user-delete

$ docker compose exec -T admin flask mailu user-delete user2@example.net

注意语义:官方文档明确"名为 delete,默认只做停用"——因为 Mailu 不会连带清理用户数据(邮件与 Webmail 联系人),加 -r/--really 才真删(且建议先手工清理用户数据)。停用效果实测:

$ docker compose exec -T admin flask mailu config-export user.email user.enabled
user:
  - email: admin@example.com
    enabled: true
  - email: user1@example.com
    enabled: true
  - email: user2@example.net
    enabled: false

3.6 按哈希导入用户:user-import

迁移场景(只拿得到旧系统口令哈希):

$ docker compose run --rm admin flask mailu user-import myuser example.net \
    '$6$51ebe0cb9f1dab48effa2a0ad8660cb489b445936b9ffd812a0b8f46bca66dd549fea530ce' \
    'SHA512-CRYPT'

注意官方示例用的是 docker compose run --rm(一次性执行),与 exec 的区别是 run 会新起一个临时实例执行后销毁。哈希方案名要与旧系统一致(SHA512-CRYPT/MD5-CRYPT 等)。

四、别名管理命令

# 创建别名 support@example.net -> user1@example.com(多目的地用逗号分隔)
$ docker compose exec -T admin flask mailu alias support example.net "user1@example.com"
# 删除别名
$ docker compose exec -T admin flask mailu alias-delete support@example.net

两命令成功时均静默。别名支持通配(--wildcard)。删除后可用 config-export 复核:

$ docker compose exec -T admin flask mailu config-export alias.email alias.destination
alias: []

五、配置导出与导入

5.1 导出:config-export

帮助(实测):

Usage: flask mailu config-export [OPTIONS] [FILTER]...

  Export configuration as YAML or JSON to stdout or file

Options:
  -f, --full                  Include attributes with default value.
  -s, --secrets               Include secret attributes (dkim-key, passwords).
  -d, --dns                   Include dns records.
  -c, --color                 Force colorized output.
  -o, --output-file FILENAME  Save configuration to file.
  -j, --json                  Export configuration in json format.
  -?, -h, --help              Show this message and exit.

行为规则:默认只导出非默认值属性;要全量加 --full;要含明文秘密(DKIM 私钥、口令)加 --secrets;要含 DNS 记录(MX/SPF/DKIM/DMARC)加 --dns;可用过滤器只导指定对象或属性(如 user、domain.name,过滤器点名了的属性自动包含)。实测样例:

$ docker compose exec -T admin flask mailu config-export user.email user.global_admin
user:
  - email: admin@example.com
    global_admin: true
  - email: user1@example.com
    global_admin: false
$ docker compose exec -T admin flask mailu config-export alias.email alias.destination
alias:
  - email: info@example.net
    destination:
      - user1@example.com

备份建议:-o 落文件 + --dns,配合 --secrets 才是可恢复的完整备份(秘密默认脱敏)。

5.2 导入:config-import

帮助(实测):

Usage: flask mailu config-import [OPTIONS] [FILENAME|-]

  Import configuration as YAML or JSON from stdin or file

Options:
  -v, --verbose   Increase verbosity.
  -s, --secrets   Show secret attributes in messages.
  -q, --quiet     Quiet mode - only show errors.
  -c, --color     Force colorized output.
  -u, --update    Update mode - merge input with existing config.
  -n, --dry-run   Perform a trial run with no changes made.
  -?, -h, --help  Show this message and exit.

要点:

  • 不带 --update 默认整库替换(现有配置先清空再导入),只想合并增量必须加 --update;
  • stdin 传入必须用 -T(flask mailu config-import -u -);
  • 删单条/清空的特殊记法:- -name:example.com(删指定数组对象)、- -user1@example.com(删指定列表项)、- -key:null(删全部剩余/重置默认值)、- -prune-(清空全部剩余列表项);
  • 新建域时可用魔法值 dkim_key: -generate- 让系统现生成 DKIM 密钥。

干跑实测(只演练不落库):

$ printf 'user:\n  - email: user4@example.net\n    password: q1w2e3r4\n' | \
    docker compose exec -T admin flask mailu config-import -nv -
Dry run. Not committing changes.
Created: user(1)

实际导入实测(增量合并,导入一个别名):

$ printf 'alias:\n  - email: postmaster@example.net\n    destination:\n      - user1@example.com\n' | \
    docker compose exec -T admin flask mailu config-import -u -
Committing changes.
Created: alias(1)

5.3 增量同步:config-update(deprecated)

官方已将其标记为 deprecated(新场景用 config-import),存量脚本迁移提示:两者口令字段约定不同——

  • config-update 的 user 段要 password_hash(哈希):
    $ HASH=$(openssl passwd -6 q1w2e3r4)
    $ printf 'users:\n  - localpart: user3\n    domain: example.net\n    password_hash: %s\n' "$HASH" | \
        docker compose exec -T admin flask mailu config-update
    Created: user(1), alias(1)
    
    直接传明文 password 会撞数据库非空约束(实测报错 IntegrityError: (sqlite3.IntegrityError) NOT NULL constraint failed: user.password);
  • config-import 的 user 段要 password(明文)。

5.4 批量 YAML 模板

config-update 的输入格式(官方 cli.html 原样):

users:
  - localpart: foo
    domain: example.com
    password_hash: klkjhumnzxcjkajahsdqweqqwr

aliases:
  - localpart: alias1
    domain: example.com
    destination: "user1@example.com,user2@example.com"

不指定 --delete-objects 时只增改、不删缺失条目;指定后以 YAML 为准做全量对齐。

六、域策略与未文档化命令

6.1 设置域级限制:setlimits

Usage: flask mailu setlimits [OPTIONS] DOMAIN_NAME MAX_USERS MAX_ALIASES MAX_QUOTA_BYTES

用于多租户托管:限制每个域可建邮箱数/别名数/总配额(字节);-1 表示不限。等效于管理台域名编辑页的三个限制字段。

6.2 任命域管理员:setmanager

$ docker compose exec -T admin flask mailu setmanager <user邮箱> <domain>

把普通用户提升为指定域的管理员(只能管理该域的账号),等效于管理台的"域管理员"指派。撤销同理走 Web 界面。

6.3 其他内置命令

  • shell:进入应用上下文的 Python shell(调试数据层用);
  • db:数据库迁移(Flask-Migrate 包装,db status/db upgrade);
  • advertise:向统计聚合服务上报本服务器存在(DISABLE_STATISTICS=true 后无实际动作);
  • routes/run:Flask 框架自带(开发调试用,生产无关)。

七、CLI 与 Web 管理台、REST API 的分工

Mailu 三条管理通道操作同一份数据,能力对等关系(官方 api.html 原话:"Anything that can be configured via the Mailu web administration interface, can also be configured via the API"):

通道适用场景认证
flask mailu CLI批量脚本、迁移、无图形环境、CI 里初始化服务器本地执行
Web 管理台日常运营、一次性操作、域管理员分权登录会话
RESTful API与外部系统对接、自动化巡检API_TOKEN Bearer

API 速览(实测于本部署,WEB_API=/api,Swagger UI 见 https://<主机>/api/,机读定义 /api/v1/swagger.json 共 18 组端点:alias/alternative/domain(+dkim/manager/users)/relay/token/tokenuser/user 等):

$ curl -sk -H 'Authorization: q1w2e3r4' -X POST \
    -H 'Content-Type: application/json' \
    -d '{"name":"example.org","max_users":-1,"max_aliases":-1,"max_quota_bytes":0,"signup_enabled":false}' \
    https://127.0.0.1:8132/api/v1/domain
{"message":"Domain example.org has been created"}

选型建议:人值守的操作走 Web 台;脚本化/批量走 CLI;跨系统集成走 API。CLI 与 API 的一个差异点要记住:CLI 建域不生成 DKIM 密钥(flask mailu domain/admin 均如此),Web 台建域会生成;CLI 用户可用 API 补:POST /api/v1/domain/<域名>/dkim 生成 DKIM 密钥。

八、常见问题

Q1:命令成功为什么不打印任何东西? 官方 CLI 风格:user/domain/alias/password 等成功时静默,失败时抛栈回显。核验请用 config-export(脚本中可用退出码判断)。

Q2:config-update 报 NOT NULL constraint failed: user.password? config-update 只认 password_hash 字段(预哈希);明文口令请用 flask mailu user,或改用 config-import(它要 password 字段)。详见 5.3 节。

Q3:flask mailu --help 末尾冒出一段 AssertionError 栈? 实测在 --help 正常输出后,进程退出阶段会打印 AssertionError: There is no current event loop in thread 'MainThread'. 的栈——Flask CLI 退出钩子的已知怪象,不影响帮助内容正确性,脚本判断请以退出码/正文为准。

Q4:命令行建的域没有 DKIM? 见第七章末尾说明:用管理台"重新生成密钥"或 API POST /api/v1/domain/<域名>/dkim。

Q5:脚本里批量执行要注意什么? ① docker compose exec 必须加 -T(非 TTY 场景);② 认证限速对 CLI 不生效(本地操作),但导入大量用户后建议同步设置 setlimits 收紧域级配额;③ config-import 不带 --update 会整库替换,务必先 --dry-run 演练。

九、参考链接