在 CI 中运行
本页由英文自动翻译。
阅读英文版在你电脑上通过的测试,只需一处改动就能在 CI 中运行:API 密钥 从 CI 系统的 secrets 中读取。本页介绍这一点、如何使用地址让并行运行互不干扰、在 pull request 上提供每次运行的邮件报告,以及如何为云端编程智能体提供访问权限。
将 API 密钥 作为 secret
Section titled “将 API 密钥 作为 secret”在应用的 Project settings → API keys 下创建密钥(参阅 API 密钥),并存为名为 PROXYMAIL_QA_API_KEY 的 secret。在 GitHub Actions 中:
jobs: e2e: runs-on: ubuntu-latest steps: - uses: actions/checkout@v7 - uses: actions/setup-node@v7 with: node-version: 22 - run: npm ci - run: npx playwright install --with-deps - run: npx playwright test env: PROXYMAIL_QA_API_KEY: ${{ secrets.PROXYMAIL_QA_API_KEY }}其他 CI 系统也一样:GitLab 中的 masked CI/CD 变量,CircleCI 中的 context 或项目变量,Jenkins credentials 中的环境变量。不要把密钥放进代码仓库或日志。
密钥只在一个项目中有效,所以请为 CI 单独建一个项目(至少单独一个密钥)。这样它的地址与你手动使用的地址分开,撤销 CI 密钥也不会影响任何人。
每次运行一个地址,配合加号标签
Section titled “每次运行一个地址,配合加号标签”免费账号总共 500 个地址,每天最多 50 个,繁忙的流水线可能会用完;Team 套餐不限数量。你不需要为每个测试新建地址:发往 name+anything@ 的邮件会到达 name@,在带标签的地址上等待只会找到发往该标签的邮件。
所以为每次运行创建一个地址,并给每个测试一个自己的标签:
// Once per run (Playwright's globalSetup, say): POST /v1/addressesconst base = 'k7f2x9ab12cd@mailclub.dev';
// In each test: sign up with a tagged version of it…const address = base.replace('@', `+${process.env.GITHUB_RUN_ID}-${testInfo.workerIndex}-${Date.now()}@`);// …then wait on that same tagged address.// GET /v1/addresses/{address}/code only finds mail sent to that tag.使用 Node.js 客户端 时,就是调用一次 qa.createAddress(),每个测试调用一次 qa.waitForCode(tagged, { since })。
有些应用的注册表单不接受 +;对于这些应用,请改为每个测试创建一个地址。特殊的邮件地址 列出了标签可以包含哪些字符。
传入 since,值为测试提交表单的时间,这样等待就不会拿到之前步骤或运行的邮件:
const submitted = new Date();await page.getByRole('button', { name: 'Sign up' }).click();// GET /v1/addresses/{address}/code?since=<submitted, ISO 8601>并行 worker
Section titled “并行 worker”每个密钥每分钟可发出 60 次请求(免费)或 600 次(Team)(限制)。一次等待无论持续多久(最长 30 秒)都只算一次请求,所以免费套餐下跑几个并行 worker 没有问题。大型测试套件请使用 Team 套餐,或每条流水线一个密钥。
在运行结束时用 DELETE /v1/addresses/{address} 删除地址,例如在 Playwright 的 globalTeardown 中。没删除的地址会在过期时自动删除。删除基础地址也会删除发往其标签的邮件。
pull request 上的报告
Section titled “pull request 上的报告”Proxy Mail QA action 会把一个 job 的邮件测试归为一次 run,并把结果发布到 pull request 上:哪些邮件到达了、在测试提交后多久到达、验证码、每个链接指向哪里、你运行的邮件检查(在 Labs 中开启垃圾邮件检查时,还包括可能有多少封邮件会进入垃圾箱)、退订、优惠和优惠券检查、失败的测试,以及所有没到的邮件。同一份报告也会写入 job summary,项目中的每个人都可以在应用中打开这次 run,QA report for this run 会把这次 run 的地址和邮件生成一份 QA 报告,可打印或另存为 PDF。
jobs: e2e: runs-on: ubuntu-latest permissions: contents: read pull-requests: write steps: - uses: actions/checkout@v7 - uses: aaquib90/proxymail-qa-action@v1 with: api-key: ${{ secrets.PROXYMAIL_QA_API_KEY }} - run: npm ci - run: npx playwright test env: PROXYMAIL_QA_API_KEY: ${{ secrets.PROXYMAIL_QA_API_KEY }}该 action 会为其后的步骤设置 PROXYMAIL_QA_RUN。Node.js 客户端(0.5.0 或更高版本)、Python helper 以及 Detox 和 Appium helper 会读取它,所以测试中已有的调用都会计入这次 run。其他移动端 helper 用接收密钥的方式接收它:XCUITest 用环境变量,Espresso 用 instrumentation 参数,Flutter 用 --dart-define,Maestro 用 -e。其他工具请在请求头中发送该 id:Proxy-Mail-QA-Run: $PROXYMAIL_QA_RUN。
job 结束后,无论是否通过,该 action 都会结束这次 run 并发布报告,每次 push 都会更新其评论。以下情况 run 会失败:测试等待的邮件没到、不该来的邮件来了、邮件检查失败、测试失败、退订后仍收到营销邮件、同一人拿到两次优惠、不该被接受的优惠券被接受,或某条备注要求判为失败。如果希望此时即使测试通过也让 job 失败,请设置 fail-job: true。同名的 run 共用一条评论,所以请给 matrix job 各自命名:name: e2e (${{ matrix.browser }})。
报告还会把这次运行与同名的最近 10 次已完成运行进行比较,并列出变化:到达时间比平常长很多的邮件、现在收到两封而不是一封邮件的测试、首次失败或时好时坏的测试、新出现失败的邮件检查、上次通过但这次没有运行或失败的步骤(等待、计数、退订、优惠和优惠券检查),以及新的发件人或链接站点。每次运行保持相同的名称,这些比较才能生效。
来自 fork 的 pull request 拿不到 secrets,所以在这种情况下 action 会发出警告,不会启动运行。
@v1 跟随每个 1.x 版本,所以修复会自动到达,你无需改动。如果只想在自己选择时接受变更,可以改为固定某个版本的 commit,并在注释中写上版本号:uses: aaquib90/proxymail-qa-action@<commit> # v1.0.1。commit 列在标签页面上,Dependabot 会让固定的 commit 保持最新。
一次运行会保存地址、验证码(包括优惠券的折扣和结账时的返回结果)、耗时、检查结论、失败测试的名称和错误,以及每个链接的站点和路径,路径中看起来像 token 的部分会被隐藏。它从不保存邮件的正文或主题,也不保存链接的查询参数,登录 token 通常就在那里。运行记录保留 90 天。
在其他地方(另一个 CI 系统,或智能体的会话中),用 POST /v1/runs 启动运行,在 Proxy-Mail-QA-Run header 中发送它的 id,用 POST /v1/runs/{id}/finish 结束运行,再用 GET /v1/runs/{id}?format=markdown 获取报告。使用 Node.js 客户端时,对应的是 qa.startRun()、qa.finishRun() 和 qa.runReport()。参见 REST API。
每封邮件来自哪个测试
Section titled “每封邮件来自哪个测试”报告可以说明每封邮件属于哪个测试,并列出失败的测试及其邮件的情况。
Playwright:从 proxymail-qa/playwright 导入 test,使用它的 qa fixture(一个在每次调用中都带上测试名称的客户端),并添加 reporter,它会记录失败和不稳定的测试以及总数。失败测试的那一行会写明失败的步骤或浏览器操作(例如 At “Enter the code › locator.fill(…)”):
export default defineConfig({ reporter: [['list'], ['proxymail-qa/playwright/reporter']],});import { test, expect } from 'proxymail-qa/playwright';
test('sign-up sends one code', async ({ page, qa }) => { const { address } = await qa.createAddress(); // …sign up, wait for the code, check the email…});pytest:把 Python helper 的 hooks 导入 conftest.py:
from proxymail_qa import pytest_runtest_setup, pytest_runtest_teardown, pytest_runtest_logreport, pytest_sessionfinish移动端测试:每个移动端 helper 都接收测试名称:Swift、Kotlin 和 Dart 中是 ProxyMailQA(test:),Maestro 脚本的 env 中是 TEST,Detox 和 Appium 中是当前的 Jest 测试(或 setTest)。
其他工具在 Proxy-Mail-QA-Test header 中发送经过百分号编码的测试名称,并把结果发送到 POST /v1/runs/{id}/tests(REST API)。两者在运行之外都不起作用,也绝不会让测试本身失败。
在 CI 中什么都没收到时
Section titled “在 CI 中什么都没收到时”当等待返回空结果时,响应会在 Proxy Mail QA 能判断的范围内说明原因(hint,以及针对我们拒收的邮件的 refused)。在 CI 中,常见原因是 staging 环境的邮件服务商:处于 sandbox 或测试模式时,它只向已验证的地址发送,所以邮件根本没有发出。GET /v1/addresses/{address}/delivery 可以不等待就检查一个地址。更多内容见测试邮件收不到?
如果所有运行同时失败,或者 API 返回 5xx 错误,请先查看我们的状态页面,再修改你的测试。
云端的编程智能体
Section titled “云端的编程智能体”通过浏览器登录 MCP server 需要人来操作,所以在云端运行的智能体改用 API 密钥,以 Bearer 令牌 的形式发送。给它们一个专门为此创建的项目的密钥。
Claude Code GitHub Action
Section titled “Claude Code GitHub Action”在 action 之前的一个步骤中写入 MCP 配置,密钥取自 secret,并允许智能体需要的工具:
- name: Proxy Mail QA for Claude run: | cat > /tmp/mcp.json << 'EOF' { "mcpServers": { "proxymail-qa": { "type": "http", "url": "https://api.proxymail.qa/mcp", "headers": { "Authorization": "Bearer ${{ secrets.PROXYMAIL_QA_API_KEY }}" } } } } EOF - uses: anthropics/claude-code-action@v1 with: anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} claude_args: | --mcp-config /tmp/mcp.json --allowedTools mcp__proxymail-qa__get_project,mcp__proxymail-qa__create_address,mcp__proxymail-qa__wait_for_code,mcp__proxymail-qa__wait_for_link,mcp__proxymail-qa__check_delivery,mcp__proxymail-qa__delete_addressGitHub Copilot 编程智能体
Section titled “GitHub Copilot 编程智能体”在仓库的 Settings → Copilot → MCP servers 中添加:
{ "mcpServers": { "proxymail-qa": { "type": "http", "url": "https://api.proxymail.qa/mcp", "headers": { "Authorization": "Bearer $COPILOT_MCP_PROXYMAIL_QA_API_KEY" }, "tools": ["get_project", "create_address", "wait_for_code", "wait_for_link", "check_delivery", "delete_address"] } }}然后在仓库的 copilot 环境中,把密钥添加为名为 COPILOT_MCP_PROXYMAIL_QA_API_KEY 的 Agents secret:Copilot 只会把名称以 COPILOT_MCP_ 开头的 secrets 传给 MCP 服务器。Copilot 的编程智能体无法通过浏览器登录,所以需要密钥。
在 CI 任务中使用 Codex CLI(codex exec)时,把服务器添加到 ~/.codex/config.toml,并用 CI secret 设置 PROXYMAIL_QA_API_KEY:
[mcp_servers.proxymail-qa]url = "https://api.proxymail.qa/mcp"bearer_token_env_var = "PROXYMAIL_QA_API_KEY"Codex 的文档没有说明它的云端任务能否访问远程 MCP 服务器。如果你的不能,请让 Codex 改为调用 REST API,密钥取自环境设置。
对本页有疑问?
可以用任何语言提问。文档可以立即回答,你也可以把问题发给 Proxy Mail QA 团队,他们会用英文回复。