---
title: "Pre-send QA, MailKaro Docs"
description: "A live audit that lints the design for the mistakes that hurt deliverability and rendering, before it's sent."
---

# Pre-send QA

Deliverability

# Pre-send QA

A live audit that lints the design for the mistakes that hurt deliverability and rendering, before it's sent. The toolbar's **Audit** button carries a **live badge** with the current error/warning count, and opens a **docked, non-blocking panel** you can keep open while you fix issues, each finding jumps straight to the offending block.

ℹ Audit is a paid feature, the button appears only when the plan grants `qa.audit` (part of the Deliverability suite with [Inbox previews](https://mailkaro.com/docs/inbox-previews); see [Plans & entitlements](https://mailkaro.com/docs/plans)).

## What it checks

|Property |Controls |Default |
|`Links` |Empty/placeholder (#, example.com) and unsafe javascript: URLs |error / warning |
|`Alt text` |Images & GIFs missing alt text |warning |
|`Heading order` |A heading that skips a level (h1 straight to h3) |warning |
|`Link text` |Links that say only click here or read more |info |
|`Button label` |A button with no label |warning |
|`Small text` |Text, headings and buttons under 12px |warning |
|`Table header` |A table with the header row turned off |info |
|`Language` |No document language set in Body settings |info |
|`Contrast` |Button text vs background below WCAG 4.5:1 |warning |
|`Subject line` |Missing, or longer than ~70 characters |warning / info |
|`Preheader` |No preheader text set |info |
|`Unsubscribe` |No unsubscribe link / {{unsubscribe_url}} found |warning |
|`Spam words` |Classic spam-filter trigger phrases in subject/content |info |
|`Gmail clipping` |HTML over about 102 KB (Gmail hides the rest), or over 90 KB (close). Linked images do not count. The toolbar shows a Gmail size badge from 90 KB |warning / info |

## Programmatic

The same audit is exported from the renderer, so you can gate your own send flow:

ts qa.ts

```
import { auditDesign } from "email-craft-sdk";

const findings = auditDesign(design);
// [{ id, severity: "error"|"warning"|"info", category, message, blockId?, hint? }]
const blockers = findings.filter((f) => f.severity === "error");
if (blockers.length) throw new Error("Fix QA errors before sending");
```

## Custom validators

Register **your own** rules with `config.qa.validators` (or pass them to `auditDesign(design, { validators })`). They run alongside the built-in checks and their findings merge into the same live panel. A validator that throws is skipped, one bad rule never breaks the audit.

ts customValidators.ts

```
const config = {
 qa: {
 validators: [
 {
 id: "brand", run: (design) => {
 const hasLogo = design.body.rows.some((r) =>
 r.columns.some((c) => c.blocks.some((b) => b.type === "image")));
 return hasLogo ? [] : [{ severity: "error", message: "Add your logo before sending." }];
 }
 }
 ]
 }
};
```

Source: https://docs.mailkaro.com/qa-checks
