Agent skill

Mailparser Webhooks Skill

Receive and authenticate Mailparser webhooks (Advanced Webhooks that send parsed email data). Use when setting up a Mailparser webhook handler, securing it with the Additional Headers Mailparser lets you attach (e.g. X-Webhook-Secret or Authorization: Basic ...), debugging why the header check fails, or handling parsed email data and per-row table requests. Mailparser does not sign webhooks: there is no signature header or HMAC.

Install this skill

npx skills add hookdeck/webhook-skills --skill mailparser-webhooks


Mailparser extracts structured data from emails and attachments. An Advanced Webhook sends the parsed data to a URL you choose as soon as an email has been parsed. You control the HTTP verb, content type, body template and extra headers.

When to Use This Skill

  • How do I receive Mailparser webhooks?
  • How do I authenticate / verify a Mailparser webhook?
  • Why is my Mailparser webhook header check failing?
  • How do I handle parsed email data from Mailparser?
  • How do I handle "one request per row" table webhooks?
  • Does Mailparser sign webhooks with an HMAC?

No Signature: Additional Headers Only

Mailparser's documentation describes no signature, HMAC or timestamp header (ignore third-party claims of one). Instead, an Advanced Webhook has an Additional Headers field: one Name: value header per line, sent unchanged on every request. The docs' example is an Authorization: Basic ... header.

X-Webhook-Secret: 3f9c1e...a random value from `openssl rand -hex 32`

Pick one header (a secret header such as X-Webhook-Secret, or Authorization: Basic ...), and compare the whole value in constant time on every request. Without it, anyone who knows the URL can post fake data.

Verification (core)

const crypto = require('crypto');

const HEADER = (process.env.MAILPARSER_WEBHOOK_HEADER || 'x-webhook-secret').toLowerCase();
const EXPECTED = process.env.MAILPARSER_WEBHOOK_SECRET; // exact value set in Mailparser

function verifyMailparserHeader(received, expected) {
  if (!received || !expected) return false;                // fail closed
  const a = Buffer.from(String(received), 'utf8');         // the WHOLE header value
  const b = Buffer.from(String(expected), 'utf8');
  return a.length === b.length && crypto.timingSafeEqual(a, b); // length guard first
}

// In the handler: verifyMailparserHeader(req.headers[HEADER], EXPECTED)

For complete handlers with tests, see examples/express/, examples/nextjs/, examples/fastapi/.

Mailparser has no SDK, so every example compares directly (crypto.timingSafeEqual in Node, hmac.compare_digest in Python). Authenticate before you parse the body.

Payload and Events

Mailparser has no event types: an Advanced Webhook fires when an email has been parsed. The body is whatever you put in the HTTP Body Payload Template (Handlebars, e.g. {"invoice_no": "{{InvoiceNumber}}"}), sent as JSON or form data depending on the Content-Type you choose. So the field names are your own parsing-rule names, not a fixed schema.

SettingEffect
What data to send: defaultOne request per email, with all parsed data
What data to send: "One request per row"One request per parsed table row
HTTP VerbPOST by default; GET, PUT, DELETE also available (use POST)
Webhook DelayOptional delay between calls

There is no event ID, so add a unique field to your template (such as a document or message identifier you parse) or hash the raw body for idempotency. See references/overview.md.

Environment Variables

# Header name you added under Additional Headers (case-insensitive). Default: X-Webhook-Secret
MAILPARSER_WEBHOOK_HEADER=X-Webhook-Secret
# The exact header value you added in Mailparser
MAILPARSER_WEBHOOK_SECRET=your_random_secret

With no MAILPARSER_WEBHOOK_SECRET, the examples reject every request with a 500 rather than accept unauthenticated webhooks.

Local Development

npx hookdeck-cli listen 3000 mailparser --path /webhooks/mailparser

No account required — the CLI creates a guest account on first run and gives you a public HTTPS URL plus a web UI for inspecting requests (including your custom header). Use port 8000 for the FastAPI example.

Reference Materials


Repository

hookdeck/webhook-skills

v0.1.0 · MIT · Updated Nov 2, 2026

View on GitHub →