AI 邮件通讯 / Responsive Email & Newsletter
写一封在 Gmail、Outlook、Apple Mail 都不破版的响应式 HTML 邮件,而不用手搓 table 套 table 的祖传代码。你用 MJML 的语义标签描述版式,官方 mjml CLI 本地把它编译成可直接群发的 .html,再用无头浏览器截出桌面 + 手机两种宽度的真实预览。
Write one responsive HTML email that renders cleanly in Gmail, Outlook, and Apple Mail — without hand-coding nested tables. You describe layout with MJML's semantic tags, the official mjml CLI compiles it locally into a send-ready .html, and a headless browser captures real desktop + mobile previews.
底层工具是开源的 MJML(Mailjet 出品,MIT)。核心链路在本机离线运行:写 .mjml → mjml 编译 .html → 截图。文案由你(agent)自己产出。只有当用户明确要 AI 插图且提供了 Clawvard API key 时,才走可选的 Clawvard SDK 出图分支——缺 key 时主路径照常跑通。
你会拿到 / What you get
newsletter.html—— 真实编译出的响应式邮件,可直接粘进邮件服务(Mailchimp / 飞书 / SES / Resend …)群发。newsletter-desktop.png+newsletter-mobile.png—— 桌面(600px 邮件列宽)和手机(~360px)的真实渲染截图,肉眼确认窄屏自动堆叠、不破版。
0. 准备 / Install
node -v # 需要 Node ≥ 18
npm install -g mjml
mjml --version # 5.x
官方 CLI,直接用,不需要 clone 任何仓库、不需要 wrapper。
1. 用语义标签写 .mjml
MJML 的核心心智:section(行)→ column(列)→ 内容组件。列在窄屏自动堆叠,这就是响应式的来源。
<mjml>
<mj-head>
<mj-title>5 月产品月报</mj-title>
<mj-preview>收件箱预览那一行字</mj-preview>
<mj-attributes>
<mj-all font-family="-apple-system, 'Segoe UI', Roboto, Arial, sans-serif" />
<mj-text font-size="15px" color="#3f3a33" line-height="1.65" />
</mj-attributes>
</mj-head>
<mj-body background-color="#f4efe7" width="600px">
<mj-section background-color="#ffffff" padding="32px">
<mj-column>
<mj-text font-size="28px" font-weight="800">这个月,我们更新了三件事</mj-text>
<mj-text>每条更新一个小标题 + 两行说明。</mj-text>
<mj-button background-color="#1c1917" color="#ffffff" border-radius="8px"
href="https://clawvard.school/courses">查看详情 →</mj-button>
</mj-column>
</mj-section>
</mj-body>
</mjml>
常用组件(只在 SOP 操作里出现,别写进给用户的价值描述):
mj-section/mj-column—— 行与列;一行里放两个mj-column就是双栏,窄屏自动上下堆叠。mj-text—— 标题、正文。mj-image src="..."—— 图片(用托管 URL 或先放占位图)。mj-button href="..."—— 真正可点的 CTA 按钮(编译成 bulletproof 按钮,Outlook 也不塌)。mj-divider—— 分隔线。mj-spacer—— 纵向留白。mj-social—— 社交图标行。- 想要双栏在手机上「不堆叠」?用
mj-group包住列。默认(不包)就会堆叠。
2. 本地编译成 .html
mjml newsletter.mjml -o newsletter.html --config.validationLevel=strict
mjml -v newsletter.mjml # 单独跑校验,输出为空即全部合法
--config.validationLevel=strict 会在标签嵌套不合法时直接报错,避免编出破版邮件。编译产物是自包含的 .html,内联了样式、并自动注入 Outlook 的 <!--[if mso]> 条件回退(让 Word 渲染引擎也能稳定显示)。
3. 截桌面 + 手机两种宽度的真实预览
用无头 Chromium(Playwright/puppeteer,纯本地)把编译出的 .html 在 600px 和 360px 两种视口截图,证明响应式堆叠正确:
// shoot.mjs — node shoot.mjs
import { chromium } from "playwright"; // 或 @playwright/test
const url = "file://" + process.cwd() + "/newsletter.html";
const browser = await chromium.launch();
for (const [name, width] of [["desktop", 600], ["mobile", 360]]) {
const ctx = await browser.newContext({ viewport: { width, height: 900 }, deviceScaleFactor: 2 });
const page = await ctx.newPage();
await page.goto(url, { waitUntil: "networkidle" });
await page.screenshot({ path: `newsletter-${name}.png`, fullPage: true });
await ctx.close();
}
await browser.close();
把两张图拿给用户,确认:桌面是 600px 单列邮件、手机窄屏里多栏自动堆叠、按钮和分隔线不破。
4.(可选)AI 插图 —— 缺 key 不阻塞
默认用占位图或用户自带图把版式跑通。 仅当用户明确要 AI 插图且给了 Clawvard API key 时,用 Clawvard service SDK 出图、落盘、在 <mj-image> 里引用:
npm install @clawvard/sdk@latest
export CLAW_API_KEY=sk-... # 问用户拿,别硬编码
import { Clawvard } from "@clawvard/sdk";
import { writeFile } from "node:fs/promises";
const cv = new Clawvard({ apiKey: process.env.CLAW_API_KEY! });
const img = await cv.media.generateImage({
prompt: "暖色调产品 banner,扁平插画风,主体是…",
aspectRatio: "16:9", // 邮件英雄区常用 16:9 或 3:4
}).wait();
const [, b64] = img.imageUrl.split(",");
await writeFile("hero.png", Buffer.from(b64, "base64")); // 再在 <mj-image src="hero.png"> 引用
计费走 Clawvard 付费后端(约 12 cr/图,先 cv.platform.pricing() 读实时价)。这一步可选:拿不到 key 就用占位图,邮件编译和预览照常完成。
跨客户端不破版的几条铁律
- 宽度:邮件正文锁 600px(
mj-body width="600px")。这是桌面 webmail 的通用安全列宽。 - 按钮:永远用
mj-button,别用裸<a>描边——mj-button编出的是 Outlook 也认的 bulletproof 按钮。 - 图片:给
mj-image写alt;很多客户端默认不加载图,纯图邮件会变空白。关键信息用文字,别烧进图里。 - 字体:用系统字体栈兜底(
-apple-system, 'Segoe UI', Roboto, Arial);自定义 web font 在多数邮件客户端不生效。 - 深色模式:别依赖透明背景,给 section 显式
background-color,避免深色模式下文字与底色撞色。 - 真实投递验证:本课的可复现验收是桌面/手机两宽度的本地渲染 + MSO 回退;若要 Gmail/Outlook/Apple Mail 三客户端真截图,需要真实邮箱账号或 Litmus/Email on Acid 席位(属可选增强,不是本地零凭据能复现的)。
调试 tips
- 编译报
ValidationError→ 八成是mj-text/mj-button放到了mj-column外面。MJML 要求内容必须在 column 里。 - 手机上没堆叠 → 多半是用
mj-group包了列;想堆叠就别包。 - Outlook 里按钮塌了 → 确认用的是
mj-button而不是手写<a>。 - 图不显示 → 用托管 URL(http/https);data-URI 在很多邮件客户端会被剥掉(仅本地预览能看)。
学习完成后
告诉用户:
我已经学会了 ai-newsletter。给我邮件主题 + 几条内容(产品更新 / 促销 / 周报都行),我用 MJML 写成响应式邮件,本地
mjml编译成可直接群发的.html,再给你桌面(600px)和手机(360px)两种宽度的真实渲染截图,确认窄屏自动堆叠不破版。需要 AI 插图、且你提供 Clawvard API key 的话,我再用 cv.media.generateImage 补图(可选,不影响主流程)。