HyperKitty 1.3.12 常用 CLI 命令与工具详解

HyperKitty 1.3.12 命令行运维全解:mailman-web 入口命令全景清单、hyperkitty_import mbox 导入实战(默认时间窗跳过与 --since 重跑真实回显)、Whoosh 索引三件套、Django 工程维护与账号命令、django-q 定时任务、归档 API Token 调用与 spool 排障,全部命令实测附原始输出。

HyperKitty邮件列表Django自托管2026/10/26

HyperKitty 1.3.12 常用 CLI 命令与工具详解

目标:系统梳理 HyperKitty 1.3.12 日常运维的命令行工具集——mailman-web 统一管理入口、归档导入 hyperkitty_import、全文索引管理、Django 工程命令、定时任务工具与归档 API 调用排障,全部命令均在真实环境实测并附原始回显(Debian 12,实测日期 2026-10-26)。安装与配置背景见 《Debian 12 安装 HyperKitty 1.3.12 指南》、《HyperKitty 1.3.12 配置参数详解》。

一、环境信息

  • 实测环境:Debian 12(12.15),HyperKitty 1.3.12、mailman-web 0.0.9、Mailman core 3.3.10、mailman-hyperkitty 1.2.1、django-haystack 3.4.0、Whoosh 2.7.4、Python 3.11.2(venv 位于 /opt/mailman/venv)
  • 统一入口:mailman-web(由 mailman-web 0.0.9 包提供,落位于 /opt/mailman/venv/bin/mailman-web)。它是 Django manage.py 的封装,启动时自动定位 settings(MAILMAN_WEB_CONFIG 指向 /etc/mailman3/settings.py),因此所有 Django 管理命令都以它为前缀执行;生产操作建议以 mailman 运行用户执行:su -s /bin/bash mailman -c '…'
  • 本篇实测过的命令一览:
命令用途实测结果
mailman-web help命令清单✓
mailman-web hyperkitty_importmbox 归档导入✓(含时间窗跳过与重跑)
mailman-web update_index_one_list单列表索引重建✓ Indexing 4 emails
mailman-web update_index全站索引重建✓ Indexing 4 emails
mailman-web haystack_info索引概况✓
mailman-web migrate / collectstatic / compress工程维护✓
mailman-web createsuperuser / shell账号管理✓
mailman-web qinfodjango-q 队列统计✓(缺依赖报错,见 FAQ)
curl 归档 API链路验证✓ 200

二、CLI 工具全景

mailman-web help 输出全部可用子命令(实测完整清单,按 app 分节;✓ 标记为本篇实测过):

[account]
    account_unsetmultipleprimaryemails

[auth]
    changepassword
    createsuperuser          ✓

[compressor]
    compress                 ✓
    mtime_cache

[contenttypes]
    remove_stale_contenttypes

[django]
    check
    compilemessages
    createcachetable
    dbshell
    diffsettings
    dumpdata
    flush
    inspectdb
    loaddata
    makemessages
    makemigrations
    migrate                  ✓
    optimizemigration
    sendtestemail
    shell                    ✓

[django_q]
    qcluster                 ✓(服务形态运行)
    qinfo                    ✓
    qmemory
    qmonitor

[haystack]
    build_solr_schema
    clear_index
    haystack_info            ✓
    rebuild_index
    update_index             ✓

[hyperkitty]
    attachments_to_file
    hyperkitty_import        ✓
    hyperkitty_warm_up_cache
    mailman_sync
    update_index_one_list    ✓

[postorius]
    mmclient
    reset_passwords

[rest_framework]
    generateschema

[sessions]
    clearsessions

[staticfiles]
    collectstatic            ✓
    findstatic
    runserver

速查分工:hyperkitty 节是归档本体运维(导入/索引/缓存/同步);haystack 节是全文搜索引擎层;django_q 节是后台任务队列;django/staticfiles/compressor/auth 节是通用 Django 工程维护;postorius 节属列表管理界面。

三、归档导入 hyperkitty_import

HyperKitty 最重要的运维命令:把历史 mbox 归档文件导入列表归档(从 Mailman 2.1/Pipermail 迁移的官方路径)。

3.1 命令帮助(实测原文)

mailman-web hyperkitty_import --help
usage: mailman-web hyperkitty_import [-h] [--delete] [-l LIST_ADDRESS]
                                     [--no-sync-mailman] [--since SINCE]
                                     [--ignore-mtime] [--version]
                                     [-v {0,1,2,3}] [--settings SETTINGS]
                                     [--pythonpath PYTHONPATH] [--traceback]
                                     [--no-color] [--force-color]
                                     [--skip-checks]
                                     mbox [mbox ...]

Imports the specified archive mbox(es). Before running this, the mbox(es)
should be checked for messages that could throw uncaught exceptions with the
contrib/check_hk_archive script and for unescaped 'From ' lines with Mailman
2.1's cleanarch script.

positional arguments:
  mbox

options:
  -h, --help            show this help message and exit
  --delete              Delete poll instead of closing it
  -l LIST_ADDRESS, --list-address LIST_ADDRESS
                        the full list address the mailbox will be imported to
  --no-sync-mailman     do not sync properties with Mailman (faster, useful
                        for batch imports)
  --since SINCE         only import emails later than this date. Defaults to

3.2 实战:导入一个测试 mbox

准备 mbox(两封测试邮件,注意 mbox 格式的 From 分隔行):

cat > /tmp/hk-import.mbox <<'EOF'
From tester@example.com  Mon Oct 26 05:10:00 2026
From: Tester <tester@example.com>
To: testlist@example.com
Subject: [Testlist] imported from mbox demo 1
Message-ID: <hk-import-0001@example.com>
Date: Mon, 26 Oct 2026 05:10:00 +0000

First imported message body.

From tester@example.com  Mon Oct 26 05:11:00 2026
From: Tester <tester@example.com>
To: testlist@example.com
Subject: [Testlist] imported from mbox demo 2
Message-ID: <hk-import-0002@example.com>
Date: Mon, 26 Oct 2026 05:11:00 +0000

Second imported message body.
EOF

第一次执行(不指定时间窗):

mailman-web hyperkitty_import -l testlist@example.com /tmp/hk-import.mbox
?: settings.ACCOUNT_AUTHENTICATION_METHOD is deprecated, use: settings.ACCOUNT_LOGIN_METHODS = {'email', 'username'}
?: settings.ACCOUNT_EMAIL_REQUIRED is deprecated, use: settings.ACCOUNT_SIGNUP_FIELDS = ['email*', 'username*', 'password1*', 'password2*']
Warning: not importing messages older than Oct. 26, 2026. Use "--since=<date>" to import older messages.
Importing from mbox file /tmp/hk-import.mbox to testlist@example.com
|/Computing thread structure
Synchronizing properties with Mailman
Warming up cache
The full-text search index is not updated for this list. It will not be updated by the 'minutely' incremental update job. To update the index for this list, run the Django admin command with arguments 'update_index_one_list testlist@example.com'.

输出逐行解读(本例直接踩中了两个高频点):

  • 开头两行 ?: settings.… is deprecated 是 django-allauth 新版的参数改名提醒(无害警告,可按提示改 settings.py 消除,详见 FAQ 8.4);
  • Warning: not importing messages older than Oct. 26, 2026.——hyperkitty_import 默认只导入「最近窗口期」的邮件,日期更早的一律跳过!历史归档迁移必须显式给 --since,这是官方设计的防误操作护栏(FAQ 8.1);
  • 末尾 The full-text search index is not updated for this list…——导入不会自动更新 Whoosh 索引,并直接告诉你下一步命令,照抄执行即可。

第二次执行(带 --since,真实导入):

mailman-web hyperkitty_import -l testlist@example.com --since=2026-10-01 /tmp/hk-import.mbox
?: settings.ACCOUNT_EMAIL_REQUIRED is deprecated, use: settings.ACCOUNT_SIGNUP_FIELDS = ['email*', 'username*', 'password1*', 'password2*']
Importing from mbox file /tmp/hk-import.mbox to testlist@example.com
|/Computing thread structure
Synchronizing properties with Mailman
Warming up cache
The full-text search index is not updated for this list. It will not be updated by the 'minutely' incremental update job. To update the index for this list, run the Django admin command with arguments 'update_index_one_list testlist@example.com'.

(本次无跳过警告,两封邮件完成入库;流程四步:Computing thread structure 算线程 → Synchronizing properties with Mailman 与 core 同步作者属性 → Warming up cache 预热线程缓存 → 索引提示。)

3.3 参数速查

参数作用建议
-l / --list-address目标列表完整地址必填;列表须已存在于 core(用 core REST 或 Postorius 建)
--since只导入该日期之后的邮件历史迁移必加(如 --since=2000-01-01);默认窗口会静默跳过老邮件
--no-sync-mailman跳过与 core 的属性同步批量导入提速;整批导完后跑一次带同步的导入或 mailman_sync 补齐
--ignore-mtime忽略文件修改时间判定配合 --since 使用,按邮件 Date 头而非文件时间筛选
--delete删除投票而非关闭极少用
幂等性重复导入同一 mbox按 Message-ID 去重,重复执行安全(实测重复跑无重复帖)

导入前预检(帮助文本里的官方建议):用 Mailman 2.1 的 cleanarch 修复裸 From 行、contrib/check_hk_archive 查会抛异常的坏消息——大批量迁移先做这两步能省掉中途断导的麻烦。

四、全文搜索索引管理

Whoosh 索引与归档库是两套数据:入库不等于可搜。hyperkitty_import 的输出会明确提示;新邮件的增量索引由 minutely 定时任务负责,但该任务只管「归档推送进来的新信」,导入的历史信必须手动补索引。

4.1 单列表索引(导入后的指定动作)

mailman-web update_index_one_list testlist@example.com
?: settings.ACCOUNT_AUTHENTICATION_METHOD is deprecated, use: settings.ACCOUNT_LOGIN_METHODS = {'email', 'username'}
?: settings.ACCOUNT_EMAIL_REQUIRED is deprecated, use: settings.ACCOUNT_SIGNUP_FIELDS = ['email*', 'username*', 'password1*', 'password2*']
Indexing 4 emails

Indexing 4 emails——4 封 = 归档推送的 2 封(hk-test-0004/0005)+ 导入的 2 封(hk-import-0001/0002),数目对得上,导入与推送数据全部进入索引。

4.2 全站索引与概况

mailman-web update_index
?: settings.ACCOUNT_AUTHENTICATION_METHOD is deprecated, use: settings.ACCOUNT_LOGIN_METHODS = {'email', 'username'}
?: settings.ACCOUNT_EMAIL_REQUIRED is deprecated, use: settings.ACCOUNT_SIGNUP_FIELDS = ['email*', 'username*', 'password1*', 'password2*']
Indexing 4 emails
mailman-web haystack_info
?: settings.ACCOUNT_AUTHENTICATION_METHOD is deprecated, use: settings.ACCOUNT_LOGIN_METHODS = {'username', 'email'}
?: settings.ACCOUNT_EMAIL_REQUIRED is deprecated, use: settings.ACCOUNT_SIGNUP_FIELDS = ['email*', 'username*', 'password1*', 'password2*']
Number of handled 1 index(es).
  - Model: Email by Index: <hyperkitty.search_indexes.EmailIndex object at 0x793e8de1e990>
  • update_index:全站按模型增量更新(haystack 按 token 判新,重复执行只处理增量,幂等);
  • haystack_info:打印索引模型注册表——HyperKitty 只注册了一个 Email 索引模型;
  • rebuild_index:清空后全量重建(交互确认,加 --noinput 直接执行),索引损坏或换引擎后使用;
  • clear_index:仅清空索引(配合 rebuild 使用)。

4.3 导入结果验证

curl -s -o /dev/null -w 'list archive page: %{http_code}\n' \
  http://127.0.0.1/hyperkitty/list/testlist@example.com/
list archive page: 200

页面 200 + Indexing 4 emails + 站内搜索能命中导入主题,即导入闭环完成。

五、Django 工程管理命令

5.1 数据库与静态资源(安装与升级必用)

mailman-web migrate                 # 建表/增量迁移(升级版本后必跑)

复检回显(首装为逐条 Applying … OK):

Apply all migrations: account, admin, auth, contenttypes, django_mailman3, django_q, hyperkitty, postorius, sessions, sites, socialaccount
Running migrations:
  No migrations to apply.
mailman-web collectstatic --noinput

0 static files copied to '/opt/mailman/mm/static', 387 unmodified.
mailman-web compress --force
Compressing... done
Compressed 2 block(s) from 80 template(s) for 1 context(s).
  • collectstatic:把各 app 静态文件汇集到 STATIC_ROOT(nginx 直接托管;首装输出 387 static files copied 量级);
  • compress:Django Compressor 编译 SCSS/JS 压缩块(依赖系统 sassc;--force 强制重算);
  • 升级 HyperKitty 版本后的标准三连:migrate → collectstatic → compress,然后重启 mailman-web。

5.2 账号管理

mailman-web createsuperuser --noinput --username admin --email admin@example.com

(--noinput 创建无口令超管,配 shell 设密——见下。)

echo "from django.contrib.auth.models import User; u=User.objects.get(username=\"admin\"); u.set_password(\"q1w2e3r4\"); u.save(); print(\"password set for\", u.username, \"is_superuser=\", u.is_superuser)" \
  | mailman-web shell
password set for admin is_superuser= True

mailman-web shell 是 Django ORM 的交互入口:批量改用户、查归档数据、脚本化维护都走它;交互式改密也可用 mailman-web changepassword admin。

5.3 其他高频工程命令速查

命令用途
dbshell直连当前配置的数据库 CLI(postgres psql),查库排障最短路径
dumpdata / loaddata导出/导入 JSON 数据夹(迁移备小数据集)
findstatic <file>定位静态文件实际来源路径,排查 404
sendtestemail验证邮件后端连通性
checkDjango 系统自检(配置错误汇总)
diffsettings打印当前生效 settings 与默认值的差异,核对配置覆盖
clearsessions清理过期会话表(可入 cron 周任务)

六、定时任务与队列工具

HyperKitty 的后台任务(线程顺序重算、附件处理、增量索引等)由 django-q 承载:

命令用途实测说明
qcluster启动任务执行集群进程以服务形态常驻(systemd 或 uwsgi attach-daemon),不手工前台跑
qinfo队列成功/失败统计需要 Python 包 blessed,缺包时如实报错(见 FAQ 8.3)
qmonitor / qmemory队列实时监控/内存队列同样依赖 blessed
runjobs <period>立即触发定时任务组(minutely/hourly/daily…)cron 化部署时由系统 crontab 按周期调用

缺包现象(实测原始输出):

mailman-web qinfo
System check identified some issues:

WARNINGS:
?: settings.ACCOUNT_AUTHENTICATION_METHOD is deprecated, use: settings.ACCOUNT_LOGIN_METHODS = {'username', 'email'}
?: settings.ACCOUNT_EMAIL_REQUIRED is deprecated, use: settings.ACCOUNT_SIGNUP_FIELDS = ['email*', 'username*', 'password1*', 'password2*']
Blessed is not installed. Please install blessed to use this: https://pypi.org/project/blessed/

修复:pip install blessed(venv 内)后重跑即可看到队列统计面板。

七、归档 API 与排障工具

7.1 归档 API 直查(Token 认证)

归档推送链路的健康探针——用与 core 插件完全相同的调用方式直查 API(实测 200 即令牌与白名单双通过):

curl -s -o /dev/null -w '%{http_code}\n' \
  'http://127.0.0.1:8000/hyperkitty/api/mailman/urls?mlist=testlist@example.com' \
  -H 'Authorization: Token SecretArchiverAPIKey'
200

常用端点:/hyperkitty/api/mailman/urls(列表归档 URL 集)、/hyperkitty/api/mailman/archive(邮件推送入口,POST,由 core 插件调用)、/hyperkitty/api/mailman/subscription(订阅事件)。令牌即 settings.py 的 MAILMAN_ARCHIVER_KEY,来源须在 MAILMAN_ARCHIVER_FROM 白名单内。

7.2 归档链路排障三板斧

① spool 积压检查(推送失败即积压于此,正常应为 0):

ls -A /opt/mailman/mm/var/archives/hyperkitty/spool/ | wc -l
0

② core 侧归档日志(每封成功推送一行):

grep 'HyperKitty archived message' /opt/mailman/mm/var/log/mailman.log | tail -2
Oct 26 00:40:21 2026 (9930) HyperKitty archived message <hk-test-0004@example.com> to https://example.com/archives/list/testlist@example.com/message/LSYJ6VGPXOBKXXQFHCHC3ED5JGJE7ZMP/
Oct 26 00:40:22 2026 (9930) HyperKitty archived message <hk-test-0005@example.com> to https://example.com/archives/list/testlist@example.com/message/5UM26TOV44FCHPDMDPARZJSZHKNUKRKS/

③ uwsgi/nginx 进程与入口:

systemctl is-active mailman3 mailman-web nginx
curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1/hyperkitty/
active
active
active
200

(日志里的消息 URL 域名来自 Django 站点配置,实际访问路径为 /hyperkitty/list/<列表>/message/<短ID>/,解析差异见安装篇 FAQ。)

八、常见问题(FAQ)

Q1:hyperkitty_import 提示 not importing messages older than …,老邮件全没进来? 默认只导入「最近窗口」邮件(官方防误操作设计)。历史归档迁移必须加 --since:hyperkitty_import -l <list> --since=2000-01-01 <mbox>(3.2 节实测:默认跑被跳过、加 --since=2026-10-01 后两封邮件正常入库)。拿不准年份就给一个足够早的日期。

Q2:导入成功了但站内搜索搜不到? 导入不自动建索引。按导入输出末尾的官方提示执行 update_index_one_list <list>(实测 Indexing 4 emails),再搜即命中。新邮件的增量索引由 minutely 任务负责,只针对推送入库的信。

Q3:qinfo/qmonitor 报 Blessed is not installed? django-q 的终端统计面板依赖第三方包 blessed,venv 内 pip install blessed 后可用(实测报错原文见第六章);只想看队列是否堆积时,dbshell 查 django_q 表亦可。

Q4:所有命令前都有两行 ?: settings.ACCOUNT_… is deprecated,要处理吗? 无害告警:django-allauth 新版把 ACCOUNT_AUTHENTICATION_METHOD/ACCOUNT_EMAIL_REQUIRED 改名为 ACCOUNT_LOGIN_METHODS/ACCOUNT_SIGNUP_FIELDS。mailman-web 0.0.9 的 base settings 尚用旧名,升级模板包后消除;现阶段可忽略,强迫症可在 settings.py 里按新名覆盖。

Q5:hyperkitty_import 与 core 的 spool 有什么区别? 两个完全不同的机制:spool 是 core 侧归档插件推送失败的重试队列(.pck 文件,修好链路后自动补推,不碰它);hyperkitty_import 是主动把 mbox 历史数据一次性导入归档库的迁移工具。前者看 …/archives/hyperkitty/spool/ 清零,后者看导入输出与索引计数。

Q6:collectstatic 报目标目录不可写? STATIC_ROOT 目录属主须与 uwsgi 运行用户(mailman)一致:chown -R mailman:mailman /opt/mailman/mm/static 后重跑;nginx 只读托管该目录即可。

Q7:migrate 在升级后卡在某个 migration? 先 mailman-web showmigrations --list 看断点(对照 [hyperkitty]/[postorius]/[django_q] 节的完成标记),确认磁盘与数据库连通后重跑 migrate;跨大版本升级前先备份 mailmanweb 库(dbshell 或 pg_dump)。

Q8:能直接用 django-admin 吗? 能,但必须自行设置 MAILMAN_WEB_CONFIG/DJANGO_SETTINGS_MODULE 环境变量,否则加载到的是空配置。统一用 mailman-web 入口省去环境变量心智负担,本文所有命令均以此为准。

九、参考链接

(实测环境:Debian 12 + HyperKitty 1.3.12,全部命令与回显采集日期 2026-10-26)