Mail Server Method Registry

Shared per-method dispatch registry for the IMAP / JMAP / ManageSieve listener factories. Replaces the hand-rolled switch (verb) dispatchers with a single primitive that:

- runs the protocol-specific guard chain BEFORE the handler lookup (so operator-supplied overrides cannot bypass b.guardImapCommand / b.guardJmap / b.guardManagesieveCommand), - enforces per-handler resource budgets (maxHandlerBytes, maxHandlerMs) — refused at registration time if not supplied, - emits a mail.serverRegistry.method_dispatch audit event with handler-source (builtin | operator-override), - rejects registrations of method names outside the per-protocol IANA / RFC catalogue (unless allowExperimental: true, which itself audits).

Operators wanting to override IMAP FETCH, JMAP Email/query, ManageSieve PUTSCRIPT, etc. supply opts.overrides: { "FETCH": { fn, maxHandlerBytes, maxHandlerMs } } to the listener factory and the registry routes dispatch through the override without touching wire-protocol state, audit lifecycle, or the guard substrate.

Per-handler resource budgets are required (no auto-defaults) per the framework's security-defaults-on rule: an operator-supplied FETCH override that omits a budget could regress CVE-2024-34055 (Cyrus authenticated OOM via unbounded allocation); the stricter-mode contract forces the operator to acknowledge the resource ceiling explicitly.

b.mail.serverRegistry.create(opts) #

stable0.10.11
{
  protocol:        "imap" | "jmap" | "managesieve",
  defaults:        { [name]: { fn, maxHandlerBytes, maxHandlerMs } },
  overrides:       { [name]: { fn, maxHandlerBytes, maxHandlerMs } },
  notFoundHandler: function (name, ctx),  // optional; returns the protocol's "not configured" reply
}

Build a per-method dispatch registry for one of the mail-server listeners. Returns { register, unregister, dispatch, list, has, source, MailServerRegistryError }.

var reg = b.mail.serverRegistry.create({
  protocol: "imap",
  defaults: { CAPABILITY: { fn: _capabilityHandler,
                            maxHandlerBytes: 8 * 1024,
                            maxHandlerMs:    5 * 1000 } },
  overrides: opts.overrides || {},
});
await reg.dispatch("CAPABILITY", state, socket, parsed);

Last updated 2026-08-08T16:39:49.652Z by seeder.