AnonAddy 1.7.3 常用 CLI 命令详解

逐个实测 AnonAddy 1.7.3 的 13 个 anonaddy:* artisan 命令(用户管理/邮件管道/域名检查/清理/配额/计划任务),附高频运维命令速查

AnonAddyAnonAddy邮件别名Laravel自托管2026/10/25

AnonAddy 1.7.3 常用 CLI 命令详解

目标:讲清 AnonAddy(addy.io)v1.7.3 的命令行体系——13 个 anonaddy:* 专属命令逐个实测,并串起日常运维最常用的 Laravel artisan 通用命令。所有回显均在 Ubuntu 22.04 + AnonAddy 1.7.3(Laravel 13.34 / PHP 8.3)真实环境实测,命令默认在项目根目录 /var/www/anonaddy 下、以 Web 用户(www-data)身份执行。安装与环境准备见《Ubuntu 22.04 安装 AnonAddy 1.7.3 指南》,配置项含义见《AnonAddy 配置参数详解》。

一、命令体系总览

AnonAddy 基于 Laravel,全部 CLI 入口是项目根目录的 artisan。v1.7.3 共注册 143 个命令,其中 13 个是 anonaddy: 前缀的专属命令,其余为 Laravel 框架命令(queue、schedule、cache、config 等)。

实测验证——环境指纹与命令清单:

$ php artisan about

  Environment ................................................................
  Application Name .................................................. AnonAddy
  Laravel Version .................................................... 13.34.0
  PHP Version ......................................................... 8.3.36
  Composer Version .................................................... 2.10.3
  Environment ..................................................... production
  Debug Mode ............................................................. OFF
  URL ........................................................ app.example.com
  Maintenance Mode ....................................................... OFF
  Timezone ............................................................... UTC
  Locale .................................................................. en

  Cache ......................................................................
  Config .............................................................. CACHED
  Events .......................................................... NOT CACHED
  Routes .............................................................. CACHED
  Views ............................................................... CACHED

  Drivers ....................................................................
  Broadcasting ........................................................... log
  Cache ................................................................ redis
  Database ............................................................. mysql
  Logs ......................................................... stack / daily
  Mail .................................................................. smtp
  Queue ................................................................ redis
  Session .............................................................. redis
$ php artisan list anonaddy --raw
anonaddy:check-domains-mx-validation            Checks all existing domains to see if they still have valid MX records
anonaddy:check-domains-sending-verification     Checks all existing domains to see if they are still verified for sending
anonaddy:clear-failed-deliveries                Clears failed deliveries that are older than 3 days
anonaddy:clear-outbound-messages                Clears outbound messages that are older than 7 days
anonaddy:create-user                            Creates a new user
anonaddy:email-users-with-token-expiring-soon   Send an email to users who have an API token that is expiring soon
anonaddy:list-users                             Display the list of current users
anonaddy:parse-postfix-mail-log                 Parse Postfix log for inbound rejections and store them
anonaddy:receive-email                          Receive email from postfix pipe
anonaddy:remove-username-externalid             Removes the externalid of an username for logging in using Proxy authentication
anonaddy:reset-bandwidth                        Reset bandwidth for all users at the start of each month
anonaddy:set-username-externalid                Set the externalid of an username for logging in using Proxy authentication
anonaddy:update-app-version                     Updates the cached app version

执行身份红线:除 receive-email 由 Postfix 管道以 www-data 触发外,手工执行一律用 Web 用户身份(如 sudo -u www-data php artisan ...)。用 root 直接跑会在 storage/logs/ 留下 root 属主的日志文件,导致后续 Web/管道进程写日志失败、收信邮件被 Postfix 判为临时失败(deferred),这是实测踩过的坑。

二、用户管理

2.1 anonaddy:create-user — 创建用户

$ php artisan anonaddy:create-user --help
Usage:
  anonaddy:create-user <username> <email>

实测验证:

$ php artisan anonaddy:create-user cliuser clidemo@qq.com
Created user: "cliuser" with user_id: "80db5eb5-9f85-44fe-a651-8a46b0e568f1"
This user can now reset their password (the default password is their user_id)

要点:

  • 初始密码就是 user_id,用户首次登录后应立即改密,或通过登录页「忘记密码」重置(重置邮件走本机 Postfix 投递)。
  • 邮箱必须通过 email:rfc,dns 校验——不仅要格式合法,还要 DNS 能解析到 MX/A 记录且不接受 null MX。内网测试用不存在的域名会直接失败:
$ php artisan anonaddy:create-user demo bad-email
The email must be a valid email address.
  • 注册开关关闭(ANONADDY_ENABLE_REGISTRATION=false)后,这是唯一的建号途径。

2.2 anonaddy:list-users — 用户列表

实测验证:

$ php artisan anonaddy:list-users
+--------------------------------------+----------+-----------+---------------------+---------------------+
| ID                                   | Username | Bandwidth | Created_At          | Updated_At          |
+--------------------------------------+----------+-----------+---------------------+---------------------+
| 7f113ba9-cb3b-459e-8d24-12910a2895db | admin    | 120       | 2026-10-25 02:16:49 | 2026-10-25 02:50:18 |
| 80db5eb5-9f85-44fe-a651-8a46b0e568f1 | cliuser  | 0         | 2026-10-25 02:50:39 | 2026-10-25 02:50:39 |
+--------------------------------------+----------+-----------+---------------------+---------------------+

Bandwidth 列是该用户本月已用带宽(字节),与 ANONADDY_BANDWIDTH_LIMIT(默认 100MB)对照即可判断谁接近限额。

三、邮件管道:anonaddy:receive-email

这是整个别名系统的入口——Postfix 收到邮件后通过 master.cf 管道调用它完成别名匹配、限额检查、GPG 加密与转发投递。正常运维不需要手工执行,但理解参数对排障至关重要。

$ php artisan anonaddy:receive-email --help
Usage:
  anonaddy:receive-email [options] [--] [<file>]

Arguments:
  file                           The file of the email [default: "stream"]

Options:
      --sender[=SENDER]          The sender of the email
      --recipient[=RECIPIENT]    The recipient of the email (multiple values allowed)
      --local_part[=LOCAL_PART]  The local part of the recipient (multiple values allowed)
      --extension[=EXTENSION]    The extension of the local part of the recipient (multiple values allowed)
      --domain[=DOMAIN]          The domain of the recipient (multiple values allowed)
      --size[=SIZE]              The size of the email in bytes

Postfix 管道实际调用形如:

php /var/www/anonaddy/artisan anonaddy:receive-email --sender=${sender} --recipient=${recipient} --local_part=${user} --extension=${extension} --domain=${domain} --size=${size}

实测验证——手工投递一封原始邮件到别名 test1@example.com:

$ cat /tmp/raw.eml
From: sender@qq.com
To: test1@example.com
Subject: cli-manual-test
Message-ID: <cli-test-001@qq.com>

hello from cli

$ php artisan anonaddy:receive-email /tmp/raw.eml --sender=sender@qq.com --recipient=test1@example.com --local_part=test1 --extension= --domain=example.com --size=120
$ echo $?
0

返回码 0 表示管道受理成功(转发动作进入队列异步执行)。受理后 list-users 中该用户 Bandwidth 立即按 --size 计入 120 字节,可作受理凭证。

排障要点:--recipient/--local_part/--extension/--domain 是四个按下标一一对齐的数组,多收件人时每个数组都要给同样多的值。少给一个(比如漏了 --extension)会直接抛错:

production.ERROR: Undefined array key 0 {"exception":"[object] (ErrorException(code: 0): Undefined array key 0 at app/Console/Commands/ReceiveEmail.php:772)

别名不带扩展名时也要给空值 --extension=。另一个常见报错是输出 4.3.0 An error has occurred, please try again later.(SMTP 风格的临时失败码,Postfix 收到后会 deferred 重试),此时去 storage/logs/laravel-YYYY-MM-DD.log 看具体异常,八成是别名不存在、用户超限或存储目录属主不对。

四、域名健康检查

4.1 anonaddy:check-domains-mx-validation

遍历所有用户自定义域名,检查 MX 记录是否仍指向本服务(ANONADDY_HOSTNAME)。MX 失效的域名会被标记,其别名停止收信,防止域名过期后被别人抢注冒收邮件。

4.2 anonaddy:check-domains-sending-verification

遍历自定义域名,重新校验 SPF 等发信验证记录是否仍有效,失效则取消该域的发送权限。

两者均无输出、计划任务每日凌晨各跑一次(见第八章),手工执行用于修改 DNS 后立即复检:

$ php artisan anonaddy:check-domains-mx-validation
$ php artisan anonaddy:check-domains-sending-verification

五、日志解析与数据清理

5.1 anonaddy:parse-postfix-mail-log

解析 Postfix 日志(默认 /var/log/mail.log,可用 POSTFIX_LOG_PATH 改),把入站拒信记录入库,在 Web 控制台「Failed Deliveries」展示。计划任务每 5 分钟一次。

实测验证——两个典型状态:

$ php artisan anonaddy:parse-postfix-mail-log
Cannot read log file: /var/log/mail.log

原因:Ubuntu 默认 /var/log/mail.log 属主 syslog:adm、权限 640,www-data 读不到。修复:chmod 644 /var/log/mail.log(或把 www-data 加入 adm 组,并确认 logrotate 新建文件也继承可读权限)。修复后再跑无任何输出、退出码 0,即正常。

5.2 anonaddy:clear-failed-deliveries / clear-outbound-messages

$ php artisan anonaddy:clear-failed-deliveries   # 清理 3 天前的失败投递记录
$ php artisan anonaddy:clear-outbound-messages   # 清理 7 天前的外发邮件存档

均无输出。前者每天跑一次,后者每 6 小时一次(计划任务自动执行)。外发存档是匿名回复/发送功能的留痕,定期清理控制数据库体积。

六、配额与系统维护

6.1 anonaddy:reset-bandwidth

每月 1 日 00:00 由计划任务触发,把所有用户本月已用带宽清零。无输出。修改 ANONADDY_BANDWIDTH_LIMIT 不影响当月已计数,等月初自动清零。

6.2 anonaddy:email-users-with-token-expiring-soon

向 API token 即将过期的用户发提醒邮件,每日一次。无输出。

6.3 anonaddy:update-app-version

更新缓存中的应用版本号。升级代码后执行:

$ php artisan anonaddy:update-app-version
addy.io version:

(自托管实例未设置 ANONADDY_VERSION 环境变量时版本号为空,属正常现象。)

七、反代外部 ID 管理

配合 ANONADDY_USE_PROXY_AUTHENTICATION=true(见配置篇第七章)使用,把用户名与外部身份系统的 ID 绑定/解绑:

$ php artisan anonaddy:set-username-externalid admin ext-12345
Username: "admin" set as external with id : "ext-12345"

$ php artisan anonaddy:remove-username-externalid admin
Externalid of username: "admin" is removed

八、计划任务体系

上述带周期属性的命令全部由 Laravel 调度器驱动。实测验证:

$ php artisan schedule:list

  0   0   1 * *  php artisan anonaddy:reset-bandwidth  Next Due: 6 days from now
  0   0   * * *  php artisan anonaddy:check-domains-sending-verification  Next Due: 21 hours from now
  0   0   * * *  php artisan anonaddy:check-domains-mx-validation  Next Due: 21 hours from now
  0   0   * * *  php artisan anonaddy:clear-failed-deliveries  Next Due: 21 hours from now
  0   */6 * * *  php artisan anonaddy:clear-outbound-messages  Next Due: 3 hours from now
  0   0   * * *  php artisan anonaddy:email-users-with-token-expiring-soon  Next Due: 21 hours from now
  */5 *   * * *  php artisan anonaddy:parse-postfix-mail-log  Next Due: 39 seconds from now
  0   0   * * *  php artisan auth:clear-resets ... Next Due: 21 hours from now
  0   0   * * *  php artisan sanctum:prune-expired --hours=168  Next Due: 21 hours from now
  0   *   * * *  php artisan cache:prune-stale-tags  Next Due: 10 minutes from now

调度器本身靠 crontab 每分钟触发一次(安装篇已配):

* * * * * cd /var/www/anonaddy && php artisan schedule:run >> /dev/null 2>&1

排障时先 schedule:list 看任务是否在册、Next Due 是否合理,再 php artisan schedule:run --verbose 手动触发一轮观察输出。

九、运维高频通用命令速查

别名服务的日常排障离不开这些 Laravel 框架命令(www-data 身份执行):

场景命令
改 .env 后生效php artisan config:cache
查看生效配置php artisan config:show anonaddy
前台跑队列看实时日志php artisan queue:work redis --queue=default --verbose
查看失败队列任务php artisan queue:failed
重推失败任务php artisan queue:retry all
清路由/视图缓存php artisan route:clear && php artisan view:clear
进 Tinker 查数据php artisan tinker
维护模式php artisan down / php artisan up

队列是重点:转发、退信处理全部异步,队列停滞表现为「别名收信无转发」。用 Supervisor 常驻 queue:work(安装篇已配),排查时先 supervisorctl status 看 worker 是否存活,再 queue:failed 看有无堆积的失败任务。

十、参考链接