Pre-Send Email HTML Compatibility Checker
Pricing
from $20.00 / 1,000 email analyzeds
Pre-Send Email HTML Compatibility Checker
Check email HTML against 12 client profiles before you send it. Finds Outlook and Gmail breakages, dead or insecure assets, and Gmail clip-limit risk, with no browser and no render farm.
Pricing
from $20.00 / 1,000 email analyzeds
Rating
0.0
(0)
Developer
kingii98
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
9 days ago
Last modified
Categories
Share
Check email HTML before you send it. The Actor finds design breaks in Outlook and Gmail, and in ten other clients, without a browser and without a render farm. Send it your email HTML. Get a client-by-client score, a list of findings, and a send verdict.
What it does
For each email, the Actor:
- Reads the HTML you supply, either inline or from a public URL.
- Tests the HTML and CSS against a static rule matrix for up to 12 email client profiles (Outlook desktop, Outlook.com, Gmail web/Android/iOS, Apple Mail macOS/iOS, Yahoo, AOL, Samsung Mail, Thunderbird, Orange.fr).
- Sends one bounded HEAD request for each unique image and link that the HTML names, to check that the asset is reachable, served over HTTPS, and not oversize.
- Reports structure flags: missing alt text, a missing preheader, table layout use, media query count, and the Gmail 102 KB clip limit.
- Scores each client from 0 to 100 and gives one verdict:
SEND_OK,SEND_WITH_RISK, orDO_NOT_SEND.
The Actor never renders the email and never opens a browser. It reads the supplied HTML as text and sends network requests only to asset URLs that the HTML itself names.
Input
See .actor/input_schema.json for the full schema. The main fields:
| Field | Type | Default | Purpose |
|---|---|---|---|
emails | array | the example email | Each item needs name and one of html or htmlUrl. Maximum 200 items, 2 MB of HTML each. If you leave this field empty, the Actor checks the example email from the default input. |
clientProfiles | array of string | all 12 profiles | Which client profiles to score. |
checkRemoteAssets | boolean | true | Send HEAD requests to check images and links. |
maxAssetsPerEmail | integer | 60 | Cap on unique assets checked for each email. |
darkModeChecks | boolean | true | Flag emails with no dark mode support signal. |
previousDatasetId | string | — (optional) | Dataset ID from an earlier run. Marks each finding as new or already known. |
Output
One dataset record for each email, plus one run-level summary record first. Each email record holds:
emailName,htmlBytes,checkedAtclientScores: one 0-100 score for each requested client profilefindings: a list of{severity, client, ruleId, cssPropertyOrTag, lineNumber, message, fixSnippet}assetFindings: a list of{url, kind, httpStatus, contentType, bytes, verdict}structureFlags:{missingAltCount, missingPreheader, tableLayoutUsed, mediaQueryCount, totalHtmlBytesOverGmailClipLimit}verdict:SEND_OK,SEND_WITH_RISK, orDO_NOT_SENDerror: set only when the Actor could not read the HTML (for example, a failedhtmlUrlfetch)
The summary record holds verdictCounts for the run and topBlockerRules,
the blocker rules that fired most often across the batch.
Safety bounds
- HTTP(S) only. No browser, no proxy, no third-party paid API.
- Every network target — an
htmlUrlfetch and every asset HEAD request — is checked against a public-address allow list before each request and again on every redirect hop. Localhost, private, link-local, and reserved addresses are rejected. - HTML input is capped at 2 MB for each email, 200 emails for each run.
- Fetches are bounded by timeout, byte size, and redirect count.
- Asset and email checks run under a bounded concurrency limit.
Local development
uv syncuv run pytestuv run ruff check .
Run the Actor locally with the Apify CLI, or directly:
$uv run python -m email_html_compatibility_checker
The default input at .actor/default_input.json
is a small, self-contained fixture: one email with a flexbox button, one
missing alt attribute, no preheader, and two stable public asset URLs (one
reachable, one a deliberate 404) so a first run shows both an OK and a
BROKEN asset finding.