Outbound delivery

Turnkey outbound SMTP composer. Wraps the discovery chain (MX-lookup → MTA-STS-fetch + MX-allowlist match → DANE TLSA query → REQUIRETLS handshake hint) around the existing per-host b.mail.smtpTransport wire-layer, plus deferred-retry scheduling for transient failures and RFC 3464 DSN generation for permanent ones.

Operators no longer have to glue these pieces by hand:

var deliver = b.mail.send.deliver.create({ hostname: "mta1.example.com", policy: { mtaSts: "enforce", dane: "opportunistic" }, dsn: { from: "mailer-daemon@example.com", onPermanentFailure: function (env, hist) { ... } }, resolver: b.network.dns.resolver.create({ ... }), });

var result = await deliver({ from: "ops@example.com", to: ["alice@recipient.com", "bob@other.com"], rfc822: messageBuffer, requireTls: true, }); // → { delivered: [{ recipient, mxHost, tlsProtocol, ... }], // deferred: [{ recipient, reason, retryAfterMs }], // failed: [{ recipient, reason, dsnSent }] }

Composes: - b.network.smtp.policy.mtaSts.fetch + .matchMx → RFC 8461 enforcement - b.network.smtp.policy.dane.tlsa → RFC 7672 TLSA query - b.network.dns.resolver (operator-supplied) → caching + DoH posture - b.mail.smtpTransport → SMTP wire layer - b.mail.requireTls → RFC 8689 REQUIRETLS - b.mailBounce-style RFC 3464 DSN generation → permanent-failure report-mail - b.audit → mail.send.deliver.* events - b.safeAsync.repeating + operator's queue → retry scheduling (deferred deliveries re-enter via the retry.scheduleRetry callback)

The deferred-retry surface is operator-side: this primitive classifies a recipient's outcome as "deferred" and emits a retryAfterMs budget; the operator's queue / scheduler re-invokes deliver for the deferred recipient after that elapses. The primitive does NOT own a background scheduler — that ownership lives with the operator's job-runner so a single deferred-delivery tick can't pin a long-lived process.

b.mail.send.deliver.create(opts) #

stable0.11.24
{
  hostname:   string,                    // required — local hostname for HELO/EHLO + DSN Reporting-MTA
  port:       number,                    // default 25 (IANA SMTP, RFC 5321) — set 587 (RFC 6409 submission) or 465 (RFC 8314 implicit-TLS) for a smarthost relay
  resolver:   object | null,             // optional — b.network.dns.resolver handle; falls back to node:dns when omitted
  policy: {
    mtaSts:   "enforce" | "testing" | "off",  // default "enforce" — RFC 8461 posture
    dane:     "opportunistic" | "enforce" | "off",  // default "opportunistic" — RFC 7672
  },
  retry: {
    maxAttempts:  number,                // default 5
    backoffMs:    Array,         // default [1m, 5m, 15m, 1h, 4h]
  },
  dsn: {
    from:     string,                    // required when dsn.onPermanentFailure is set
    onPermanentFailure: function (envelope, result, dsnMessage) → Promise,
  },
  timeouts: {
    mxLookupMs: number,                  // default 10s
    perHostMs:  number,                  // default 60s
  },
  audit:      boolean,                   // default true
}

Build a turnkey delivery handle. Returns a deliver(envelope) function that takes a single multi-recipient envelope, resolves MX records per recipient domain, applies the operator's configured MTA-STS / DANE policy, attempts delivery via b.mail.smtpTransport, and returns a per-recipient outcome split into delivered / deferred / failed arrays.

Deferred recipients carry retryAfterMs budgets the operator's queue / scheduler honors by re-invoking deliver for that subset after the budget elapses. The primitive does not own a background scheduler — operator job-runner owns the retry lifecycle.

Failed recipients trigger DSN composition: a RFC 3464 multipart/ report message is built per failed recipient and handed to the operator-supplied dsn.onPermanentFailure(envelope, recipientResult, dsnMessage) callback. The callback is responsible for delivering the DSN itself (typically by re-entering the same deliver handle with the original sender as recipient — but operators who want a separate transport for DSNs wire that here).

var deliver = b.mail.send.deliver.create({
  hostname: "mta1.example.com",
  policy:   { mtaSts: "enforce", dane: "opportunistic" },
  dsn:      { from: "mailer-daemon@example.com",
              onPermanentFailure: function (env, res, dsn) {
                return deliver({ from: env.from, to: [env.from], rfc822: Buffer.from(dsn) });
              } },
});
var result = await deliver({
  from:   "ops@example.com",
  to:     ["alice@recipient.com"],
  rfc822: messageBuffer,
});
typeof result.delivered;   // → "object" (array)
typeof result.deferred;    // → "object" (array)
typeof result.failed;      // → "object" (array)

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