Mailexam REST API¶
Mailexam REST API 可编程管理项目、收件箱和邮件,适用于自动化测试、QA 与 CI/CD。典型流程:应用通过 SMTP 发送邮件,测试通过 API 确认投递并校验主题、正文或附件。
完整 OpenAPI 规范见 Swagger UI。
基础 URL¶
| 参数 | 值 |
|---|---|
| 基础地址 | https://mailexam.cn/api/v1 |
| 格式 | JSON |
| 方法 | GET、POST、PUT、DELETE |
认证¶
所有请求需要 Mailexam 控制台 中的 API 令牌。
令牌通过 query 参数 token 传递:
CI/CD 密钥
不要将令牌提交到代码仓库。在 GitLab CI、GitHub Actions 等 pipeline 中将 MAILEXAM_API_TOKEN 设为密钥变量。
| 状态码 | 含义 |
|---|---|
200 / 201 |
成功 |
403 |
权限不足或令牌无效 |
404 |
未找到对应 UUID 的对象 |
CI/CD 典型流程¶
- 应用通过 SMTP 发送邮件(见集成示例)。
- 等待投递,通常 1–5 秒。
- 通过 API 获取项目 → 收件箱 → 邮件列表。
- 按主题或收件人找到邮件并校验内容。
sequenceDiagram
participant App as 应用
participant SMTP as Mailexam SMTP
participant API as REST API
participant Test as 自动化测试
App->>SMTP: sendMail()
Note over SMTP: 邮件进入 sandbox
Test->>API: GET /project
Test->>API: GET /inbox?project=...
Test->>API: GET /email?inbox=...
Test->>Test: 断言主题、正文
接口参考¶
项目 (/project)¶
| 方法 | 路径 | 说明 |
|---|---|---|
GET |
/project |
项目列表 |
POST |
/project/store |
创建项目 |
GET |
/project/{uuid} |
项目详情 |
PUT |
/project/{uuid}/update |
更新项目 |
DELETE |
/project/{uuid}/delete |
删除项目 |
创建/更新请求体:
响应示例 (ProjectResponse):
{
"uuid": "536a47df-5aad-44d0-8163-a39bb55abe0b",
"name": "我的项目",
"description": null,
"user": {
"uuid": "984f1f70-21e1-4244-bbb7-734ac151dcdc",
"name": "Mailexam 支持",
"email": "support@mailexam.cn"
}
}
收件箱 (/inbox)¶
| 方法 | 路径 | 说明 |
|---|---|---|
GET |
/inbox?project={uuid} |
项目下的收件箱列表 |
POST |
/inbox/store |
创建收件箱 |
GET |
/inbox/{uuid} |
收件箱详情 |
PUT |
/inbox/{uuid}/default |
设为默认收件箱 |
PUT |
/inbox/{uuid}/update |
更新收件箱 |
DELETE |
/inbox/{uuid}/delete |
删除收件箱 |
创建请求体 (InboxRequest):
{
"project_uuid": "536a47df-5aad-44d0-8163-a39bb55abe0b",
"name": "全部邮件",
"has_autorelay": false,
"relay_host": null,
"relay_port": null,
"relay_pass": null
}
邮件 (/email)¶
| 方法 | 路径 | 说明 |
|---|---|---|
GET |
/email?inbox={uuid} |
收件箱中的邮件列表 |
GET |
/email/{uuid} |
完整邮件(正文、头) |
GET |
/email/{uuid}/attachment?cid={id} |
附件 |
PUT |
/email/{uuid}/unread |
未读标记 |
PUT |
/email/{uuid}/like |
点赞 |
PUT |
/email/{uuid}/dislike |
点踩 |
PUT |
/email/{uuid}/relay |
转发到 SMTP 服务器 |
DELETE |
/email/{uuid}/delete |
删除邮件 |
简短格式 (EmailShort):
{
"uuid": "e2f9a506-d766-4935-be11-c413384de020",
"from": "\"Mailexam\" <support@mailexam.cn>",
"to": "Mailexam 支持 <support@mailexam.cn>",
"cc": null,
"subject": "Mailexam 连接参数",
"human_size": "113 字节",
"date": "2025-03-01T08:58:49.000000Z",
"attachments": true,
"unread": false,
"like": true,
"dislike": false
}
完整格式 (EmailDetailed) 还包含 body(html、text、raw、attachments)、headers 和 relay。
示例:用 curl 校验邮件¶
环境变量:
示例:Python 自动化测试¶
SMTP 发送后按主题查找邮件并校验正文。
import os
import time
import urllib.parse
import urllib.request
import json
API_BASE = os.environ.get("MAILEXAM_API_BASE", "https://mailexam.cn/api/v1")
TOKEN = os.environ["MAILEXAM_API_TOKEN"]
PROJECT_UUID = os.environ["MAILEXAM_PROJECT_UUID"]
EXPECTED_SUBJECT = "CI 检查"
def api_get(path, params=None):
params = dict(params or {})
params["token"] = TOKEN
url = f"{API_BASE}{path}?{urllib.parse.urlencode(params)}"
with urllib.request.urlopen(url) as resp:
return json.loads(resp.read().decode())
def wait_for_email(subject, timeout=30, interval=2):
inboxes = api_get("/inbox", {"project": PROJECT_UUID})
inbox_uuid = inboxes[0]["uuid"]
deadline = time.time() + timeout
while time.time() < deadline:
emails = api_get("/email", {"inbox": inbox_uuid})
for item in emails:
if item["subject"] == subject:
return api_get(f"/email/{item['uuid']}")
time.sleep(interval)
raise TimeoutError(f"未在 {timeout} 秒内找到主题「{subject}」的邮件")
if __name__ == "__main__":
# ... 在此通过 SMTP 发送邮件 ...
time.sleep(3)
email = wait_for_email(EXPECTED_SUBJECT)
body_text = (email.get("body") or {}).get("text") or ""
assert "你好" in body_text, "正文不匹配"
print("OK")
仅使用 Python 3 标准库。若项目中已有 requests 或 httpx 也可使用。
示例:Node.js 自动化测试¶
const TOKEN = process.env.MAILEXAM_API_TOKEN;
const API_BASE = process.env.MAILEXAM_API_BASE || 'https://mailexam.cn/api/v1';
const PROJECT_UUID = process.env.MAILEXAM_PROJECT_UUID;
const EXPECTED_SUBJECT = 'CI 检查';
async function apiGet(path, params = {}) {
const query = new URLSearchParams({ ...params, token: TOKEN });
const res = await fetch(`${API_BASE}${path}?${query}`);
if (!res.ok) throw new Error(`${res.status} ${path}`);
return res.json();
}
async function waitForEmail(subject, timeoutMs = 30000, intervalMs = 2000) {
const inboxes = await apiGet('/inbox', { project: PROJECT_UUID });
const inboxUuid = inboxes[0].uuid;
const deadline = Date.now() + timeoutMs;
while (Date.now() < deadline) {
const emails = await apiGet('/email', { inbox: inboxUuid });
const match = emails.find((item) => item.subject === subject);
if (match) return apiGet(`/email/${match.uuid}`);
await new Promise((r) => setTimeout(r, intervalMs));
}
throw new Error(`未在 ${timeoutMs / 1000} 秒内找到「${subject}」`);
}
(async () => {
// ... SMTP 发送 ...
await new Promise((r) => setTimeout(r, 3000));
const email = await waitForEmail(EXPECTED_SUBJECT);
const text = email.body?.text || '';
if (!text.includes('你好')) throw new Error('正文不匹配');
console.log('OK');
})().catch((err) => {
console.error(err);
process.exit(1);
});
需要 Node.js 18+(内置 fetch)。
GitLab CI¶
integration_test:
stage: test
variables:
MAILEXAM_API_BASE: "https://mailexam.cn/api/v1"
MAILEXAM_PROJECT_UUID: "536a47df-5aad-44d0-8163-a39bb55abe0b"
script:
- python send_and_verify.py
# MAILEXAM_API_TOKEN、MAILEXAM_LOGIN、MAILEXAM_PASSWORD — 在 CI/CD Variables 中配置
SMTP 凭据(MAILEXAM_LOGIN、MAILEXAM_PASSWORD)与 API 令牌是不同的值:前者用于发送,后者用于 REST 读取。
与 Mailtrap API 对照¶
从 Mailtrap 迁移 时替换 Sandbox API 调用:
| 任务 | Mailtrap | Mailexam |
|---|---|---|
| 邮件列表 | Sandbox API | GET /email?inbox={uuid} |
| 单封邮件 | Sandbox API | GET /email/{uuid} |
| 附件 | Sandbox API | GET /email/{uuid}/attachment?cid={id} |
| 管理 sandbox | Sandboxes API | GET /project、/inbox |
常见问题¶
403 Forbidden
- 确认令牌完整且以
?token=...传递。 - 令牌属于您的账户 — 确认项目在同一用户下。
邮件列表为空
- 邮件可能进入其他项目或收件箱 — 核对 SMTP 登录名与对应项目。
- 增加 SMTP 发送后的等待时间(2–5 秒)或使用带超时的轮询。
控制台可见但测试找不到
- 按精确主题过滤,或按 API 响应中的
date检查最新邮件。 - 附件需先获取
EmailDetailed,再按cid下载。