# aggregate ## Purpose Implements `parseDmarcAggregate`, the primary entry point for converting raw DMARC aggregate (RUA) report data into validated, strongly-typed `DmarcAggregateReport` objects. It handles the full pipeline: gzip auto-detection and decompression, XML parsing, snake_case-to-camelCase field mapping, single-vs-multiple element normalisation, and Zod schema validation with structured error reporting. ## Features - Auto-detects gzip input via magic-byte probe — no caller configuration needed for compressed reports - Accepts both raw XML strings and `Uint8Array` binary blobs in a single overload - Full snake_case → camelCase mapping for all RFC 7489 field names - Handles variable-arity elements: ``, ``, `` can be single or multiple - Validates the mapped structure with `DmarcAggregateReportSchema` (Zod) - Emits OTel counter and histogram via `recordParse()` on both success and error paths - Wraps all failures in typed `DmarcError` with stable codes ## Usage: Basic Example ```ts import { parseDmarcAggregate } from "@suaveplan/dmarc/parsers/aggregate"; const report = parseDmarcAggregate(` 1.0 Example Corp dmarc@example.com 12345 16094592001609545600 example.com rr

none

100
192.0.2.15 nonepasspass example.com example.compass example.compass
`); console.log(report.reportMetadata.orgName); // "Example Corp" console.log(report.record[0].row.count); // 5 ``` ## Usage: Advanced Example ```ts import { parseDmarcAggregate } from "@suaveplan/dmarc/parsers/aggregate"; import { DmarcError, DMARC_CODES } from "@suaveplan/dmarc/errors"; import { gzipSync, strToU8 } from "fflate"; // Parse from gzip-compressed bytes const xmlBytes = strToU8(xmlString); const compressed = gzipSync(xmlBytes); const report = parseDmarcAggregate(compressed); // Error discrimination try { parseDmarcAggregate("not xml"); } catch (err) { if (err instanceof DmarcError) { switch (err.code) { case DMARC_CODES.PARSE_ERROR: // XML could not be parsed break; case DMARC_CODES.INVALID_REPORT: // Parsed but failed schema validation break; case DMARC_CODES.UNSUPPORTED_ENCODING: // Gzip decompression failed break; } } } ``` ## API Reference ### `parseDmarcAggregate(input, options?): DmarcAggregateReport` **Parameters:** - `input: string | Uint8Array` — raw XML string or binary data (plain or gzip-compressed) - `options.decompress?: boolean` — force gzip decompression even without magic bytes **Returns:** `DmarcAggregateReport` — fully validated aggregate report **Throws:** - `DmarcError(DMARC.PARSE_ERROR)` — XML parse failure - `DmarcError(DMARC.INVALID_REPORT)` — missing required elements or schema validation failure - `DmarcError(DMARC.UNSUPPORTED_ENCODING)` — gzip decompression failure ### `ParseDmarcAggregateOptions` `{ decompress?: boolean }` ## Implementation Notes The parser uses a two-phase approach: structural mapping first (XML → plain object), validation second (Zod). This separation means that when validation fails the error message includes Zod's structured issue list rather than a raw type error, making debugging significantly easier. The `performance.now()` timing wraps the entire pipeline so OTel histograms reflect the true end-to-end cost including decompression and schema validation.