{"id":51707169,"url":"https://github.com/emailens/engine","last_synced_at":"2026-08-04T23:00:27.694Z","repository":{"id":340620431,"uuid":"1165769256","full_name":"emailens/engine","owner":"emailens","description":"Email compatibility engine - analyze HTML against 250+ CSS rules across 15 clients, score compatibility, detect spam, check accessibility, simulate dark mode.","archived":false,"fork":false,"pushed_at":"2026-05-08T22:03:45.000Z","size":481,"stargazers_count":6,"open_issues_count":0,"forks_count":1,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-08T22:21:03.950Z","etag":null,"topics":["accessibility","compatibility","css","css-compatibility","dark-mode","email","email-client","email-testing","gmail","html-email","mjml","outlook","react-email","spam-check","spam-detection"],"latest_commit_sha":null,"homepage":"https://emailens.dev","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/emailens.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-02-24T14:24:38.000Z","updated_at":"2026-05-08T22:03:19.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/emailens/engine","commit_stats":null,"previous_names":["emailens/engine"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/emailens/engine","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/emailens%2Fengine","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/emailens%2Fengine/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/emailens%2Fengine/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/emailens%2Fengine/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/emailens","download_url":"https://codeload.github.com/emailens/engine/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/emailens%2Fengine/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":36291062,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-07-20T02:08:10.276Z","status":"online","status_checked_at":"2026-08-04T02:00:06.901Z","response_time":57,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["accessibility","compatibility","css","css-compatibility","dark-mode","email","email-client","email-testing","gmail","html-email","mjml","outlook","react-email","spam-check","spam-detection"],"created_at":"2026-07-16T17:00:29.849Z","updated_at":"2026-08-04T23:00:27.682Z","avatar_url":"https://github.com/emailens.png","language":"TypeScript","funding_links":[],"categories":["Code"],"sub_categories":["Other"],"readme":"\u003cdiv align=\"center\"\u003e\n\n\u003cpicture\u003e\n  \u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"./docs/wordmark-dark.svg\"\u003e\n  \u003cimg src=\"./docs/wordmark-light.svg\" alt=\"emailens / engine\" width=\"515\"\u003e\n\u003c/picture\u003e\n\n**The rendering linter for email**\n\n[![npm](https://img.shields.io/npm/v/@emailens/engine)](https://www.npmjs.com/package/@emailens/engine)\n[![license](https://img.shields.io/npm/l/@emailens/engine)](./LICENSE)\n[![tests](https://img.shields.io/badge/tests-719%20passing-brightgreen)]()\n[![node](https://img.shields.io/node/v/@emailens/engine)](https://nodejs.org/)\n[![MCP](https://img.shields.io/badge/MCP-Server-blue)](https://github.com/emailens/mcp)\n[![GitHub stars](https://img.shields.io/github/stars/emailens/engine?style=flat)](https://github.com/emailens/engine/stargazers)\n\n[Quick Start](#quick-start) · [What It Catches](#what-it-catches) · [Why Emailens](#why-emailens) · [Supported Clients](#supported-email-clients) · [API Docs](./docs/API.md) · [The State of Email CSS](https://emailens.dev/email-css/report)\n\n\u003c/div\u003e\n\n**Your email looks perfect in Apple Mail. Gmail strips half the CSS. Outlook renders it in Word.**\n\n`@emailens/engine` analyzes your HTML against 250+ CSS properties across 21 email clients, scores compatibility, and shows you exactly what to fix — before you hit send.\n\nOur data says you need this: across the 255 CSS and HTML features we track, **only 6 are fully supported in every major email client**. See [The State of Email CSS](https://emailens.dev/email-css/report).\n\n![emailens lint output showing errors and warnings across email clients](./docs/lint-demo.png)\n\n\u003e **[emailens.dev](https://emailens.dev)** — Try the hosted version. Paste HTML, get a full audit in seconds.\n\n## Quick Start\n\nNo install, no project setup, lint any email right now:\n\n```bash\nnpx @emailens/cli lint email.html\n```\n\nOr use the engine as a library:\n\n```bash\nnpm install @emailens/engine\n```\n\n```typescript\nimport { auditEmail } from \"@emailens/engine\";\n\n// Flexbox + gap + box-shadow — all Outlook killers\nconst html = `\u003chtml lang=\"en\"\u003e\n\u003chead\u003e\u003ctitle\u003eWeekly Update\u003c/title\u003e\n  \u003cstyle\u003e\n    .card { border-radius: 8px; box-shadow: 0 2px 8px rgba(0,0,0,0.1); }\n  \u003c/style\u003e\n\u003c/head\u003e\n\u003cbody\u003e\n  \u003cdiv class=\"card\" style=\"display: flex; gap: 16px;\"\u003e\n    \u003cdiv\u003eColumn A\u003c/div\u003e\n    \u003cdiv\u003eColumn B\u003c/div\u003e\n  \u003c/div\u003e\n\u003c/body\u003e\n\u003c/html\u003e`;\n\nconst report = auditEmail(html, { framework: \"jsx\" });\n\nconsole.log(report.compatibility.scores[\"outlook-windows\"]);\n// { score: 30, errors: 3, warnings: 3, info: 1 }\n//  ↑ Outlook uses Word — flexbox, gap, box-shadow, border-radius all break\n\nconsole.log(report.compatibility.scores[\"gmail-web\"]);\n// { score: 75, errors: 0, warnings: 5, info: 0 }\n\nconsole.log(report.spam.score);        // 100 (clean)\nconsole.log(report.accessibility.score); // 88\nconsole.log(report.size.clipped);       // false (under Gmail's 102KB limit)\n```\n\n## Score too low? Fix it\n\nScore too low? Fix it automatically:\n\n```typescript\nimport { generateAiFix, AI_FIX_SYSTEM_PROMPT } from \"@emailens/engine\";\n\nconst { code } = await generateAiFix({\n  originalHtml: html,\n  warnings: report.compatibility.warnings,\n  scores: report.compatibility.scores,\n  scope: \"outlook-windows\",\n  format: \"jsx\",\n  provider: async (prompt) =\u003e {\n    // Any LLM — Claude, GPT, etc.\n    const msg = await anthropic.messages.create({\n      model: \"claude-sonnet-4-6\",\n      max_tokens: 8192,\n      system: AI_FIX_SYSTEM_PROMPT,\n      messages: [{ role: \"user\", content: prompt }],\n    });\n    return msg.content[0].type === \"text\" ? msg.content[0].text : \"\";\n  },\n});\n// code → JSX with \u003cTable\u003e layout, VML roundrects, inline fallbacks\n```\n\n## What It Catches\n\n10 analysis engines, one `auditEmail()` call.\n\n- **CSS compatibility** — 250+ properties tested across 21 email clients, with fix snippets and AI-powered auto-fix\n- **Content overflow** — fixed widths wider than the email frame and unbreakable strings that force horizontal scrolling\n- **Visual bugs** — gradients/background images with no color fallback (invisible content in Outlook) and fonts with no web-safe fallback, each with a concrete fix\n- **Spam scoring** — 45+ signals modeled after SpamAssassin, CAN-SPAM, and GDPR\n- **Accessibility** — WCAG contrast ratios, alt text, semantic structure, heading hierarchy\n- **Link validation** — broken hrefs, insecure HTTP, `javascript:` protocols, deceptive URLs\n- **Image analysis** — missing dimensions, oversized data URIs, tracking pixels, WebP/SVG format\n- **Inbox preview** — subject/preheader truncation per client, Gmail clipping detection\n- **Domain authentication** — SPF, DKIM, DMARC, MX, and BIMI DNS record validation\n- **Template variables** — unresolved merge tags across 6 template systems (Handlebars, ERB, Mailchimp, etc.)\n\n## Installation\n\n```bash\nnpm install @emailens/engine\n```\n\nThree entry points:\n\n| Import | Description |\n|---|---|\n| `@emailens/engine` | Core analysis — CSS, spam, a11y, links, images, inbox preview, size, templates, AI fix |\n| `@emailens/engine/compile` | JSX / MJML / Maizzle → HTML compilers |\n| `@emailens/engine/server` | Node-only: DNS deliverability checks, SpamAssassin integration |\n\n## Why Emailens?\n\n- **Offline-first** — runs entirely locally, no network calls required (except DNS deliverability checks)\n- **Unified audit** — one function call returns CSS compatibility, spam, accessibility, links, images, inbox preview, size, and template checks\n- **Framework-aware** — fix snippets tailored to React Email (JSX), MJML, and Maizzle\n- **AI-ready** — structural issues get LLM-powered auto-fix with any provider (Claude, GPT, etc.)\n- **Programmable** — TypeScript API, not a GUI — integrate into CI, editors, or build pipelines\n\n| | @emailens/engine | Litmus | Email on Acid | caniemail.com |\n|---|---|---|---|---|\n| Local/offline | Yes | No | No | Data only |\n| Programmatic API | Yes | Limited | No | No |\n| CSS + Spam + A11y | Yes | Separate tools | Separate tools | CSS only |\n| AI auto-fix | Yes | No | No | No |\n| Open source | MIT | No | No | Yes (data) |\n\n### vs other email libraries\n\n`@emailens/engine` sits in the **QA / lint / scoring** slot — it analyzes finished HTML. It's complementary to (not a replacement for) composition and inlining libraries.\n\n| | @emailens/engine | [juice](https://github.com/automattic/juice) | [email-comb](https://github.com/codsen/email-comb) | [mjml](https://mjml.io/) | [maizzle](https://maizzle.com/) |\n|---|---|---|---|---|---|\n| Purpose | QA / lint / score | CSS inliner | Unused CSS pruner | MJML → HTML | Tailwind → HTML |\n| Per-client compatibility scoring | Yes | No | No | No | No |\n| Spam / a11y / link / image analysis | Yes | No | No | No | No |\n| AI-powered fix generation | Yes | No | No | No | No |\n| Compose emails | Reads only | Reads only | Reads only | Yes | Yes |\n| CSS inlining | No (pair with juice) | Yes | No | Yes (built-in) | Yes (built-in) |\n\nA typical pipeline: write in **mjml** or **maizzle** → inline with **juice** → audit with **@emailens/engine** → ship.\n\n## Supported Email Clients\n\n| Client | ID | Category | Engine | Dark Mode |\n|---|---|---|---|---|\n| Gmail | `gmail-web` | Webmail | Gmail Web | Yes |\n| Gmail Android | `gmail-android` | Mobile | Gmail Mobile | Yes |\n| Gmail iOS | `gmail-ios` | Mobile | Gmail Mobile | Yes |\n| Outlook 365 | `outlook-web` | Webmail | Outlook Web | Yes |\n| Outlook (New) | `outlook-windows` | Desktop | Outlook Web | Yes |\n| Outlook Classic | `outlook-windows-legacy` | Desktop | Microsoft Word | Yes |\n| Outlook iOS | `outlook-ios` | Mobile | Outlook Mobile | Yes |\n| Outlook Android | `outlook-android` | Mobile | Outlook Mobile | Yes |\n| Outlook for Mac | `outlook-macos` | Desktop | WebKit | Yes |\n| Apple Mail | `apple-mail-macos` | Desktop | WebKit | Yes |\n| Apple Mail iOS | `apple-mail-ios` | Mobile | WebKit | Yes |\n| Yahoo Mail | `yahoo-mail` | Webmail | Yahoo | Yes |\n| Yahoo Mail Android | `yahoo-mail-android` | Mobile | Yahoo | Yes |\n| Yahoo Mail iOS | `yahoo-mail-ios` | Mobile | Yahoo | Yes |\n| Samsung Mail | `samsung-mail` | Mobile | Samsung | Yes |\n| Thunderbird | `thunderbird` | Desktop | Gecko | No |\n| HEY Mail | `hey-mail` | Webmail | WebKit | Yes |\n| Proton Mail | `protonmail` | Webmail | Proton | Yes |\n| AOL Mail | `aol` | Webmail | AOL | Yes |\n| Fastmail | `fastmail` | Webmail | Fastmail | Yes |\n| Superhuman | `superhuman` | Desktop | Blink | Yes |\n\n## API Documentation\n\nFull API reference: **[docs/API.md](./docs/API.md)**\n\nCovers:\n- `auditEmail` and `createSession` — core analysis\n- Standalone analyzers (CSS, spam, links, accessibility, images, inbox preview, size, templates)\n- DNS deliverability and SpamAssassin integration\n- Client transforms and dark mode simulation\n- Compile module (JSX, MJML, Maizzle)\n- AI-powered fixes and token estimation\n- Performance optimization guide\n- Security considerations\n- Full TypeScript type definitions\n\n## Roadmap\n\nSee [ROADMAP.md](./ROADMAP.md) for the full picture (shipped items + items under consideration with rationale).\n\n**Shipped:** automated caniemail.com data sync · GitHub Actions integration via `@emailens/cli` and the [Marketplace Action](https://github.com/marketplace/actions/emailens-email-preview-check) · AI-powered fix generation · compile module for JSX/MJML/Maizzle.\n\n**Considering:** Outlook VML auto-generation · plugin system for custom analyzers · MJML/Maizzle source-level linting · ESLint plugin · spam corpus tuning · dark-mode accuracy tests.\n\nConcrete bugs go in [Issues](https://github.com/emailens/engine/issues). Open-ended ideas live in the roadmap.\n\n## Contributing\n\nContributions are welcome! See **[CONTRIBUTING.md](./CONTRIBUTING.md)** for architecture overview, setup instructions, and PR guidelines.\n\n```bash\nbun install \u0026\u0026 bun test   # 719 tests\n```\n\nOptional real-render validation — renders engine output in a real browser engine (free, no Litmus/Email on Acid needed). Off by default; needs a browser-capable machine:\n\n```bash\nbunx playwright install chromium\nbun run test:render\n```\n\n### Data Maintenance\n\nCSS support data is auto-synced from [caniemail.com](https://www.caniemail.com/). Other data (dark mode behavior, display limits, Superhuman overrides) is manually curated and tracked with verification dates.\n\n```bash\nbun run sync:caniemail    # Refresh CSS support matrix from caniemail.com\nbun run check:freshness   # Flag stale data sources (exits 1 if any overdue)\n```\n\nSee [CONTRIBUTING.md](./CONTRIBUTING.md#data-sources-and-freshness) for full details on data sources and verification procedures.\n\n## License\n\nMIT — Copyright 2025 [Emailens](https://emailens.dev)\n\n---\n\nIf this saved you from an Outlook surprise, [a star](https://github.com/emailens/engine) helps other email developers find it.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Femailens%2Fengine","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Femailens%2Fengine","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Femailens%2Fengine/lists"}