REQUIRETLS — RFC 8689

RFC 8689 SMTP REQUIRETLS — per-message TLS-requirement signaling between sender and receiver MTAs. The sender advertises that the message MUST NOT be relayed over a cleartext (non-TLS) hop; if no downstream MTA can deliver under TLS, the message bounces instead of falling back to cleartext. Complements MTA-STS / DANE (which are policy-side, domain-scoped) with a per-message knob that overrides the policy when the operator wants stricter-than-policy delivery.

Wire surface (RFC 8689 §3):

EHLO peer advertises: 250 REQUIRETLS Client sends: MAIL FROM: REQUIRETLS Server replies: 250 OK (or 550 if it can't honor)

Header surface (RFC 8689 §5):

TLS-Required: No Explicit operator override; sender requests REQUIRETLS-style behavior be DISABLED for this message even if the policy infrastructure (MTA-STS / DANE) says otherwise. Use sparingly — primary use case is delivery to legacy peers during a controlled migration.

This module ships:

b.mail.requireTls.peerSupports(ehloLines) → boolean Walks EHLO response lines and returns true when the peer advertised the REQUIRETLS keyword.

b.mail.requireTls.mailFromExtension({ requireTls }) → string Returns the trailing " REQUIRETLS" token (or empty string) to append to a MAIL FROM line.

b.mail.requireTls.parseTlsRequiredHeader(headerValue) → "yes" | "no" | null Parses the TLS-Required header field per §5. Returns "no" only when the value is the literal token "no" (case- insensitive); any other value returns "yes" (the conservative default — operators must opt OUT explicitly, never default to fall-back-to-cleartext). null when the header is absent.

b.mail.requireTls.peerSupports(ehloLines) #

stable0.8.90

Walk a parsed EHLO response and return true when the peer advertised the REQUIRETLS keyword. ehloLines is the array of post-greeting capability lines returned by the SMTP transport (each entry is the capability token, e.g. "SIZE 10485760", "PIPELINING", "REQUIRETLS"). Case-insensitive match per RFC 5321 §2.4 (EHLO keywords are uppercase by convention but comparison is case-insensitive).

Returns false for empty / non-array input — operators who can't parse the EHLO get a definitive "not supported" verdict rather than a throw, matching the "defensive request-shape reader" convention used elsewhere.

var ehlo = ["mail.example.com", "PIPELINING", "SIZE 10485760", "REQUIRETLS", "STARTTLS"];
b.mail.requireTls.peerSupports(ehlo);  // → true

b.mail.requireTls.peerSupports(["PIPELINING", "SIZE 10485760"]);  // → false

b.mail.requireTls.mailFromExtension(opts) #

stable0.8.90
{
  requireTls: boolean,   // true to emit " REQUIRETLS"; falsy/absent → ""
}

Build the trailing SMTP MAIL FROM extension token for REQUIRETLS. Returns " REQUIRETLS" (with a leading space, ready to append) when opts.requireTls === true; empty string otherwise. The primitive does NOT validate the operator's address — that's the SMTP transport's job. This only emits the standard-defined token suffix.

Refuses non-object opts. requireTls must be a boolean when provided (any other type throws mail-require-tls/bad-flag) so a truthy-but-wrong-shape value (e.g. "yes") doesn't silently succeed.

var line = "MAIL FROM:" +
           b.mail.requireTls.mailFromExtension({ requireTls: true });
// → "MAIL FROM: REQUIRETLS"

b.mail.requireTls.parseTlsRequiredHeader(headerValue) #

stable0.8.90

Parse the RFC 8689 §5 TLS-Required header field. Returns:

- "no" when the value is the literal token no (case- insensitive, ignoring surrounding whitespace) — the sender EXPLICITLY opts out of REQUIRETLS-style behavior for this message. - "yes" for any other non-empty value — conservative default so an operator who set a typo / malformed value still gets the strict path (RFC 8689 §5: "if a recipient receives a message containing a TLS-Required field with any value other than 'No', it MUST be treated as if the field had been absent"). - null when the header is absent / empty / not a string — operator code branches on null vs "yes" / "no".

Refuses CR / LF / NUL in the value (header-injection-shape inputs shouldn't reach a parser that's downstream of header splitters anyway, but a defensive check here catches operator-side mistakes).

b.mail.requireTls.parseTlsRequiredHeader("No");      // → "no"
b.mail.requireTls.parseTlsRequiredHeader("no");      // → "no"
b.mail.requireTls.parseTlsRequiredHeader("  no  ");  // → "no"
b.mail.requireTls.parseTlsRequiredHeader("yes");     // → "yes"
b.mail.requireTls.parseTlsRequiredHeader("anything"); // → "yes" (RFC 8689 §5 default)
b.mail.requireTls.parseTlsRequiredHeader("");        // → null
b.mail.requireTls.parseTlsRequiredHeader(undefined); // → null

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