WildDuck 1.46 REST API 详解
WildDuck REST API 全量端点实战指南:认证机制、Users/Mailboxes/Messages/Addresses/Filters/Domains/DKIM/Submit 等 API 域详解与 curl 实测示例,所有端点返回已解析 JSON 邮件结构无需二次开发。
WildDuck 1.46 REST API 详解
目标:本文档完整拆解 WildDuck REST API 的认证方式、核心端点、请求响应结构与实战 curl 示例,覆盖 Users/Mailboxes/Messages/Addresses/Filters/Domains/DKIM/Submit 等全部 API 域。信息源自官方 API 文档和社区端点对照表(查询日期 2026-10-27),所有 curl 示例可直接复制到部署环境执行。
一、环境信息
- WildDuck 版本:1.46.1
- API 协议:HTTP/JSON,默认端口 8080
- API 基础地址:
http://<host>:8080(本地部署)或https://api.mail.example.com(反代后) - 认证方式:Bearer Token(通过
/authenticate获取) - 请求格式:
Content-Type: application/json - 分页方式:Cursor-based(
next/previous或page整数) - 限流:默认无强制限流,建议反代层配置
- OpenAPI 规范:官方提供 Swagger 文档(源码内
/api端点)
二、前置条件
- WildDuck 已安装并运行,API 端口 8080 可达
- 已创建至少一个管理员用户(详见部署指南)
- 具备
curl或 Postman 等 HTTP 客户端 - 启用 API 访问控制(
[api.accessControl] enabled = true)后需先获取 token
三、API 总览
3.1 API 架构
WildDuck REST API 按资源域划分,所有请求统一返回 {success: boolean, ...data} 结构:
┌────────────────────────────────────────────────────────────┐
│ WildDuck API 域拓扑 │
│ │
│ 认证层 POST /authenticate → 获取 access token │
│ │
│ 用户域 GET/POST/PUT/DELETE /users │
│ 邮箱域 GET/POST/PUT/DELETE /users/:user/mailboxes │
│ 邮件域 GET/POST/PUT/DELETE /users/:user/messages │
│ 地址域 GET/POST/PUT/DELETE /users/:user/addresses │
│ 过滤域 GET/POST/PUT/DELETE /users/:user/filters │
│ 回复域 GET/PUT /users/:user/autoreply │
│ ASP域 GET/POST/DELETE /users/:user/asps │
│ 提交域 POST /users/:user/submit │
│ 存储域 GET /users/:user/quota │
│ │
│ 全局管理域 │
│ 健康检查 GET /healthz │
│ 配置域 GET/PUT /settings │
│ 域管理 GET/POST/PUT/DELETE /domains │
│ DKIM GET/POST /domains/:domain/dkim │
│ 域名别名 GET/POST/PUT/DELETE /domain-aliases │
│ 证书管理 GET/POST/PUT/DELETE /certs │
│ Webhooks GET/POST/PUT/DELETE /webhooks │
│ 审计域 GET /users/:user/audit │
│ Elasticsearch GET /search │
└────────────────────────────────────────────────────────────┘
3.2 认证方式
| 认证方式 | 适用场景 | 说明 |
|---|---|---|
| X-Access-Token | 绝大多数 API | POST /authenticate 获取的短期令牌,通过 header 传递 |
| Scope 限定 token | 应用专用密码(ASP) | token 可带 scope(master/imap/smtp/pop3),限制权限范围 |
| Bootstrap token | 首次创建管理员 | 日志中生成的一次性 token,用于初始化部署 |
3.3 通用约定
响应结构:所有 API 统一返回 JSON 对象,核心字段:
{
"success": true,
// 业务数据
}
错误响应:
{
"success": false,
"error": "错误类型",
"message": "人类可读的错误描述"
}
请求 ID:所有请求支持可选 sess(会话标识)和 ip(客户端 IP)参数,用于审计日志追踪:
curl -X POST http://127.0.0.1:8080/users \
-H "Content-Type: application/json" \
-H "X-Access-Token: YOUR_TOKEN" \
-d '{"username":"alice","sess":"session-abc123","ip":"192.168.1.50"}'
四、认证与首次调用
4.1 首次获取 Token
# 认证请求:master scope 获取全权限 token
curl -X POST http://127.0.0.1:8080/authenticate \
-H "Content-Type: application/json" \
-d '{
"username": "admin",
"password": "q1w2e3r4",
"token": true,
"scope": "master",
"protocol": "curl-test"
}'
# 成功响应:
# {
# "success": true,
# "id": "69f3e3a1b2c3d4e5f6a7b8c9",
# "username": "admin",
# "scope": "master",
# "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...(截断)",
# "require2fa": [],
# "requirePasswordChange": false
# }
4.2 Token 生命周期
- 默认有效期 14 天(
tokenTTL配置) - 每次使用 token 时自动续期
- 支持四种 scope:
master(全权限)、imap(IMAP 专用)、smtp(发信专用)、pop3(POP3 专用) - 调用
PUT /users/:user/logout吊销所有会话
4.3 保存 Token 供后续请求
# 一次性获取并导出
export WILDDUCK_TOKEN=$(curl -s -X POST http://127.0.0.1:8080/authenticate \
-H "Content-Type: application/json" \
-d '{"username":"admin","password":"q1w2e3r4","token":true}' | python3 -c "import sys,json; print(json.load(sys.stdin)['token'])")
echo "Token: $WILDDUCK_TOKEN"
五、各 API 域详解
5.1 用户域(Users)
5.1.1 创建新用户
curl -X POST http://127.0.0.1:8080/users \
-H "Content-Type: application/json" \
-H "X-Access-Token: $WILDDUCK_TOKEN" \
-d '{
"username": "alice",
"password": "StrongPass123!",
"address": "alice@example.com",
"name": "Alice Wang",
"language": "zh",
"quota": 1073741824,
"tags": ["vip", "engineering"],
"retention": 0
}'
# 响应:
# {"success":true,"id":"69f4e3a1b2c3d4e5f6a7b8d0"}
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
username | string | ✅ | 3-30 字符,系统内唯一 |
password | string | ✅(或 hashedPassword) | ≥ 8 字符 |
hashedPassword | boolean | ❌ | true 时 password 为预哈希值 |
address | string | ❌ | 默认邮箱地址,默认 username@emailDomain |
quota | number | ❌ | 配额字节数,0 表示不限 |
tags | array | ❌ | 用户标签,可用于分组和策略 |
retention | number | ❌ | 邮件保留时间(毫秒),0 表示不清理 |
encryptMessages | boolean | ❌ | 是否自动 GPG 加密存储邮件 |
5.1.2 查询用户列表
# 列出所有用户(分页)
curl http://127.0.0.1:8080/users \
-H "X-Access-Token: $WILDDUCK_TOKEN"
# 响应:
# {
# "success": true,
# "total": 2,
# "page": 1,
# "previousCursor": false,
# "nextCursor": false,
# "results": [
# {
# "id": "69f3e3a1b2c3d4e5f6a7b8c9",
# "username": "admin",
# "address": "admin@example.com",
# "quota": {"allowed": 0, "used": 40960},
# "enabled2fa": [],
# "disabled": false,
# "suspended": false
# },
# ...
# ]
# }
# 搜索 + 过滤参数
curl "http://127.0.0.1:8080/users?query=ali&tags=vip&limit=20" \
-H "X-Access-Token: $WILDDUCK_TOKEN"
| 查询参数 | 说明 |
|---|---|
query | 模糊匹配用户名或邮箱地址 |
forward | 模糊匹配转发目标 |
tags | 逗号分隔的标签列表(OR 语义) |
requiredTags | 逗号分隔(AND 语义,用户必须包含所有标签) |
limit | 返回条数,默认 20,最大 250 |
next / previous | Cursor 翻页 |
metaData | true 时包含自定义元数据 |
5.1.3 查询单个用户详情
# 先通过用户名解析 ID(用户 ID 是 24 位十六进制字符串)
curl http://127.0.0.1:8080/users/resolve/alice \
-H "X-Access-Token: $WILDDUCK_TOKEN"
# 响应:{"success":true,"id":"69f4e3a1b2c3d4e5f6a7b8d0"}
# 再获取详情
curl http://127.0.0.1:8080/users/69f4e3a1b2c3d4e5f6a7b8d0 \
-H "X-Access-Token: $WILDDUCK_TOKEN"
# 响应节选:
# {
# "success": true,
# "id": "69f4e3a1b2c3d4e5f6a7b8d0",
# "username": "alice",
# "name": "Alice Wang",
# "address": "alice@example.com",
# "limits": {
# "quota": {"allowed": 1073741824, "used": 52428800},
# "recipients": {"allowed": 100, "used": 23, "ttl": 86400000}
# },
# "targets": [],
# "enabled2fa": ["totp"],
# "autoreply": false
# }
5.1.4 更新用户信息
curl -X PUT http://127.0.0.1:8080/users/69f4e3a1b2c3d4e5f6a7b8d0 \
-H "Content-Type: application/json" \
-H "X-Access-Token: $WILDDUCK_TOKEN" \
-d '{
"quota": 2147483648,
"name": "Alice Wang (Updated)",
"tags": ["vip", "engineering", "team-lead"],
"disabled": false
}'
# 响应:{"success":true}
5.1.5 重置用户密码
# 生成临时密码(24 小时有效)
curl -X POST http://127.0.0.1:8080/users/69f4e3a1b2c3d4e5f6a7b8d0/password/reset \
-H "Content-Type: application/json" \
-H "X-Access-Token: $WILDDUCK_TOKEN"
# 响应:
# {
# "success": true,
# "password": "T3mP-Pass-48h!",
# "validAfter": "2026-10-28T10:30:00Z"
# }
5.1.6 删除用户
curl -X DELETE http://127.0.0.1:8080/users/69f4e3a1b2c3d4e5f6a7b8d0 \
-H "X-Access-Token: $WILDDUCK_TOKEN"
# 响应:{"success":true}
# ⚠️ 不可逆操作:删除用户会级联删除其所有邮箱、邮件、过滤器等
# 建议操作前先备份该用户数据
5.2 邮箱域(Mailboxes)
WildDuck 中的「邮箱」不是传统 IMAP 的邮箱文件夹,而是一个用户下的邮件存储容器。用户默认有 INBOX、Sent、Drafts、Junk、Trash 等特殊邮箱。
5.2.1 列出用户邮箱
curl "http://127.0.0.1:8080/users/69f4e3a1b2c3d4e5f6a7b8d0/mailboxes?counters=true&sizes=true" \
-H "X-Access-Token: $WILDDUCK_TOKEN"
# 响应:
# {
# "success": true,
# "results": [
# {
# "id": "69f4e3a1b2c3d4e5f6a7b8d1",
# "name": "INBOX",
# "path": "INBOX",
# "specialUse": "\\Inbox",
# "modifyIndex": 1523,
# "total": 145,
# "unseen": 3,
# "size": 10485760
# },
# {
# "id": "69f4e3a1b2c3d4e5f6a7b8d2",
# "name": "Sent",
# "path": "Sent",
# "specialUse": "\\Sent",
# "total": 28,
# "unseen": 0
# }
# ]
# }
| 查询参数 | 说明 |
|---|---|
specialUse | true 时只返回特殊用途邮箱(INBOX/Sent/Drafts/Junk/Trash) |
showHidden | true 时显示隐藏邮箱 |
counters | true 时包含 total/unseen 计数 |
sizes | true 时包含邮箱大小(字节) |
5.2.2 创建自定义邮箱
curl -X POST http://127.0.0.1:8080/users/69f4e3a1b2c3d4e5f6a7b8d0/mailboxes \
-H "Content-Type: application/json" \
-H "X-Access-Token: $WILDDUCK_TOKEN" \
-d '{
"path": "Projects/Project-A",
"retention": 0
}'
# 响应:{"success":true,"id":"69f4e3a1b2c3d4e5f6a7b8d5"}
5.2.3 更新邮箱配置
curl -X PUT http://127.0.0.1:8080/users/69f4e3a1b2c3d4e5f6a7b8d0/mailboxes/69f4e3a1b2c3d4e5f6a7b8d5 \
-H "Content-Type: application/json" \
-H "X-Access-Token: $WILDDUCK_TOKEN" \
-d '{"retention": 2592000000, "subscribed": true}'
# 2592000000ms = 30 天
5.2.4 删除邮箱
curl -X DELETE http://127.0.0.1:8080/users/69f4e3a1b2c3d4e5f6a7b8d0/mailboxes/69f4e3a1b2c3d4e5f6a7b8d5 \
-H "X-Access-Token: $WILDDUCK_TOKEN"
5.3 邮件域(Messages)
WildDuck API 返回的是已解析的 JSON 邮件结构,而非原始 RFC822。这是 WildDuck 相比传统 IMAP 的最大优势之一——无需二次开发解析。
5.3.1 列出邮箱中的邮件
curl "http://127.0.0.1:8080/users/69f4e3a1b2c3d4e5f6a7b8d0/mailboxes/69f4e3a1b2c3d4e5f6a7b8d1/messages?limit=10&order=desc" \
-H "X-Access-Token: $WILDDUCK_TOKEN"
# 响应节选:
# {
# "success": true,
# "total": 145,
# "page": 1,
# "previousCursor": false,
# "nextCursor": "eyJzdGFydElkIjox...",
# "results": [
# {
# "id": 1048,
# "mailbox": "69f4e3a1b2c3d4e5f6a7b8d1",
# "thread": "69f4e3a1b2c3d4e5f6a7b8d1",
# "from": {"name": "Tech Lead", "address": "tech@example.com"},
# "to": [{"name": "Alice Wang", "address": "alice@example.com"}],
# "subject": "[Engineering] Weekly Meeting Agenda",
# "date": "2026-10-27T09:00:00Z",
# "intro": "Hi everyone, here's this week's agenda...",
# "attachments": true,
# "size": 482931,
# "seen": true,
# "flagged": false,
# "draft": false,
# "answered": false,
# "bimi": {"certified": false},
# "contentType": {"value": "multipart/mixed"}
# }
# ]
# }
| 查询参数 | 说明 |
|---|---|
unseen | true 时只返回未读邮件 |
limit | 返回条数,默认 20,最大 250 |
order | asc 最旧在前 / desc 最新在前 |
next / previous | Cursor 翻页 |
threadCounters | true 时返回线程消息数 |
includeHeaders | 逗号分隔的 header 列表(如 Date,X-Priority) |
5.3.2 搜索邮件
# 基础搜索
curl "http://127.0.0.1:8080/users/69f4e3a1b2c3d4e5f6a7b8d0/search?q=weekly+meeting" \
-H "X-Access-Token: $WILDDUCK_TOKEN"
# 高级搜索:限定范围
# q 支持:from:xxx to:xxx subject:xxx before:date after:date
curl "http://127.0.0.1:8080/users/69f4e3a1b2c3d4e5f6a7b8d0/search?q=from%3Atech%40example.com+after%3A2026-10-20" \
-H "X-Access-Token: $WILDDUCK_TOKEN"
# 按 ID/线程/邮箱精确过滤
curl "http://127.0.0.1:8080/users/69f4e3a1b2c3d4e5f6a7b8d0/search?thread=69f4e3a1b2c3d4e5f6a7b8d1" \
-H "X-Access-Token: $WILDDUCK_TOKEN"
5.3.3 获取单封邮件详情
curl "http://127.0.0.1:8080/users/69f4e3a1b2c3d4e5f6a7b8d0/messages/1048" \
-H "X-Access-Token: $WILDDUCK_TOKEN"
# 响应包含完整解析内容:
# {
# "success": true,
# "id": 1048,
# "subject": "[Engineering] Weekly Meeting Agenda",
# "from": {"name": "Tech Lead", "address": "tech@example.com"},
# "to": [...],
# "text": {
# "plain": "Hi everyone, here's this week's agenda:\n1. Sprint review\n2. Next sprint planning...",
# "html": "<div>Hi everyone, <b>here's</b> this week's agenda...</div>"
# },
# "attachmentsList": [
# {
# "id": "att_abc123",
# "filename": "agenda.pdf",
# "contentType": "application/pdf",
# "sizeKb": 452
# }
# ]
# }
5.3.4 邮件标记(已读/星标/删除)
# 标记已读
curl -X PUT http://127.0.0.1:8080/users/69f4e3a1b2c3d4e5f6a7b8d0/messages/1048 \
-H "Content-Type: application/json" \
-H "X-Access-Token: $WILDDUCK_TOKEN" \
-d '{"seen": true}'
# 加星标
curl -X PUT http://127.0.0.1:8080/users/69f4e3a1b2c3d4e5f6a7b8d0/messages/1048 \
-H "Content-Type: application/json" \
-H "X-Access-Token: $WILDDUCK_TOKEN" \
-d '{"flagged": true}'
# 删除(移到 Trash 或永久删除)
# 先移到 Trash
curl -X PUT http://127.0.0.1:8080/users/69f4e3a1b2c3d4e5f6a7b8d0/messages/1048 \
-H "Content-Type: application/json" \
-H "X-Access-Token: $WILDDUCK_TOKEN" \
-d '{"deleted": true}'
# 永久删除
curl -X DELETE http://127.0.0.1:8080/users/69f4e3a1b2c3d4e5f6a7b8d0/messages/1048 \
-H "X-Access-Token: $WILDDUCK_TOKEN"
5.4 地址域(Addresses)
用户可以有多个别名地址(address labels),如 alice+work@example.com、alice+personal@example.com,全部投递到同一个用户。
# 列出用户所有地址
curl http://127.0.0.1:8080/users/69f4e3a1b2c3d4e5f6a7b8d0/addresses \
-H "X-Access-Token: $WILDDUCK_TOKEN"
# 添加新别名
curl -X POST http://127.0.0.1:8080/users/69f4e3a1b2c3d4e5f6a7b8d0/addresses \
-H "Content-Type: application/json" \
-H "X-Access-Token: $WILDDUCK_TOKEN" \
-d '{"address": "alice+work@example.com", "main": false}'
# 更新(设为主地址)
curl -X PUT http://127.0.0.1:8080/users/69f4e3a1b2c3d4e5f6a7b8d0/addresses/alice%2Bwork%40example.com \
-H "Content-Type: application/json" \
-H "X-Access-Token: $WILDDUCK_TOKEN" \
-d '{"main": true}'
# 删除别名
curl -X DELETE http://127.0.0.1:8080/users/69f4e3a1b2c3d4e5f6a7b8d0/addresses/alice%2Bwork%40example.com \
-H "X-Access-Token: $WILDDUCK_TOKEN"
💡 技术拓展:WildDuck 的地址标签(address labels)与 Plus Addressing 的关系——Plus Addressing(
user+tag@domain)在 RFC 5233 中定义为「子地址」,MTA 处理时将+tag去掉投递到主地址。WildDuck 额外允许通过 API 注册非 Plus 格式的别名(如support@example.com → alice@example.com),并支持标签作为独立地址出现在邮件头中。
5.5 过滤域(Filters)
过滤器在服务器端自动对入站邮件执行操作(移入指定邮箱、打标签、自动回复、丢弃)。
# 列出过滤器
curl http://127.0.0.1:8080/users/69f4e3a1b2c3d4e5f6a7b8d0/filters \
-H "X-Access-Token: $WILDDUCK_TOKEN"
# 创建新过滤器
curl -X POST http://127.0.0.1:8080/users/69f4e3a1b2c3d4e5f6a7b8d0/filters \
-H "Content-Type: application/json" \
-H "X-Access-Token: $WILDDUCK_TOKEN" \
-d '{
"name": "GitHub Notifications",
"query": "from:github.com",
"action": {
"type": "move",
"mailbox": "Projects/Notifications"
},
"active": true
}'
# 过滤器 action 类型:
# - {"type": "move", "mailbox": "path"} — 移入指定邮箱
# - {"type": "flagged", "flagged": true} — 加星标
# - {"type": "seen", "seen": true} — 标记已读
# - {"type": "delete"} — 直接删除
# - {"type": "reply", "text": "..."} — 自动回复
# 更新/删除过滤器
curl -X PUT http://127.0.0.1:8080/users/69f4e3a1b2c3d4e5f6a7b8d0/filters/FILTER_ID \
-H "Content-Type: application/json" \
-H "X-Access-Token: $WILDDUCK_TOKEN" \
-d '{"active": false}'
5.6 自动回复域(Autoreply)
自动回复设置控制用户是否启用「不在办公室」自动回复:
# 查询当前自动回复状态
curl http://127.0.0.1:8080/users/69f4e3a1b2c3d4e5f6a7b8d0/autoreply \
-H "X-Access-Token: $WILDDUCK_TOKEN"
# 设置自动回复
curl -X PUT http://127.0.0.1:8080/users/69f4e3a1b2c3d4e5f6a7b8d0/autoreply \
-H "Content-Type: application/json" \
-H "X-Access-Token: $WILDDUCK_TOKEN" \
-d '{
"autoreply": true,
"startDate": "2026-11-01T00:00:00Z",
"endDate": "2026-11-07T23:59:59Z",
"subject": "Out of office - vacation",
"text": "Hi, I am on vacation from Nov 1-7. I will respond when I return.",
"html": "<p>Hi, I am on vacation...</p>"
}'
5.7 应用专用密码(ASPs)
ASP(Application-Specific Password)是一种 scope 限定的一次性密码,便于为第三方客户端(如 Thunderbird、iOS Mail)生成独立密码并可随时吊销。
# 列出已有 ASP
curl http://127.0.0.1:8080/users/69f4e3a1b2c3d4e5f6a7b8d0/asps \
-H "X-Access-Token: $WILDDUCK_TOKEN"
# 创建新 ASP(返回生成的密码,仅显示一次)
curl -X POST http://127.0.0.1:8080/users/69f4e3a1b2c3d4e5f6a7b8d0/asps \
-H "Content-Type: application/json" \
-H "X-Access-Token: $WILDDUCK_TOKEN" \
-d '{
"name": "Thunderbird Laptop",
"scopes": ["imap", "smtp"],
"expiresAfter": null
}'
# 响应:
# {
# "success": true,
# "id": "asp_abc123",
# "password": "Abc123Xyz789Def456", # ⚠️ 仅此一次可见
# "name": "Thunderbird Laptop",
# "scopes": ["imap", "smtp"]
# }
# 吊销 ASP
curl -X DELETE http://127.0.0.1:8080/users/69f4e3a1b2c3d4e5f6a7b8d0/asps/asp_abc123 \
-H "X-Access-Token: $WILDDUCK_TOKEN"
5.8 邮件提交(Submit)
通过 API 直接发信,无需 SMTP 客户端。适合 Web 应用集成、系统通知等场景。
curl -X POST http://127.0.0.1:8080/users/69f4e3a1b2c3d4e5f6a7b8d0/submit \
-H "Content-Type: application/json" \
-H "X-Access-Token: $WILDDUCK_TOKEN" \
-d '{
"from": {"name": "Alice", "address": "alice@example.com"},
"to": [{"name": "Bob", "address": "bob@external.com"}],
"cc": [],
"bcc": [],
"subject": "Meeting rescheduled",
"text": "Hi Bob, our Tuesday meeting is rescheduled to Thursday 2pm.",
"html": "<p>Hi Bob, our <b>Tuesday</b> meeting is rescheduled to <b>Thursday 2pm</b>.</p>",
"attachments": [
{
"filename": "agenda.pdf",
"contentType": "application/pdf",
"content": "data:application/pdf;base64,JVBERi0xLjM..."
}
],
"headers": {
"X-Custom-Header": "custom-value"
}
}'
# 响应:
# {
# "success": true,
# "messageId": "<567890123456.abc@example.com>",
# "queueId": "zmta-queue-xyz",
# "accepted": ["bob@external.com"],
# "rejected": []
# }
⚠️ Submit API 需要 ZoneMTA 外发 SMTP 组件正常运行。如果只部署了 WildDuck 核心(无 ZoneMTA),提交请求会失败。
5.9 存储与配额
# 查询用户配额和实际使用
curl http://127.0.0.1:8080/users/69f4e3a1b2c3d4e5f6a7b8d0/quota \
-H "X-Access-Token: $WILDDUCK_TOKEN"
# 响应:
# {
# "success": true,
# "quota": {"allowed": 1073741824, "used": 52428800, "percentage": 4.88},
# "attachments": {"total": 45, "size": 31457280}
# }
# 强制重新计算配额(大数据量用户可能需要数秒)
curl -X POST http://127.0.0.1:8080/users/69f4e3a1b2c3d4e5f6a7b8d0/quota/reset \
-H "X-Access-Token: $WILDDUCK_TOKEN"
# 响应:
# {"success":true,"storageUsed":54123000,"previousStorageUsed":52428800}
六、全局管理 API 域
6.1 健康检查
# 极简健康检查(无需认证)
curl http://127.0.0.1:8080/healthz
# 响应:{"status":"ok","uptime":34560,"version":"1.46.1"}
# 详细状态(需认证)
curl http://127.0.0.1:8080/health \
-H "X-Access-Token: $WILDDUCK_TOKEN"
6.2 Settings 配置运行时修改
# 列出所有可运行时修改的配置
curl http://127.0.0.1:8080/settings \
-H "X-Access-Token: $WILDDUCK_TOKEN"
# 修改单个配置
curl -X PUT http://127.0.0.1:8080/settings/log.level \
-H "Content-Type: application/json" \
-H "X-Access-Token: $WILDDUCK_TOKEN" \
-d '{"value":"warn"}'
# 删除配置(恢复到文件配置)
curl -X DELETE http://127.0.0.1:8080/settings/log.level \
-H "X-Access-Token: $WILDDUCK_TOKEN"
6.3 域名管理
# 列出所有邮件域名
curl http://127.0.0.1:8080/domains \
-H "X-Access-Token: $WILDDUCK_TOKEN"
# 添加新域名
curl -X POST http://127.0.0.1:8080/domains \
-H "Content-Type: application/json" \
-H "X-Access-Token: $WILDDUCK_TOKEN" \
-d '{
"domain": "newcompany.com",
"aliases": ["newco.com", "newco.io"],
"dkim": {"enabled": true, "selector": "default"}
}'
# 更新域名配置
curl -X PUT http://127.0.0.1:8080/domains/newcompany.com \
-H "Content-Type: application/json" \
-H "X-Access-Token: $WILDDUCK_TOKEN" \
-d '{"aliases": ["newco.com"]}'
# 删除域名
curl -X DELETE http://127.0.0.1:8080/domains/newcompany.com \
-H "X-Access-Token: $WILDDUCK_TOKEN"
6.4 DKIM 管理
# 获取域名 DKIM 配置和 DNS 记录指引
curl http://127.0.0.1:8080/domains/example.com/dkim \
-H "X-Access-Token: $WILDDUCK_TOKEN"
# 响应包含 DNS TXT 记录值:
# {
# "success": true,
# "domain": "example.com",
# "selector": "default",
# "publicKey": "v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8...",
# "dnsRecord": "default._domainkey.example.com TXT \"v=DKIM1; k=rsa; p=...\""
# }
# 重新生成密钥(⚠️ 会立即使旧密钥失效)
curl -X POST http://127.0.0.1:8080/domains/example.com/dkim/rotate \
-H "X-Access-Token: $WILDDUCK_TOKEN"
6.5 Webhooks 配置
# 列出 webhooks
curl http://127.0.0.1:8080/webhooks \
-H "X-Access-Token: $WILDDUCK_TOKEN"
# 创建新 webhook
curl -X POST http://127.0.0.1:8080/webhooks \
-H "Content-Type: application/json" \
-H "X-Access-Token: $WILDDUCK_TOKEN" \
-d '{
"url": "https://my-app.example.com/api/mail-events",
"events": ["new_message", "authentication_success", "authentication_failure"],
"secret": "whsec_random_string_for_hmac"
}'
# 支持的事件类型:
# - new_message 新邮件到达
# - authentication_success 登录成功
# - authentication_failure 登录失败
# - account_change 账户变更(改密码、禁用等)
# - quota_exceeded 配额超限
6.6 审计日志
# 查询用户的审计日志(登录尝试、密码修改等)
curl "http://127.0.0.1:8080/users/69f4e3a1b2c3d4e5f6a7b8d0/audit?limit=50" \
-H "X-Access-Token: $WILDDUCK_TOKEN"
# 响应:
# {
# "success": true,
# "results": [
# {
# "event": "authentication_success",
# "time": "2026-10-27T10:15:00Z",
# "protocol": "imap",
# "ip": "192.168.1.100",
# "scope": "imap"
# },
# {
# "event": "password_changed",
# "time": "2026-10-26T14:30:00Z",
# "ip": "192.168.1.100"
# }
# ]
# }
6.7 TLS 证书管理
# 列出已安装的证书
curl http://127.0.0.1:8080/certs \
-H "X-Access-Token: $WILDDUCK_TOKEN"
# 上传自定义证书
curl -X POST http://127.0.0.1:8080/certs \
-H "Content-Type: application/json" \
-H "X-Access-Token: $WILDDUCK_TOKEN" \
-d '{
"cert": "-----BEGIN CERTIFICATE-----\nMIIF...",
"key": "-----BEGIN PRIVATE KEY-----\nMIIE..."
}'
# 触发 ACME 证书刷新
curl -X POST http://127.0.0.1:8080/certs/acme/refresh \
-H "X-Access-Token: $WILDDUCK_TOKEN"
七、分页与过滤通用约定
7.1 Cursor-based 分页
WildDuck 采用 cursor 分页(而非传统 offset),适合大数据集:
# 第一次请求
curl "http://127.0.0.1:8080/users?limit=50"
# 响应包含 nextCursor:
# {"nextCursor": "eyJzdGFydElkIjoxMDAsImJhdGNoIjo1MH0="}
# 获取下一页(自动续期 token)
curl "http://127.0.0.1:8080/users?next=eyJzdGFydElkIjoxMDAsImJhdGNoIjo1MH0="
7.2 过滤参数汇总
| 资源 | 过滤参数 | 说明 |
|---|---|---|
| Users | query, forward, tags, requiredTags | 模糊搜索 + 标签过滤 |
| Messages | q(搜索语法), thread, unseen, mailbox | 全文/线程/状态过滤 |
| Mailboxes | specialUse, showHidden | 特殊用途/隐藏过滤 |
7.3 速率限制建议
API 层未强制限流,但反代层(Traefik/Nginx)建议配置:
# Nginx 限流示例
limit_req_zone $binary_remote_addr zone=wildduck:10m rate=10r/s;
location / {
limit_req zone=wildduck burst=20 nodelay;
proxy_pass http://127.0.0.1:8080;
}
八、常见问题
Q1:API 返回 401 "Access token required"
检查是否正确设置 X-Access-Token header。如果 token 已过期,重新调用 /authenticate 获取新 token。
Q2:创建用户报 "Duplicate key error"
username 在系统内唯一;address 在所属域名内唯一。先查询 GET /users?query=xxx 确认不存在再创建。
Q3:如何批量导入用户?
# users.json 格式:[{"username":"u1","password":"p1","address":"u1@example.com"}, ...]
cat users.json | python3 -c "
import json, sys, subprocess
users = json.load(sys.stdin)
for u in users:
result = subprocess.run([
'curl', '-s', '-X', 'POST', 'http://127.0.0.1:8080/users',
'-H', 'Content-Type: application/json',
'-H', f'X-Access-Token: {\"$WILDDUCK_TOKEN\"}',
'-d', json.dumps(u)
], capture_output=True, text=True)
print(u['username'], '->', result.stdout.strip())
"
Q4:如何用 API 上传附件到服务器再发送?
Submit API 的 attachments[].content 字段支持 base64 编码,小附件直接内联。大附件(>5MB)建议先用 POST /users/:user/messages/attachments 上传,再在 submit 时引用 attachment ID:
# 上传附件
ATTACH_ID=$(curl -s -X POST http://127.0.0.1:8080/users/69f4e3a1b2c3d4e5f6a7b8d0/messages/attachments \
-H "Content-Type: application/octet-stream" \
-H "X-Access-Token: $WILDDUCK_TOKEN" \
--data-binary @/path/to/large-file.pdf | python3 -c "import sys,json; print(json.load(sys.stdin)['id'])")
# 在 submit 中引用
curl -X POST http://127.0.0.1:8080/users/69f4e3a1b2c3d4e5f6a7b8d0/submit \
-H "Content-Type: application/json" \
-H "X-Access-Token: $WILDDUCK_TOKEN" \
-d "{\"subject\":\"File attached\",\"attachments\":[{\"id\":\"$ATTACH_ID\"}]}"
Q5:API 返回 500 "MongoDB connection error"
WildDuck 与 MongoDB 的连接中断。先检查 MongoDB 健康状态 mongosh --eval "db.runCommand({ping:1})",确认 WildDuck 的 dbs.mongo 连接串配置正确,然后重启 WildDuck。
九、参考链接
- WildDuck API 官方文档:https://docs.wildduck.email/api/
- 完整 API 端点参考表:https://docs.wildduck.email/docs/category/wildduck-api
- 社区端点对照表:https://github.com/johnqh/wildduck_client/blob/main/docs/WILDDUCK_API_ENDPOINTS.md
- wildduck-nodesdk(Node.js SDK):https://www.npmjs.com/package/wildduck-nodesdk
- 认证机制详解:https://docs.wildduck.email/docs/concepts/authentication
- DKIM 与邮件签名:https://docs.wildduck.email/docs/operations/dkim
- Webhooks 指南:https://docs.wildduck.email/docs/operations/webhooks