GitHub - stewartjarod/email-lint: Lint email HTML for client compatibility using caniemail data. CLI + library.

2 min read Original article ↗

Catch email client compatibility issues before your users do. Validates HTML and CSS against caniemail data for 30+ email clients including Gmail, Outlook, Apple Mail, and Yahoo.

$ npx @email-lint/core check welcome.html

welcome.html
  12:5   error    cursor not supported (4/4 variants)  [gmail]
  18:3   warning  background-image not supported (2/6 variants: windows, windows-mail)  [outlook]
  24:10  warning  <picture> not supported (4/4 variants)  [gmail]

✖ 1 error, 2 warnings

Quick start

# Lint an HTML email
npx @email-lint/core check welcome.html

# Lint a React Email component (renders to HTML automatically)
npx @email-lint/core check src/emails/welcome.tsx

# Check only Gmail compatibility
npx @email-lint/core check welcome.html --preset gmail

Install

npm install @email-lint/core

What it does

Raw caniemail data gives you one diagnostic per client variant — 26+ results per issue, no severity levels, no formatting. email-lint makes that data useful:

  • Collapses by family — 4 Gmail variants become one line: (4/4 variants) [gmail]
  • Smart severitycursor is cosmetic (info, not error). Gmail forces target="_blank" on all links — if you already use it, that's info too
  • React Email aware — Suppresses false positives from framework internals (preview blocks, preload images, forced target="_blank")
  • CI-ready — Exit code 1 on errors. GitHub Actions formatter shows inline annotations on PR diffs
  • TSX support — Point it at a .tsx component, it renders and lints in one step

Use with React Email

npm install @email-lint/react-email
import { lintComponent } from '@email-lint/react-email';

const result = await lintComponent(<Welcome name="Jane" />);
// Framework-aware filtering enabled by default

Or use the CLI directly — it auto-detects .tsx files:

email-lint check src/emails/welcome.tsx

Use in CI

# GitHub Actions
- name: Lint emails
  run: npx @email-lint/core check 'src/emails/**/*.html' --format github
# Any CI — exit code 1 on errors
email-lint check src/emails/ --format json

Use in tests

import { expect, test } from 'vitest';
import { lintComponent } from '@email-lint/react-email';
import { Welcome } from './emails/welcome';

test('Welcome email has no compatibility errors', async () => {
  const result = await lintComponent(<Welcome name="Jane" />);
  expect(result.errorCount).toBe(0);
});

test('Welcome email passes Gmail checks', async () => {
  const result = await lintComponent(<Welcome name="Jane" />, { preset: 'gmail' });
  expect(result.success).toBe(true);
});

Packages

Package Description
@email-lint/core Linter engine + CLI npm
@email-lint/react-email React Email integration npm

Contributing

pnpm install
pnpm build
pnpm test

License

MIT