Sign inGet Started

在 CI 中检查邮件模板

bird email templates check 从任何 CI 系统检查你的邮件模板,并在变更会导致模板损坏时以失败退出,让 pull request 在收件人发现问题之前拦截它。它只读取数据:不会发送任何内容,也不会更改草稿。

开始之前

  • 使用固定版本安装 bird CLI,这样新版本不会在未通知的情况下更改你的流水线。
  • 创建一个对 email_management 具有读取权限的 API 密钥,并将其作为 BIRD_API_KEY 提供给作业。

检查模板

代码示例
bird email templates check welcome-email order-shipped
该命令会渲染每个模板草稿的所有语言版本,因为翻译本身可能出问题,并按模板和语言报告:
  • 邮件客户端兼容性:与模板预览显示的兼容性结果相同,例如客户端会移除或忽略的 CSS。
  • 大小:HTML 正文与 Gmail 约 102 KB 的截断点的对比。Gmail 会将超出部分隐藏在一个链接后面。超过 90 KB 时检查会发出警告,因为合并变量可能使消息超限。
  • 链接和图片:链接(<a> 和 <area>)、图片来源或 srcset、background 属性,或 style 属性或 <style> 块中 CSS url() 里的每个 http 和 https URL,均从命令运行的位置进行抓取。404、410 或 5xx,或不存在的主机,视为问题。401、403 或 429,或 DNS 查询超时,视为警告,因为这通常意味着运行器被拒绝或无法到达主机。指向私有地址或回环地址的链接永远不会被抓取。在没有出站网络访问权限的运行器上传入 --skip-links。
由模板变量、联系人字段或退订链接构建的链接不会被抓取,因为预览无法用收件人实际收到的值填充它们。报告将它们列在 unverified_links 下,逐收件人部分显示为 {variable},--annotations github 会将其作为通知打印,以便 pull request 显示哪些内容未被检查。
该命令在 stdout 上打印 JSON 报告:首先是整个运行的 valid,然后是每个模板和语言的条目及其 findings。每项发现包含一个 severity、一个 area(compatibility、size 或 links)、一个 message,通常还有一个 fix。problem 会导致检查失败;warning 仅被报告,不会导致失败。

检查构建渲染的文件

如果你的构建自行渲染模板,例如使用 MJML 或 React Email,可以检查它生成的文件:
代码示例
bird email templates check --html dist/welcome.html --template welcome-email --annotations github
该文件作为未保存的内容针对你指定的模板进行预览,因此不会更改草稿;任何模板都可以使用。使用 --annotations github 时,兼容性结果会标注在文件中对应的行上,大小和链接结果则标注在整个文件上。

退出码

退出码是你的 CI 作业据以分支的依据:
退出码含义
0无问题。仍可能报告警告。
7检查已运行并发现至少一个问题。报告会列出每个问题。
3你指定的模板在此工作区中不存在。
4API 密钥缺失、无效,或缺少对 email_management 的读取权限。
6被限速或临时服务器错误。在 retry_after 延迟后重试。
对 7 不做更改地重试会以相同方式失败,因此只有 6 值得重试。

在 GitHub Actions 中运行

使用 --annotations github 时,命令会将结果以 GitHub Actions 注解而非 JSON 报告的形式打印,使其显示在 pull request 的检查中。以下工作流会在每个更改模板的 pull request 上检查你的构建所渲染的模板:
代码示例
name: Email templates
on:
  pull_request:
    paths: ["emails/**"]
jobs:
  check:
    # Pull requests from forks get no repository secrets, so the check could only exit 4.
    if: ${{ !github.event.pull_request.head.repo.fork }}
    runs-on: ubuntu-latest
    env:
      BIRD_API_KEY: ${{ secrets.BIRD_API_KEY }}
    steps:
      - uses: actions/checkout@v4
      - name: Install the bird CLI
        run: curl -fsSL https://cli.bird.com/install.sh | sh -s -- --version "${{ vars.BIRD_CLI_VERSION }}"
      - name: Build the templates
        run: npm ci && npm run build:emails
      - name: Check the templates
        run: |
          status=0
          for file in dist/emails/*.html; do
            bird email templates check --html "$file" --template welcome-email --annotations github || status=$?
          done
          exit "$status"
将 BIRD_CLI_VERSION 设为仓库变量,值为你测试过的发行版,并将 BIRD_API_KEY secret 设为具有 email_management 读取权限的密钥。GitHub 不会向来自 fork 的 pull request 提供仓库 secret,因此工作流会跳过它们。在合并来自 fork 的变更之前,将相同的变更推送到你仓库的分支上进行检查。在任何其他 CI 系统中,运行相同的命令并在退出码非零时让作业失败。

故障排除

  • 退出 3。 该模板不在 API 密钥所属的工作区中。使用 bird email templates list 列出工作区的模板。
  • 退出 4。 密钥缺少对 email_management 的读取权限,或 secret 未传递到作业中。
  • 所有链接均以警告形式失败。 运行器没有出站网络访问权限,或被防火墙阻止。在那里使用 --skip-links 运行,并从能够访问互联网的运行器检查链接。

后续步骤