Compose the Received: field for the handler to write
RFC 5321 §4.4 requires a receiving server to stamp a trace field, and this
one had no way to produce one: composing it needs a clock, the peer address
and the session's own state, and the session had the last of those only.
`Options.received` supplies the other two — an `Io` to read the clock from
and the peer description, which the caller has because it accepted the
connection and this library has not, since it is handed a reader and a
writer and never sees an address. With it set, every message arrives at the
handler with `Envelope.received` filled in: the complete field, `Received: `
prefix and trailing CRLF included.
The handler writes it. The library never touches the message bytes — it has
no idea whether they are being spooled, relayed or parsed — and the field
belongs at the beginning of the content, which only the handler can arrange.
Left unset, nothing is composed, and that is the caller's choice rather than
a default worth having.
The layout comes from zig-mime's `received` helper and the timestamp from
zig-datetime, pinned to the same revision zig-mime uses so the two do not
become two incompatible copies of one type. What goes in the field is read
off the session: the greeting name the client gave (escaped, since the peer
chose it), the RFC 3848 protocol name for whether the hop was encrypted,
authenticated, LMTP or SMTPUTF8, and a `for` clause only when there is
exactly one recipient — with more than one it would tell each about the
others.
The demo server writes it ahead of the body, which is what the live check
looked like:
Received: from localhost ([127.0.0.1:32946])
by localhost (zig-smtp) with ESMTP
for <b@example.net>; Sun, 13 Sep 2026 03:23:04 +0000
README: the gap is closed, the Status and Server sections say how it works,
RFC 3848 joins the standards list, and RFC 8689 — implemented but never
cited — joins the references. RFC 3848, RFC 8689, zig-mime and zig-datetime
are filed in the Zotero collection, which is now named for the project
rather than for what it used to be called.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SDrB41sGu5k1ubD1ufbxqC