npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

inbound-email-webhook

v0.1.0

Published

Type-safe parser and HMAC signature verifier for inbound email webhooks. Turn incoming email into typed JSON. Works with InboxBridge today; more providers on the roadmap.

Readme

inbound-email-webhook

Type-safe parsing and HMAC signature verification for inbound email webhooks. Turn incoming email into typed JSON, and verify it actually came from your provider — in a few lines, with zero mail-server infrastructure.

npm install inbound-email-webhook
  • Typed payloads — one canonical InboundEmail type, inferred from a Zod schema so the runtime validator and the static types never drift.
  • Signature verification — constant-time HMAC-SHA256 check, with an optional timestamp freshness window.
  • Framework adapters — drop-in Express middleware and a Web-Fetch helper (Next.js App Router, Remix, Hono, Workers).
  • No dependencies beyond Zod. ESM + CJS. Node ≥ 18.

Quick start

Web Fetch (Next.js App Router, Remix, Hono, Workers)

// app/api/inbound-email/route.ts
import { verifyRequest } from 'inbound-email-webhook/next'

export async function POST(request: Request) {
  const result = await verifyRequest(request, {
    secret: process.env.INBOXBRIDGE_SIGNING_SECRET!,
  })
  if (!result.ok) return result.response // 401 or 400, ready to send

  const email = result.email // fully typed InboundEmail
  console.log(`Email from ${email.from.email}: ${email.subject}`)

  return Response.json({ ok: true })
}

Express

import express from 'express'
import { inboundEmailWebhook, type InboundEmailRequest } from 'inbound-email-webhook/express'

const app = express()

app.post(
  '/webhooks/inbound-email',
  express.raw({ type: 'application/json' }), // raw body is required for HMAC
  inboundEmailWebhook({ secret: process.env.INBOXBRIDGE_SIGNING_SECRET! }),
  (req, res) => {
    const email = (req as InboundEmailRequest).inboundEmail!
    // ... create a ticket, post to Slack, kick off a job
    res.json({ ok: true })
  },
)

Low-level (any runtime)

import { verify, parseInboxBridge } from 'inbound-email-webhook'

// Verify over the EXACT raw body bytes — never a re-serialized object.
const ok = verify({
  rawBody,
  signature: headers['x-inboxbridge-signature'],
  secret: process.env.INBOXBRIDGE_SIGNING_SECRET!,
  // Optional freshness check:
  timestamp: headers['x-inboxbridge-timestamp'],
  toleranceSeconds: 300,
})
if (!ok) throw new Error('Invalid signature')

const email = parseInboxBridge(rawBody) // throws on a malformed payload

The payload

interface InboundEmail {
  id: string
  receivedAt: string // ISO-8601
  from: { email: string; name: string }
  to: { email: string; name: string }[]
  cc: { email: string; name: string }[]
  bcc: { email: string; name: string }[]
  replyTo: string | null
  subject: string
  date: string | null // ISO-8601, from the email's Date header
  textBody: string | null
  htmlBody: string | null
  attachments: {
    name: string
    contentType: string
    contentLength: number
    contentId: string | null
    downloadUrl?: string // present only when the file was stored
  }[]
}

Use parseInboxBridge(input) (throws) or safeParseInboxBridge(input) (returns Zod's { success, data | error }). Both accept a raw JSON string or an already-parsed object.

Signature scheme

The signature is HMAC-SHA256(rawBody, signingSecret), hex-encoded, sent in the X-InboxBridge-Signature header as sha256=<hex>. A X-InboxBridge-Timestamp header (Unix seconds) accompanies each delivery. Verify over the raw request body bytes — re-serializing a parsed object changes key order and whitespace and breaks the HMAC.

The timestamp is not currently bound into the signature, so toleranceSeconds is a freshness check, not a cryptographic replay guarantee.

Providers

This package normalizes inbound email into one canonical shape. Today it ships an adapter for InboxBridge, which gives you an inbound address and delivers parsed, signed JSON to your endpoint.

| Provider | Status | | --- | --- | | InboxBridge | ✅ Supported | | Postmark | 🗺️ Roadmap — PRs welcome | | SendGrid Inbound Parse | 🗺️ Roadmap | | Mailgun Routes | 🗺️ Roadmap | | Amazon SES / SNS | 🗺️ Roadmap |

Adapters are just a payload normalizer + a signature verifier. Contributions that add a provider you can test end-to-end are very welcome.

License

MIT · maintained by InboxBridge