Your email looks perfect in Apple Mail. Gmail strips half the CSS. Outlook renders it in Word.
@emailens/engine analyzes your HTML against 250+ CSS properties across 12 email clients, scores compatibility, and shows you exactly what to fix — before you hit send.
emailens.dev — Try the hosted version. Paste HTML, get a full audit in seconds.
npm install @emailens/engineimport { auditEmail } from "@emailens/engine"; // Flexbox + gap + box-shadow — all Outlook killers
const html = `<html lang="en">
<head><title>Weekly Update</title>
<style>
.card { border-radius: 8px; box-shadow: 0 2px 8px rgba(0,0,0,0.1); }
</style>
</head>
<body>
<div class="card" style="display: flex; gap: 16px;">
<div>Column A</div>
<div>Column B</div>
</div>
</body>
</html>`; const report = auditEmail(html, { framework: "jsx" }); console.log(report.compatibility.scores["outlook-windows"]);
// { score: 30, errors: 3, warnings: 3, info: 1 }
// ↑ Outlook uses Word — flexbox, gap, box-shadow, border-radius all break console.log(report.compatibility.scores["gmail-web"]);
// { score: 75, errors: 0, warnings: 5, info: 0 } console.log(report.spam.score); // 100 (clean)
console.log(report.accessibility.score); // 88
console.log(report.size.clipped); // false (under Gmail's 102KB limit)Score too low? Fix it automatically:
import { generateAiFix, AI_FIX_SYSTEM_PROMPT } from "@emailens/engine"; const { code } = await generateAiFix({ originalHtml: html, warnings: report.compatibility.warnings, scores: report.compatibility.scores, scope: "outlook-windows", format: "jsx", provider: async (prompt) => { // Any LLM — Claude, GPT, etc. const msg = await anthropic.messages.create({ model: "claude-sonnet-4-6", max_tokens: 8192, system: AI_FIX_SYSTEM_PROMPT, messages: [{ role: "user", content: prompt }], }); return msg.content[0].type === "text" ? msg.content[0].text : ""; },
});
// code → JSX with <Table> layout, VML roundrects, inline fallbacks8 analysis engines, one auditEmail() call.
- CSS compatibility — 250+ properties tested across 12 email clients, with fix snippets and AI-powered auto-fix
- Spam scoring — 45+ signals modeled after SpamAssassin, CAN-SPAM, and GDPR
- Accessibility — WCAG contrast ratios, alt text, semantic structure, heading hierarchy
- Link validation — broken hrefs, insecure HTTP,
javascript:protocols, deceptive URLs - Image analysis — missing dimensions, oversized data URIs, tracking pixels, WebP/SVG format
- Inbox preview — subject/preheader truncation per client, Gmail clipping detection
- Domain authentication — SPF, DKIM, DMARC, MX, and BIMI DNS record validation
- Template variables — unresolved merge tags across 6 template systems (Handlebars, ERB, Mailchimp, etc.)
npm install @emailens/engineThree entry points:
| Import | Description |
|---|---|
@emailens/engine |
Core analysis — CSS, spam, a11y, links, images, inbox preview, size, templates, AI fix |
@emailens/engine/compile |
JSX / MJML / Maizzle → HTML compilers |
@emailens/engine/server |
Node-only: DNS deliverability checks, SpamAssassin integration |
- Offline-first — runs entirely locally, no network calls required (except DNS deliverability checks)
- Unified audit — one function call returns CSS compatibility, spam, accessibility, links, images, inbox preview, size, and template checks
- Framework-aware — fix snippets tailored to React Email (JSX), MJML, and Maizzle
- AI-ready — structural issues get LLM-powered auto-fix with any provider (Claude, GPT, etc.)
- Programmable — TypeScript API, not a GUI — integrate into CI, editors, or build pipelines
| @emailens/engine | Litmus | Email on Acid | caniemail.com | |
|---|---|---|---|---|
| Local/offline | Yes | No | No | Data only |
| Programmatic API | Yes | Limited | No | No |
| CSS + Spam + A11y | Yes | Separate tools | Separate tools | CSS only |
| AI auto-fix | Yes | No | No | No |
| Open source | MIT | No | No | Yes (data) |
| Client | ID | Category | Engine | Dark Mode |
|---|---|---|---|---|
| Gmail | gmail-web |
Webmail | Gmail Web | Yes |
| Gmail Android | gmail-android |
Mobile | Gmail Mobile | Yes |
| Gmail iOS | gmail-ios |
Mobile | Gmail Mobile | Yes |
| Outlook 365 | outlook-web |
Webmail | Outlook Web | Yes |
| Outlook Windows | outlook-windows |
Desktop | Microsoft Word | No |
| Apple Mail | apple-mail-macos |
Desktop | WebKit | Yes |
| Apple Mail iOS | apple-mail-ios |
Mobile | WebKit | Yes |
| Yahoo Mail | yahoo-mail |
Webmail | Yahoo | Yes |
| Samsung Mail | samsung-mail |
Mobile | Samsung | Yes |
| Thunderbird | thunderbird |
Desktop | Gecko | No |
| HEY Mail | hey-mail |
Webmail | WebKit | Yes |
| Superhuman | superhuman |
Desktop | Blink | Yes |
Full API reference: docs/API.md
Covers:
auditEmailandcreateSession— core analysis- Standalone analyzers (CSS, spam, links, accessibility, images, inbox preview, size, templates)
- DNS deliverability and SpamAssassin integration
- Client transforms and dark mode simulation
- Compile module (JSX, MJML, Maizzle)
- AI-powered fixes and token estimation
- Performance optimization guide
- Security considerations
- Full TypeScript type definitions
Contributions are welcome! See CONTRIBUTING.md for architecture overview, setup instructions, and PR guidelines.
bun install && bun test # 580 testsCSS support data is auto-synced from caniemail.com. Other data (dark mode behavior, display limits, Superhuman overrides) is manually curated and tracked with verification dates.
bun run sync:caniemail # Refresh CSS support matrix from caniemail.com
bun run check:freshness # Flag stale data sources (exits 1 if any overdue)See CONTRIBUTING.md for full details on data sources and verification procedures.
MIT — Copyright 2025 Emailens