Install
$ agentstack add skill-emailboutique-digital-inc-email-html-qa-skill-email-html-qa-skill ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
Email HTML QA
A repeatable, opinionated review pass for HTML email, built from real production experience. Email is not the web: table-based layout, inconsistent CSS support, and every client renders differently — so QA is about robust and graceful, never pixel-perfect.
How to run it
- If you have the HTML file, run the linter first — a cheap mechanical pre-check:
python scripts/lint_email_html.py path/to/email.html It flags size/clipping, missing alt, missing charset/lang, whether dark mode is targeted (the color-scheme opt-in), transparent logos/icons that may vanish on a dark background, layout tables without role="presentation", empty/# links, unlinked images (Gmail-lightbox / lost CTA), missing auto-link suppression (blue-link risk), missing preheader, and missing compliance elements. Fix the boring stuff before spending human attention on craft.
- For a sent message, run the header check — on the raw
.emlas received:
python scripts/lint_email_headers.py path/to/message.eml It reports the SPF/DKIM/DMARC results the receiver recorded, checks List-Unsubscribe + RFC 8058 one-click, and takes a best-effort guess at the sending ESP. Run it on a message as received — the pre-send HTML has no auth headers yet. It reports the recorded results; it does not fix deliverability.
- Then work the checklist below, section by section.
- Report findings by severity, most-severe first — each with *what's wrong,
where, which client(s) it affects, and the suggested fix.* Diagnose first; do not modify the code unless explicitly asked.
The core principle — verify mechanics, not sufficiency
Where a requirement varies by country, industry, jurisdiction, or ESP — compliance wording, the accessibility standard, tracking conventions, the must-support client list — this QA does not rule on legal or regulatory sufficiency. It confirms that whatever was specified for this project is present and functional. Capture the project-specific requirements once, up front; keep the QA pass generic.
Severity scale
- Critical — breaks for a large share of recipients or destroys the message
(invisible text in dark mode, Gmail clipping, broken primary CTA).
- High — clearly wrong in a common client (Outlook-Mac regression, logo
invisible on dark, contrast failure).
- Medium — noticeable but limited.
- Low — polish.
The checklist
1. Dark mode — the highest-risk area
- First, confirm whether dark mode is targeted at all. Look for both opt-in
metas in `: and `. If they're present, the email declares dark-mode support — verify it renders as intended. If they're absent, dark mode is not being targeted and clients will auto-handle it (often force-inverting) — flag it and decide with the project spec whether that's acceptable.
- Test forced dark mode explicitly — especially Gmail, plus Outlook-for-Mac
and iOS. Behaviour varies by client and can't always be targeted.
- Confirm the logo stays visible on dark (a dark header + light logo is the
safest default).
- Watch transparent logos and social icons. Dark artwork on a transparent PNG
can sink into a dark-mode background and disappear. Fix it with a background "chip" (a padded light/brand-colour box), a dark-mode image swap, or a light logo on a deliberately dark header. The linter flags at-risk logo/icon images (transparent, icon-sized, no background behind them), but only a dark-mode proof confirms it — a flagged asset usually means going back to design for a variant.
- Check coloured buttons — confirm button copy doesn't vanish. Never assume a
blend-mode trick works on a light/coloured fill; judge each button by its own fill + text combination.
- Confirm no colour's contrast fails against its dark-mode-inverted background.
- Distinguish fixed-dark elements (already dark; must render identically —
gradient-as-solid + blend-mode wrap) from adaptive elements (light by default; deliberately invert via a dark-mode class). Never mix their techniques.
- Use the companion per-send test grid: [
references/dark-mode-qa-matrix.md](references/dark-mode-qa-matrix.md)
— surfaces × clients, with the known high-risk cells to check first.
2. Client rendering
- Outlook (Windows) — spacing, no-
max-widthelements, background-image gaps. - Outlook for Mac — MSO-conditional regressions; test separately from Windows.
- Gmail — `` stripping, coloured buttons, clipping (~102 KB).
- Apple Mail / iOS — best support; still confirm the dark-mode behaviour you rely on.
- Render-proof across the client matrix (e.g. Email on Acid / Litmus) and save proofs.
3. Responsive / mobile
- Columns stack/flex correctly; no horizontal scroll; adequate tap targets.
- Don't depend unnecessarily on media queries some clients strip.
4. Code quality & size
- Lean code; keep well under the ~102 KB Gmail clip threshold.
- Minimal table nesting; no stray markup; no reflexive Outlook ghost tables.
- No inline styles carried in from pasted copy overriding the template.
- Declare ``; confirm curly quotes, dashes, accents and
emoji render (no mojibake) after copy moves design → code → ESP.
5. Accessibility
- Live text, not text baked into images.
- Alt text is intentional, not just present. Meaningful images get a real,
descriptive alt; purely decorative images get an empty alt="" (and aria-hidden="true" where needed) so a screen reader skips them cleanly. The failure case is a decorative image with no alt attribute at all — some screen readers then read out the filename. Decide per image: describe it, or silence it.
- Contrast passes in light and dark mode.
- Logical heading hierarchy.
- Semantic mechanics: layout tables carry
role="presentation"; a document
lang is set; decorative/spacer cells and images are hidden from assistive tech (aria-hidden / empty alt=""); source order gives a sensible linear reading order when columns stack.
- Verify against the project-specified accessibility standard — this confirms
the build honours what was agreed; it does not certify legal conformance.
6. Typography
- Correct fonts render (and the fallback stack is sane where webfonts fail);
verify in the ESP — fonts/spacing can be lost design → code → ESP.
- Type scale and spacing match the style guide.
7. Images
- Correct export sizes, 2× for retina, lean file sizes.
- All images have alt text; reserve images for hero/lifestyle/product — no
image-only emails.
- Link your images — especially large ones. The eye reaches an image before
the copy, so an image is effectively a CTA: a hero/product image usually deserves the primary link. A large unlinked image is also a rendering risk — Gmail wraps unlinked images above a certain (undocumented) size in its own lightbox pop-up and opens them on tap instead of following your CTA. Wrapping the image in a real `` both captures the click and prevents the lightbox. Safe rule: link it. (Legitimate exceptions — logos, spacers, tiny icons — can stay unlinked.)
8. Links, CTAs & tracking
- Every link resolves and points where intended; primary CTA works and is visible
in dark mode.
- Confirm tracking/UTM parameters where the project uses them (convention is
project-specific).
9. Preheader & hidden content
- Preheader text is set, sensible, and not duplicating the subject; hidden/spacer
content doesn't leak into the visible body or dark mode.
10. Personalization & ESP
- Test personalization with missing fields — fallbacks are ESP-DB-dependent
and break silently. Confirm the fallback chain renders gracefully.
- Confirm the build matches the target ESP's real constraints.
11. Compliance elements — present & functional
Verify mechanics, not legal sufficiency (see the core principle). What each element must contain — which laws, which address, which language — is the sender's/their counsel's decision and varies by country and industry.
- Unsubscribe link present and resolves (not a placeholder/
#). - A sender-identity / physical-address block present where required.
- The
list-unsubscribeheader set where the ESP supports it. - Any other specified compliance element (consent language, preference centre)
present and linking correctly.
- Flag anything missing versus what was specified — don't assess statutory sufficiency.
12. Auto-linking & blue links (phone, date, address)
Some clients auto-detect phone numbers, dates, and physical addresses and wrap them in their own blue links — which can recolour text, change the font, and break the layout (common in footers). Confirm auto-linking is suppressed and these elements render as intended. Keep the three overrides separate — Gmail strips chained attribute selectors:
- Apple Mail / iOS — override
a[x-apple-data-detectors](color/
text-decoration / font-* all inherit !important). Optionally add ``.
- Gmail —
u + #body a { … inherit !important }, withid="body"on ``. - Samsung Mail —
#MessageViewBody a { … inherit !important }. - Then look at the rendered footer in each client — suppression CSS is easy to
add and easy to get stripped, so verify, don't assume.
13. Authentication & headers — from a received .eml
Runs on a message as received, not the pre-send HTML — the authentication results are stamped by the receiving server. Read and report; never advise or fix. Use scripts/lint_email_headers.py (get the raw .eml via Gmail's Show original → Download, Apple Mail's Raw Source, or Outlook's View source).
Authentication-Results— report the receiver's recorded SPF / DKIM / DMARC
results and key fields (DKIM header.i/selector, SPF mailfrom domain, DMARC policy p=/sp=/dis= and header.from). Use the topmost header (the one your receiver added); downstream ones can be forged. pass → PASS, fail → FAIL, anything else (softfail/none/neutral) → WARN.
List-Unsubscribepresent, andList-Unsubscribe-Post: List-Unsubscribe=One-Click
present (RFC 8058 — Gmail/Yahoo bulk-sender one-click).
- Best-effort ESP identification from telltale headers / bounce-domain / DKIM
selector — reported as context, never as a verdict. This surfaces what the mailbox provider already determined; the fixes (record configuration, warming, spam scoring) belong to the ESP or a deliverability specialist.
Out of scope — by design
Knowing where the expertise ends is part of doing this well. This QA does not cover:
- Deliverability advice or fixes — configuring SPF/DKIM/DMARC records, IP/domain
warming, spam scoring, inbox placement. (We read and report the auth results a receiver recorded; we don't diagnose or fix them — that's the ESP / deliverability provider.)
- ESP campaign configuration & sending — audience, segmentation, send time,
A/B, automation logic.
- Legal/regulatory certification — this confirms specified elements are
present and functional; it does not certify conformance.
If a build touches one of these, note it and route it to the right owner.
Reporting protocol
Report by severity, most-severe first, each with what's wrong, where, which client(s) it affects, and the suggested fix. Diagnose first; fix only on request.
Maintained by EmailBoutique Digital Inc. · MIT-licensed · rendering/dark-mode engines change over time — treat client-specific behaviour as time-sensitive and re-verify.
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: EmailBoutique-Digital-Inc
- Source: EmailBoutique-Digital-Inc/email-html-qa-skill
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.