Reading headers: where did this email come from?
Module 1: How email works · Reading time: 11 minutes
Learning objective: After this lesson you'll be able to open an email's headers, read the Received lines in the right order, and work out from Authentication-Results whether SPF, DKIM and DMARC passed.
Key terms: headers, RFC 5322, Received, Return-Path, From, Reply-To, Message-ID, DKIM-Signature (d=, s=), Authentication-Results, ARC, X-headers, source or original message
What you normally don't see
Your mail program shows you a few details about an email: sender, subject, date, recipients. In reality, every email has dozens of headers at the top, before the text. They're added by the sender's program and by every server the email touches along the way. Together they form the email's travel log.
If you can read headers, you can answer a lot of questions yourself: is this email really from my bank? Why did it only arrive after two hours? Why did it end up in spam? Is my own DKIM working correctly? Many exercises in this course ask you to look at headers. In this lesson you'll learn how.
Opening headers
Each program has a different button for it:
| Program | Where |
|---|---|
| Gmail (web) | Three dots on the right of the message, Show original |
| Outlook (new and web) | Three dots, View, View message details |
| Outlook (classic) | Open the message, File, Properties, the "Internet headers" box |
| Apple Mail (Mac) | View menu, Message, All Headers (or Raw Source) |
| Thunderbird | View menu, Message Source (Ctrl+U) |
| Roundcube (webmail) | Open the message, More, Show source (or Headers) |
On a phone this usually isn't possible. In that case, forward the email to yourself as an attachment, or open it in webmail.
An example
Jan receives an email from Anna. Here's what the most important headers look like (shortened):
Return-Path: <anna@example.com>
Delivered-To: jan@example.net
Received: from mx1.mailprovider.example (localhost [127.0.0.1])
by mailbox3.mailprovider.example with LMTP; Sun, 08 Nov 2026 10:15:09 +0100
Received: from out.hosting.example (out.hosting.example [192.0.2.25])
by mx1.mailprovider.example with ESMTPS id 4F2A1B
for <jan@example.net>; Sun, 08 Nov 2026 10:15:07 +0100
Received: from [198.51.100.77] (helo=[10.0.0.12])
by out.hosting.example with ESMTPSA (TLS1.3)
(authenticated as anna@example.com); Sun, 08 Nov 2026 10:15:04 +0100
Authentication-Results: mx1.mailprovider.example;
spf=pass smtp.mailfrom=example.com;
dkim=pass header.d=example.com header.s=x;
dmarc=pass header.from=example.com
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=example.com; s=x;
h=From:To:Subject:Date:Message-ID; bh=...; b=...
From: Anna <anna@example.com>
To: Jan <jan@example.net>
Subject: Offerte
Date: Sun, 8 Nov 2026 10:15:00 +0100
Message-ID: <a1b2c3@example.com>Received lines: from bottom to top
Every server that passes the email on adds a Received: line at the top. So the oldest line is at the bottom and the newest is at the top. Read them from bottom to top to follow the journey:
- Bottom line: Anna's laptop (IP
198.51.100.77, her home connection) delivers toout.hosting.example, usingESMTPSA(the A stands for authenticated: she logged in) and TLS 1.3. At 10:15:04. - Middle line:
out.hosting.example(192.0.2.25) delivers tomx1.mailprovider.example, the MX for example.net. At 10:15:07. - Top line: the mail server places the email internally into Jan's mailbox (LMTP). At 10:15:09.
A Received line always has the form from <who offered it> by <who accepted it> with <protocol>; <time>. In brackets after from is what the receiving server itself observed: the real name (PTR) and the real IP address. That part is reliable, to the extent that you trust that receiving server. What the sender itself claimed (helo=) cannot be verified.
Two practical tricks:
- Finding a delay: compare the times. If there's a two-hour gap between two lines, the email sat in a queue that long at that point. Watch out for time zones (
+0100,+0000). - Finding the real sending server: look for the topmost Received line that was written by a server belonging to the recipient itself, and check what's after
fromthere. Everything below that was written by the sending side and could, in theory, be made up. In the example,192.0.2.25is the server that delivered to the recipient; that's the one SPF and reputation are judged against.
The addresses
| Header | What it is | Who sets it |
|---|---|---|
Return-Path | The envelope sender (MAIL FROM, lesson 1.2). This is where bounces go. SPF checks this domain. | The receiving server, on delivery |
From | The sender you see. DMARC protects this domain. | The sender |
Reply-To | Where a reply goes, if it needs to be different from From. | The sender |
To, Cc | The visible recipients. BCC doesn't appear here. | The sender |
Delivered-To | The mailbox the email was actually delivered to (useful with forwarding). | The receiving server |
Message-ID | A unique number for the email. Useful for finding an email again in a log. | The sender |
A well-known scammer's trick: a From that looks like your bank, with a Reply-To pointing to a completely different address. If in doubt, always check the domain in From and in Return-Path, and look at Authentication-Results.
Authentication-Results: the recipient's verdict
The receiving server records the results of its checks in Authentication-Results (RFC 8601):
spf=pass smtp.mailfrom=example.com: the IP of the delivering server is listed in the SPF record of the domain inReturn-Path.dkim=pass header.d=example.com header.s=x: the DKIM signature for domainexample.com, with key (selector)x, checks out.dmarc=pass header.from=example.com: the domain inFromis aligned with a successful SPF or DKIM check, so DMARC passed.
Other results you may see: fail (didn't check out), softfail (SPF ends in ~all and the IP isn't listed), neutral, none (no record), temperror (temporary DNS error) and permerror (broken record, for example two SPF records). What these mean exactly and how to fix them is covered in module 4.
Note: only trust the Authentication-Results from the recipient's own server (the name at the front, here mx1.mailprovider.example). A forged email can include its own, made-up Authentication-Results. Good servers strip these out, but not all do.
DKIM-Signature: the signature
The DKIM-Signature header is the signature itself. You often need two fields from it:
d=the domain that's signing (hereexample.com);s=the selector, the name of the key (herex).
Together these let you find the public key in DNS: x._domainkey.example.com. In exercises and when troubleshooting, you'll often need to look up exactly these two values. An email can have more than one DKIM signature, for example one from your domain and one from the sending service. We'll go into this in more depth in lesson 4.3.
You may also sometimes see ARC-Seal, ARC-Message-Signature and ARC-Authentication-Results. ARC (RFC 8617) is a way for intermediate stops, such as a mailing list or a forwarding server, to record what the checks showed before they changed the email. You don't need to be able to read these yet.
X-headers
Headers starting with X- aren't standardised. Spam filters put their score in them, such as X-Spam-Status: No, score=1.2 or X-Spam-Flag: YES. This helps you see why something ended up in spam. They differ by provider.
Summary
- Headers are an email's travel log. Open them with "show original", "message source" or something similar.
- Read Received lines from bottom to top. The line written by the recipient's own server tells you which IP delivered the email.
Return-Pathis the envelope sender (SPF),Fromis the visible sender (DMARC),Reply-Tois where replies go.Authentication-Resultsgives the verdict on SPF, DKIM and DMARC; only trust the one from the receiving server.DKIM-Signaturecontainsd=(domain) ands=(selector); together they give the location of the key:s._domainkey.d.
Quiz
Exercise
Exercise Z1.5: Having headers parsed. Send yourself an email from a different address (for example, from your work address to your personal address, or the other way round), open the headers, and paste them into the form. If you don't have a second address, use the sample file kopregels-1.txt provided with the exercise. Then fill in yourself: the IP address of the server that delivered to the recipient, the domain in Return-Path, the domain and selector of the DKIM signature, and the SPF, DKIM and DMARC results. The program parses the same headers, looks up the DKIM key live, and places its result next to yours. Your headers are not stored.
Further reading
The steps in these articles apply to WebOké's control panels; with other providers it works in a similar way.
- Checking whether an email has arrived with Email Tracking in DirectAdmin
- DirectAdmin guide 9.3: E-mail Tracking: where did my mail go?
- Is this email really from WebOké? Recognizing phishing and using the promo code
- Free DNS course 4.4: DKIM: the signature under your mail
- RFC 5322 (structure of an email), RFC 8601 (Authentication-Results), RFC 6376 (DKIM), RFC 8617 (ARC)
