# parser _(no submodules)_ ## Purpose Wraps `postal-mime` with a strict input/option boundary, OTel instrumentation, structured error codes, and the `@suaveplan/email-processing/hooks` pipeline. `parseEmail` is the package's primary entry point: it takes a raw RFC 822 message in any of the three supported input shapes (string, `ArrayBuffer`, `Uint8Array`) and returns a fully-parsed `ParsedEmail` whose attachments are real MIME parts (no stubs). ## Features - Three input modes — string, `ArrayBuffer`, `Uint8Array` — covering both browser and Node consumers. - Zod-validated options at the boundary, raising `EMAIL_PROCESSING.INVALID_OPTIONS` with the failing issues on `context` so callers can surface diagnostics. - Distinct error codes for `INVALID_INPUT` (null/undefined/wrong type) and `PARSE_FAILURE` (`postal-mime` threw); `parse.failure_total` is incremented for the latter. - Hook pipeline integration — every parse returns the result of `emailHooks.applyHooksAsync("email:processing", …)`. - `parseEmailAddress` and `decodeEmailWords` re-export the `postal-mime` low-level helpers under the package's typed surface, with the same `INVALID_INPUT` guard. ## Usage: Basic ```ts import { parseEmail } from "@suaveplan/email-processing/parser"; const parsed = await parseEmail(rawMimeString); console.log(parsed.subject, parsed.attachments.length); ``` ## Usage: Advanced ```ts import { parseEmail } from "@suaveplan/email-processing/parser"; import { onEmailProcessing } from "@suaveplan/email-processing/hooks"; const off = onEmailProcessing((data) => ({ ...data, parsed: { ...data.parsed, html: data.parsed.html?.replace(//gi, ""), }, })); try { const parsed = await parseEmail(buffer, { attachmentEncoding: "base64", maxNestingDepth: 64, }); await persist(parsed); } finally { off(); } ``` ## API Reference - `parseEmail(raw, options?)` — async; returns `ParsedEmail`. Throws `EmailProcessingError` with codes `INVALID_INPUT`, `INVALID_OPTIONS`, or `PARSE_FAILURE`. - `parseEmailAddress(addressString)` — sync; returns `EmailAddress[]`. Throws `EmailProcessingError(INVALID_INPUT)` for non-string input. - `decodeEmailWords(text)` — sync; returns decoded RFC 2047 string. Throws `EmailProcessingError(INVALID_INPUT)` for non-string input. ## Implementation Notes `parseEmail` records `email_processing.parse.total` with the attachment count as an attribute so dashboards can surface average attachments-per-message. Parse failures increment a separate `parse.failure_total` counter (no attachment count is recorded because the parser never reached the attachment array). The Zod options schema is `.strict()` so unknown option keys are rejected — this catches typos at the boundary instead of letting them silently no-op.