Skip to main content
Glama
Valen-Systems-Inc

email-fixture-lab

Official
README.md
# Email Fixture Lab

Inspect an `.eml` file without uploading mail or opening its HTML. A small offline beta for people building email workflows, including Cloudflare Email Workers. Independent software by Valen Systems, not affiliated with Cloudflare.

## Try the ZIP

Install Node.js 22.13+, unzip, and run from the extracted directory:

```sh
node email-fixture-lab.mjs inspect examples/bounce.eml
```

To inspect your own file, run from the directory containing it:

```sh
node /path/to/email-fixture-lab.mjs inspect message.eml
```

The output describes body sizes, known MIME categories, attachments, nested messages and delivery-status fields. Email addresses become `address-1`, `address-2`, etc. Aliases preserve matching addresses within this inspection, including the nested original message; they reset for each file and are not cross-file identities. Exact address case is preserved internally when matching.

Subjects, display names, raw headers, message IDs, filenames, Content-IDs, diagnostic text and bodies are omitted. Unknown MIME types become `other`. Attachment bytes are never written or executed. Receipts contain input and attachment SHA-256 fingerprints, sizes, relationships and reported status codes: these can still be sensitive. Hashing is not encryption or anonymization. Review a receipt before sharing it.

## Local MCP

```json
{
  "mcpServers": {
    "email-fixture-lab": {
      "command": "node",
      "args": ["/path/to/email-fixture-lab.mjs", "mcp", "--root", "/path/to/fixtures"]
    }
  }
}
```

The only tool is `inspect_email_fixture`, with `{ "file": "bounce.eml" }`. Select a relative `.eml` path beneath the startup root. No directory discovery, URL input, network access, credentials, sending, account setup or file writes are exposed. Concurrent inspections return `BUSY` rather than queueing. CLI inspection uses the current directory as its root. Keep the root stable: this is not a sandbox against another local process replacing directories during a read.

## Beta limits

- Input: 1 MiB, regular files only, no symlinks in the selected relative path.
- MIME: 32 levels and 64 KiB aggregate headers per parsed message.
- Embedded `message/rfc822`: four levels below the outer message, 16 messages total.
- Across the inspection: 128 attachments and 256 address occurrences.
- Delivery-status part: at most 16 recipient blocks. Only standard action values and numeric enhanced-status codes are emitted. Duplicate/missing/unrecognized fields become null; `fieldsValid` checks only these extracted fields. `actionStatusConsistent` compares action and status class.

Exceeded limits fail with fixed error codes, without raw input in diagnostics. The parser is tolerant of malformed MIME; a successful inspection is not RFC conformance, a malware verdict, exhaustive MIME-tree validation or a claim that delivery occurred. Internationalized/global DSN extensions and arbitrary nested containers are outside v0.1. A DSN can be forged; this tool reports what a local fixture says. ZIP, PDF and image attachment contents are not recursively inspected. HTML is parsed as data, never rendered.

CLI exits: `0` inspected, `64` input/parse/limit error, `70` unexpected error. No runtime dependency installation is needed for the ZIP. Windows execution has not been tested.

## Source and build

```sh
npm ci --ignore-scripts
npm test
npm run build
```

The build uses the host's `zip`; package tests use `unzip`. Source CLI: `node src/cli.mjs inspect examples/bounce.eml`. Original adapter code is MIT licensed. Bundled dependencies retain their licenses, supplied in `licenses/` and `THIRD_PARTY_NOTICES.md`.

Parser: [PostalMime 3.0.0](https://github.com/postalsys/postal-mime), MIT-0. Its documented MIME/header limits are applied before extracting output. Delivery-status fields follow the core format in [RFC 3464](https://www.rfc-editor.org/rfc/rfc3464). All included messages are synthetic; no private mail code or messages were used.