Settings

The From line is text the sender typed

A mail message is headers and a body, and the sending program writes the headers. From: is one of them. There is no step anywhere in delivery at which a server checks that the name and address on that line describe whoever is connecting; the line is copy, in the same sense the subject is copy.

Mail clients make this worse by showing the display name and hiding the address. A header reading From: "Northgate Bank Security" <[email protected]> arrives in most inboxes as the four words Northgate Bank Security, with the address one click away and nobody clicking. MAILBOX pulls the two apart and prints both, and flags the version of the trick where the display name is itself an address: From: "[email protected]" <[email protected]> renders as an address that is not the address the message came from.

Three checks were built to put something behind the From line. It is worth knowing what each one actually authenticates, because two of them do not authenticate that line at all.

SPF: which servers may send for a domain

SPF is a TXT record in the domain's DNS naming the servers allowed to send its mail. This site's own record is a short one:

obscuraos.com            TXT  "v=spf1 include:_spf.mx.cloudflare.net ~all"
_spf.mx.cloudflare.net   TXT  "v=spf1 ip4:104.30.0.0/19 ip6:2405:8100:c000::/38 ~all"

The receiving server takes the address the sending server gave in the SMTP conversation, looks up that domain's record, and checks the connecting IP against it. include: pulls in another domain's list. The final term covers everything not matched: ~all is a soft fail, -all a hard one.

Here is the part that surprises people. The address SPF checks is the envelope sender — what the sending server declared in MAIL FROM, which the receiver usually records in the Return-Path: header. That is not the From: a person reads. The two are allowed to differ, and they legitimately differ every time a mailing list or a ticketing system sends on someone's behalf.

So a forgery passes SPF without difficulty. Say the attacker owns bulk-sender.example. They send from a server that domain's own record lists, with an envelope sender on that domain, and a From: header reading Northgate Bank <[email protected]>. SPF passes, correctly, for bulk-sender.example. Nothing in SPF ever looked at the line the recipient reads.

DKIM: a signature over the headers and the body

DKIM adds a DKIM-Signature: header, a list of tags separated by semicolons:

DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=northgate.example;
  s=2026a; h=From:To:Subject:Date;
  bh=ScgELOspVwknVikNk/7ABFznVmSA0YaoWbW3Ppbtx2I=; b=…

d= is the signing domain and s= the selector. h= lists which headers were signed, in order — note that it is a list, so headers not named in it are not covered. bh= is a hash of the canonicalised body, base64-encoded; b= is the signature over the signed headers and that body hash. Change one word in the body and bh= becomes an unrelated value, which is what makes the body-hash check independent of the header check.

The public key lives in DNS, at selector._domainkey.domain, as another TXT record. It is an ordinary lookup anyone can do:

google._domainkey.anthropic.com  TXT  "v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A…"

Selectors are how a domain rotates keys and retires them: 20230601._domainkey.google.com still answers, but with v=DKIM1; k=rsa; p= — an empty p=, which is the form a retired key takes.

DKIM proves that the holder of the key for d= signed this message and that the signed parts have not been altered in transit. On its own it still does not tie anything to the From: line, because d= need not be the From domain. Mail sent through a marketing or ticketing platform is signed by the platform, which is entirely normal, and is also exactly what impersonation looks like.

DMARC: the check that is about the visible From

DMARC is a policy record at _dmarc. plus the domain, and it does the one thing the other two do not: it requires alignment. An SPF or DKIM pass only counts if the domain it passed for matches the domain in the From: header a person actually sees. Two real ones, both readable from DNS right now:

_dmarc.github.com      "v=DMARC1; p=quarantine; sp=reject; pct=100; rua=…; fo=1"
_dmarc.cloudflare.com  "v=DMARC1; p=reject; sp=reject; adkim=r; aspf=r; pct=100; rua=…"

p= is what the domain asks receivers to do with mail that fails: none means deliver it anyway and just send reports, quarantine means put it in the spam folder, reject means refuse it at the door. sp= sets the policy for subdomains, adkim and aspf set how closely the domains have to match, and rua= is where the reports go. A domain on p=none is publishing a policy that stops nothing; it is a monitoring setting, and plenty of organisations never move off it.

This is why a DMARC pass is the signal worth reading and an SPF pass on its own is not. Run the forged message described above through HEADERPROOF and it says so in as many words: SPF passed for bulk-sender.example, not for the sender domain (northgate-bank.example), so it does not vouch for the From address. It says the same about a DKIM signature from the wrong domain.

Reading the headers yourself

In Gmail, choose Show original; in Outlook, View message source; in Apple Mail, View, Message, All Headers. Two things are worth finding.

Authentication-Results is written by the server that accepted the message, so a sender cannot forge it — provided the server that wrote it is one you trust. The first token names that server, and the rest records each check with the domain it vouched for:

Authentication-Results: mx.example.net;
  spf=pass smtp.mailfrom=bulk-sender.example;
  dkim=pass header.d=bulk-sender.example;
  dmarc=fail header.from=northgate-bank.example

Read the domains, not just the words. smtp.mailfrom= is the domain SPF vouched for, header.d= the domain that signed, header.from= the domain a reader sees. Microsoft adds a compauth= of its own. A message can carry several of these headers; only the ones added by your own provider mean anything.

Received: lines are stamped by each server that handles the message, and each new one is added at the top. So the list reads newest first and the origin is at the bottom. Read upwards from there and the path assembles itself; the hops below the first server you trust were written by the sender and can say anything. MAILBOX reverses them into delivery order, extracts the IP address at each hop, and compares the timestamps — a hop stamped more than a minute earlier than the one before it, or a Date: header more than a day away from the delivery stamps, means one of those lines was not written by the machine it names.

What passing all three does not rule out

The attacks that defeat none of these checks are the common ones, because the domain really is the sender's domain and everything genuinely passes.

The display name. "Northgate Bank Security" on a throwaway domain authenticates perfectly for the throwaway domain. PHISHLENS checks the display name against a list of 61 brand names and reports when the name claims one brand and the address is on another.

The lookalike domain. A domain one character from a real one, or spelled with characters that read as Latin letters and are not, is registered and configured by the attacker: its SPF record lists their server, its DKIM key is theirs, and it can publish p=reject. PHISHLENS folds a domain to a skeleton before comparing — nineteen confusable characters mapped to their ASCII twins, 0 to o, 1 to l, 3 to e, 5 to s, then rn to m and vv to w — and flags a match within one edit of a known brand. It also flags xn-- names, which is how a non-Latin domain is actually encoded.

The account that is not forged at all. A compromised mailbox at a real company passes SPF, DKIM and DMARC because the message is genuinely from there. Authentication answers "did this come from that domain", never "did the person you think write it".

And no page in a browser can verify a DKIM signature, because doing that needs a DNS lookup for the public key and a browser cannot make one. MAILBOX reads the signature, reports which domain and selector it names, and says plainly that it is relying on the receiving server's verdict rather than repeating the check. That limit is why Authentication-Results matters so much, and why a message saved before delivery has no authentication story at all.

What this is, and what it is not

Two of the three checks are not about the From line. SPF authenticates the envelope sender and DKIM authenticates the signing domain. Only DMARC requires either of those to match the address a person sees, which is why a DMARC pass is the one worth reading.

Authentication-Results is the part a sender cannot write. The receiving server writes it after the checks have run, so nothing in the message can set it. That holds only for the header your own provider added; a message can carry others, written earlier by servers nobody vouches for.

A lookalike domain passes everything. The attacker owns it, so its SPF record lists their servers, its DKIM key is theirs, and it can publish p=reject. Authentication is not a spelling check.

Nothing here is uploaded. HEADERPROOF, MAILBOX and PHISHLENS parse a pasted message inside the browser tab. Nothing is fetched, no link is opened and no image in the message is loaded, which is why reading a suspicious message here is safer than opening it where it arrived.

No browser page can verify a DKIM signature. Checking one needs the public key from the signing domain's DNS, and a page in a browser cannot make a DNS query. These tools read the signature and report the receiving server's verdict rather than repeating the check.

Questions people ask

Can the From address be faked?

Yes, entirely. It is a header the sending software writes, like the subject. Nothing in the delivery path requires it to have any relationship to the server that connected or to the address that would receive a bounce.

SPF passed, so why is the message still fake?

Because SPF checks the envelope sender, the address given in MAIL FROM and usually recorded in Return-Path, not the From line displayed to you. A sender can pass SPF for a domain they own and still print your bank in the From header. DMARC is the check that requires those to line up.

Where do I find the full headers?

In Gmail, open the message and choose Show original. In Outlook, View message source, or File then Properties. In Apple Mail, View, then Message, then All Headers. Copy the whole block; the useful lines are at the top.

Which Received line shows where it came from?

The bottom one. Each server adds its line at the top, so the list runs newest first and the origin is last. Only the lines added after the message reached a server you trust are meaningful; anything below that was written by whoever sent it.

The domain looks almost right. Does that matter?

It is one of the strongest signals there is, and it is invisible to authentication. A domain one character off, or spelled with characters that resemble Latin letters, belongs to the attacker, so it can pass SPF, DKIM and DMARC honestly. Compare it letter by letter against an address you already had.

Everything passes and I am still unsure. What then?

Authentication answers whether a message came from a domain, never whether the person you have in mind wrote it; a compromised real account passes every check. When a message asks for money, credentials or urgency, confirm through a number or address you already had, not one taken from the message.

Related tools