How to Read an Email Header
Every email carries a record of the servers it passed through and what each of them thought of it. Most of that record can be forged by the sender, but the part that cannot is added by your own provider, sits at the top, and answers the question people open headers to ask.
Getting at the headers
What you normally see is a summary. The full message source contains dozens of lines above it. Look in your client for show original, view source, message details or properties: in web clients it is usually in the menu next to reply, and in desktop clients under a view or file menu. What you get is plain text, and it is read from the bottom upwards.
Why bottom-up
Each server that handles a message adds a Received: line at the top of the existing headers. The result is a stack in reverse chronological order: the last line is the first hop, and the first line is your own provider.
This matters for a reason beyond ordering. A sender can fabricate as many Received: lines as they like before sending, inventing a plausible journey through respectable servers. What they cannot fabricate is the line your provider added when it accepted the message, that one was written after the forgery was out of the sender's hands.
So the rule is: trust downwards from the top until you reach a server you do not recognise, and treat everything below that point as unverified. The first genuinely informative line is the one where your provider records who actually connected to it.
The fields worth reading
- Authentication-Results:: the summary of SPF, DKIM and DMARC checks, written by your receiving server. This is the most valuable line in the header, and it is covered on its own below.
- Received:: one per hop, each naming the connecting host, its address, the receiving server and a timestamp. Read from the bottom, trust from the top.
- Return-Path:: the envelope sender, where bounces go. This is what SPF actually checks, and it is frequently a different domain from the one in the From line. A mismatch is normal for mailing lists and marketing platforms, and notable on a message claiming to be personal.
- From:: the display name and address you see in the client. Free text. This is the field being forged when a message impersonates someone.
- Reply-To:: where your reply is actually addressed. Set to an attacker-controlled mailbox, it turns a spoofed message into a working conversation, and most clients never show it.
- Message-ID:: a unique identifier generated by the sending system, usually ending in the sending domain. A Message-ID whose domain has nothing to do with the claimed sender is a weak but real signal.
- Date:: set by the sender's machine, and therefore no better than the sender. Compare it against the timestamps in the Received chain, which were written by servers.
- DKIM-Signature:: the signature block. Read d= for the signing domain and s= for the selector; the signing domain is the identity DKIM actually vouches for.
- X- headers: non-standard fields added by mail servers, filters and sending platforms. They frequently name the bulk-mail provider, the spam score assigned, and occasionally the campaign the message belongs to.
- List-Unsubscribe:: present on legitimate bulk mail, and its absence on something claiming to be a newsletter is worth noticing.
The one line that settles most questions
If you only read one thing, read Authentication-Results. It records what your provider concluded:
- spf=pass: the connecting server was authorised to send for the envelope domain. Note: the envelope domain, which may not be the domain you can see.
- dkim=pass: the signature verified, so the message was not altered and the signing domain vouched for it.
- dmarc=pass: the important one. It means SPF or DKIM passed and was aligned with the domain in the visible From line. This is the check that ties what you see to what was proven.
A message claiming to be from a major bank with dmarc=fail has answered your question. The mechanics of why are in the email authentication guide.
dmarc=pass does not mean the message is safe. It means the message genuinely came from the domain printed in the From line. A lookalike domain, one character different, or the brand name in front of an unrelated word, passes its own DMARC perfectly, because the attacker owns that domain and configured it properly. Authentication proves the domain; whether the domain is the right one is still a human judgement, and it is the judgement phishing is built to defeat.
About the IP addresses
The routine hope is that a header reveals where the sender was sitting. It usually does not.
Major webmail providers have for years stripped the originating address from outgoing mail, so the earliest address in the chain is the provider's own outbound relay, a data centre, shared by millions of users. Mail from a self-hosted server, some corporate systems and older desktop clients may still carry the real originating address, which is why it is worth looking even though the answer is usually a relay.
When you do have an address, read it for what it can support: the network, the operator, whether it is hosting or residential, and the reverse DNS name. It identifies a connection at a moment, not a person, the reasoning is set out in the IP guide.
A reading order
- Read Authentication-Results first. A DMARC failure on a message impersonating a known brand ends the analysis.
- Compare From, Return-Path and Reply-To. Three different domains on a supposedly personal message is the classic spoofing shape.
- Check the DKIM d= domain against the brand being claimed.
- Walk the Received chain from the top until you reach a server you do not recognise, and stop trusting there.
- Compare the Date header against the server timestamps. A large discrepancy means the sender's clock was wrong, deliberately or otherwise.
- Look at the earliest trustworthy address, and read it as a network rather than a location.
- Investigate the sending domain separately: registration age, DNS and mail posture, per the domain investigation guide.
What headers cannot tell you
They cannot identify a person. At best they identify a domain that authenticated and a server that connected, both of which can be rented anonymously for the price of a coffee.
They also cannot detect the most dangerous category of all: a genuine message from a genuinely compromised mailbox. Thread hijacking, a reply arriving inside a conversation you were already having, from the real address, with the real history quoted, passes every check in the header because nothing about it is forged. Against that, headers are silent, and the only defence is the content and an out-of-band check on anything irreversible.
Keep the original if it matters. Forward-as-attachment, or save the raw source to a file. Forwarding a message normally rewrites the headers, and a reported phishing message with its headers destroyed is far less useful to anyone investigating it.
Check the sending domain's live SPF, DMARC and DNS records with the MyRecon domain tool.
Questions people ask
Can I find the sender's real IP address in an email header?
Usually not. Major webmail providers have stripped the sender's own address from outgoing headers for years, so the earliest address you see is typically the provider's outbound server. Mail from a self-hosted server or an older client may still expose it.
Which header fields can be forged?
All of the ones the sender writes: From, Reply-To, Date, Message-ID, and any Received lines added before the message reached a server you trust. The only trustworthy parts are the headers your own provider added, at the top.
What does dmarc=pass actually mean?
That the domain shown in the From line matched a domain that genuinely authenticated, via SPF or DKIM. It confirms the message really came from that domain. It says nothing about whether the domain is honest, a lookalike domain passes its own DMARC perfectly.
Where do I find the full headers?
It varies by client, but the wording is similar: show original, view source, or message details. Web clients usually put it in the menu beside the reply button; desktop clients under a view or properties menu.