Expand description
Who really sent a message, from what the servers recorded.
It reads the Authentication-Results headers (RFC 8601) written by your own
provider, and nobody else’s: any sender can write that header into a
message, so only the ones carrying an authserv-id you trust count (RFC 8601
§5 and §7.1). Providers differ in what they record, so Sioul also checks
each message itself as it is fetched (sioul_sync::verify, with
Stalwart’s mail-auth): its results are one more such header, under its own
id (config::sioul_authserv_id),
trusted first.
The spam verdicts of the provider’s own filters (SpamAssassin, rspamd) are read here too, for the same reason: they are only as good as their source.
Structs§
- Auth
Results - What one Authentication-Results header says.
- Boundary
- Where the message entered your provider: the first server, from the top of
the
Receivedchain, that handed it over from a public address. SPF and the reverse DNS are checked on it; every hop below it could be written by anyone. - Dkim
Pass - A DKIM signature that passed, as a results header records it: the
signer’s domain (
header.d, else the domain ofheader.i), its selector (header.s) and the start of the signature itself (header.b), when written. - Spam
Verdict - The verdict of the provider’s own spam filter, when it left one.
Enums§
- Outcome
- The result of one authentication method (RFC 8601 §2.7).
- Proof
- Why the sender is believed or not; the sentence is the translator’s (
i18n). - Trust
- How far the sender can be believed.
Constants§
- LEARN_
MINIMUM 🔒 - Messages needed before an id is learned.
- MICROSOFT_
INSIDE 🔒 - The names Microsoft 365’s servers carry between themselves, as each
writes its own after
by: its mailboxes and relays (*.prod.outlook.com,*.prod.exchangelabs.com), its frontends inside (*.outlook.office365.com) and its filters (*.prod.protection.outlook.com).
Functions§
- aligned 🔒
- Whether two domains belong together, as DMARC’s relaxed alignment has it:
the same, or the same organisational domain (
organisational): “mail.example.org”, “shop.example.org” and “example.org” do; “a.github.io” and “github.io” do not, nor “victim.co.uk” and “co.uk”: a name under a public suffix belongs to whoever registered it. - arc_
sealer - The domain that sealed the newest ARC set: the
d=of theARC-Sealwith the highest instance (i=), lower case (RFC 8617 §4.1.3). - authenticated
- Whether a message is authenticated, as the results its account trusts
record it (
read_auth_results: Sioul’s own stamp, else your provider’s). It is not when SPF and DKIM both failed, unless DMARC passed, or ARC passed on a chain whose newest seal is a sealer’s you trust (sealers: your provider’s, your own domains’;arc_sealer): forwarding breaks SPF, and a forwarder that changes the message breaks DKIM, but anyone can seal a chain of their own. “none” (nothing published to check) is no failure, nor is a softfail; no results at all say nothing. DMARC failing under a policy is forged (judge_sender), set aside before this is asked. Mail that is not authenticated is not taken as coming from the address it shows (porch.rs: its sender is a stranger). - boundary
- Walking down from the top as
written_on_arrivaldoes, your provider’s own hops passed (inside_hop), the first other line: where the message came in, when the address its server saw reads (seen_ip) and is public. A line written another way gives none: the lines below it are the sender’s to write, so no address of theirs is taken for where it came in. - bracketed_
ip 🔒 - The address the receiving server saw,
[203.0.113.7]or[IPv6:2001:db8::1], in a Received header’sfromclause:from helo (rdns [203.0.113.7]),from rdns ([203.0.113.7]:5126 helo=x), orfrom [203.0.113.7] (helo=x)when the address has no name. The first word is, with most servers, the name the sender gave in HELO, which it may write[192.0.2.1], as it may thehelo=in the parentheses: neither counts while the server wrote the address it saw. - dkim_
passes - The DKIM signatures that passed, read from the header
read_auth_resultsreads (the topmost from a server you trust); none from a header that cannot be read to its end. - from_
clause 🔒 - A
Receivedline’sfromclause, up to “ by “: its first word (the name given in HELO, with most servers; the reverse DNS name with qmail) and what follows it; none for a line withoutfrom. - helo_
group 🔒 - The name a group gives in HELO, qmail’s “(HELO mail.sender.example)”.
- inside_
hop 🔒 - A hop inside your provider, as its
Receivedline says: nofrom, a private or local address in it, the delivery into the mailbox, or a hop between Microsoft 365’s own servers (microsoft_hop). - is_
public 🔒 - judge
- The verdict on the sender, when the domain shown is not at hand: the domain
DMARC was checked for stands for it. See
judge_sender. - judge_
sender - The verdict on the sender, and why. A DMARC failure is a forgery when the
domain asks receivers to act on it (quarantine, reject, or a provider’s
result that does not say); with
p=none, or on a mailing list, which rewrites what it relays, it only leaves the sender unverified. - leading_
groups 🔒 - The parenthesised groups that open
text, one after the other: “(HELO x) (203.0.113.5) with SMTP” → “HELO x”, “203.0.113.5”. - learn_
provider_ id - The authserv-id your provider writes, learned from its mail: the id of the topmost Authentication-Results header of most messages.
- lmtp 🔒
- “… with LMTP id …”, LMTPS, LMTPA, LMTPSA (RFC 3848): the mailbox’s own delivery.
- mail_
from - The envelope sender (MAIL FROM), as the receiving server recorded it in Return-Path;
empty for a bounce (
<>). - microsoft_
hop 🔒 - A hop between Microsoft 365’s own servers: received by one of the names
they carry between themselves (
MICROSOFT_INSIDE). Those hops pass the message from one public address of Microsoft’s to another, so an address cannot tell them from where the message came in, which is the hop received by its Internet frontend,*.mail.protection.outlook.com(“Received: from mail.sender.example (203.0.113.25) by BN8NAM12FT034.mail.protection.outlook.com (10.13.182.135) with Microsoft SMTP Server … via Frontend Transport”). The receiving server writes its own name, and the lines above where the message came in are Microsoft’s: no sender writes one of them. - number_
after 🔒 - organisational
- A domain’s organisational domain, as DMARC’s relaxed alignment reads it
(RFC 7489 §3.2): the name registered under its public suffix, by the
Public Suffix List (“mail.example.co.uk” → “example.co.uk”; the
pslcrate carries the list). None for a public suffix itself (“co.uk”, “github.io”), which nobody owns as a whole. - parenthesised_
ip 🔒 - The address in parentheses without brackets, right after the first word, as Microsoft 365 and Exchange write it (“from mail.sender.example (203.0.113.25) by …”, “(2001:db8::25)”), and qmail (“from unknown (HELO mail.sender.example) (203.0.113.5) by …”; “(ident@203.0.113.5)”, where what comes before the last “@” is what the sender’s ident service said). The group holds the address alone, a HELO group before it passed: a group holding anything else is not read.
- parse_
auth_ 🔒results - Parses
authserv-id [version]; method=result props; ..., comments removed. - read_
auth_ results - The topmost Authentication-Results header written by a server you trust.
- read_
spam_ verdict - Reads SpamAssassin’s X-Spam-* headers, else rspamd’s, among the fields
your provider wrote (
written_on_arrival) and nowhere else: a sender writes what it likes into its own message, “X-Spam-Flag: NO” too, and its outgoing server’s filter judges what it sends, not what you receive. - record_
method 🔒 - Records
method=result: several DKIM signatures count as a pass if any passes, and a DMARC failure is never undone by a pass beside it. - results_
of 🔒 - The results of a header, split at the semicolons between them, comments
removed (they may nest: “(google.com: domain of (x))”), and whether every
quote and comment was closed. A semicolon, a parenthesis or an equals sign
inside a quoted string belongs to a value: a sender chooses the address
"a; dmarc=pass b"@example.org, and checkers write it as it is, quoted (RFC 8601 §2.2, RFC 5322 §3.2); a backslash escapes the next character. - route_
ips - The IP addresses of the servers the message came through, newest first.
- rspamd 🔒
X-Spamd-Result: default: True [12.30 / 15.00]; ...,X-Spam: Yes,X-Rspamd-Score.- seen_ip 🔒
- The address the receiving server saw, in any of the forms servers write
it: in brackets (
bracketed_ip), else in parentheses alone (parenthesised_ip: Microsoft 365, Exchange, qmail). - spamassassin 🔒
X-Spam-Flag: YES,X-Spam-Status: Yes, score=9.1 required=5.0 tests=....- words_
of 🔒 - The words of a result, a quoted string kept whole:
pass smtp.mailfrom="a b"@x. - written_
on_ 🔒arrival - The fields your provider wrote on a message once it took it in, top to
bottom: those above the
Receivedline where it came in from the Internet.