Learn · Incident Response
Tracing an Email
Follow one message from the sender to every mailbox it reached: how mail flows, what a message trace and the headers record, and how to answer who received it and what happened next.
Why it matters
Many intrusions that start with a person start with an email. Every phishing report raises the same first questions: who else received it, was it delivered or stopped, and did anyone act on it.
Those answers live in mail-flow records, not in the copy the user forwarded. A forwarded message has lost the routing and authentication headers you need; the trace still has them.
What analysts see
Mail passes through several servers and services on its way in, and each one keeps its own record:
- The sending server's connection to your mail exchanger (MX): the address that connected and the name it gave.
- The secure email gateway's verdict: delivered, sent to junk, quarantined or rejected, and why.
- The mailbox platform's message trace: one row per recipient, each with a delivery status and the message ID.
- The message headers: a stack of
Receivedlines, one per hop, and the authentication results.
In Microsoft 365, message trace gathers this per recipient. On a self-hosted server the same story is spread across log lines that share a queue ID.
Core concept
Mail moves in hops. The sender's server hands the message to your MX, often a secure email gateway, which filters it and passes it on to the mailbox platform. Each hop adds a Received line at the top of the headers, so they read from the bottom up, oldest first.
Two identifiers tie the records together. The Message-ID is set once by the sender and is the same on every copy, so it finds every recipient. A queue or trace ID belongs to one server or service, so it follows the message through that one's own logs.
Authentication results say whether the sender's domain vouched for the message. SPF checks the sending server, DKIM checks a signature over the message, and DMARC checks that whatever passed matches the From domain the reader sees. A pass does not mean the message is safe, and when the domain the reader trusts does not pass DMARC, look closely.
Delivery is not the end. A message can be removed from mailboxes after delivery, and before that a user may open it, click a link or forward it. The trace tells you who received it; proxy, DNS, endpoint and sign-in records tell you who acted on it.
Annotated examples
Who else received it
A user reports a suspicious invoice. The message trace for its Message-ID:
- Message-ID:
- "<4f2a91c7@mail.vendor-invoices.example>" (note 1)
- From:
- "billing@vendor-invoices.example"
- recipient:
- "j.okafor@corp.example" Delivered
- recipient:
- "l.marsh@corp.example" Delivered
- recipient:
- "t.ng@corp.example" Quarantined (note 2)
- Note 1: Search on the Message-ID, not the subject. A campaign often varies its subject line, and unrelated mail can share one.
- Note 2: Three recipients, three records. The gateway quarantined one copy, so delivery was not uniform.
Two mailboxes received it. Those two users, not only the one who reported it, set the scope of what to check next.
Reading the headers
The same message's headers, from the delivered copy:
- From:
- "Accounts" <billing@vendor-invoices.example>
- Return-Path:
- <bounce@mailer.shipping-notices.example> (note 1)
- Authentication-Results:
- spf=pass smtp.mailfrom=shipping-notices.example; dkim=none; dmarc=fail header.from=vendor-invoices.example (note 2)
- Received:
- from mailer.shipping-notices.example (198.51.100.23) by mx1.corp.example (note 3)
- Note 1: The envelope sender, where bounces go, is a different domain from the
Fromline. Legitimate bulk mail does this too, so on its own it proves nothing. - Note 2: SPF passed, but for the envelope sender's domain. Nothing passed for the domain the reader sees, so DMARC failed.
- Note 3: The
Receivedline your own MX added records the address that actually connected. Lines below it were written by the sender and can be forged.
The message claims one domain, was sent through another, and the claimed domain did not vouch for it. Treat it as impersonation until something shows otherwise.
The same message on a self-hosted server
Where mail is handled by your own Postfix server, the trace is in its log:
- postfix/smtpd:
- connect from unknown[198.51.100.23] (note 1)
- postfix/cleanup:
- 7C1F2A1B3D: message-id=<4f2a91c7@mail.vendor-invoices.example> (note 2)
- postfix/qmgr:
- 7C1F2A1B3D: from=<bounce@mailer.shipping-notices.example>, nrcpt=2
- postfix/local:
- 7C1F2A1B3D: to=<l.marsh@corp.example>, status=sent (note 3)
- Note 1: The connecting address: the same one the
Receivedheader records. - Note 2: The queue ID,
7C1F2A1B3D, ties every line about this message together on this server. The Message-ID ties it to every other server and service. - Note 3: One delivery line per recipient. Search the queue ID to see them all.
On a self-hosted server, the queue ID is your message trace. Search on it, and every step and every recipient on that server lines up.
Delivered, then removed
Later that morning, the platform pulled the message from the mailboxes it had reached:
- delivery:
- "Inbox" 08:42 UTC
- post-delivery action:
- "Moved to quarantine" 09:16 UTC (note 1)
- reason:
- "URL reputation changed"
- proxy: url.domain:
- "login.vendor-invoices.example" 08:57 UTC (note 2)
- proxy: user.name:
- "l.marsh"
- Note 1: The message was removed 34 minutes after delivery. Removal does not undo anything a recipient did in between.
- Note 2: One recipient opened the link in that window. For that user, the incident is not over.
Check the window between delivery and removal. Anyone who acted on the message in that window is part of the incident, whether or not it was later quarantined.
How to investigate
- 1.
Get the Message-ID.
From the reported message's headers or the gateway record. Not the subject line, which campaigns vary.
- 2.
Trace every recipient.
Run a message trace on the Message-ID: every recipient, with a delivery outcome for each. On a self-hosted server, find the queue ID first and search on that.
email.message_id: "<4f2a91c7@mail.vendor-invoices.example>" - 3.
Read the authentication results and the first hop you trust.
Did the
Fromdomain vouch for the message? Which address actually connected to your MX? - 4.
Find what happened after delivery.
Was it removed later? Search proxy and DNS records for the link's domain, and endpoint records for any attachment, across every recipient it reached.
url.domain: "login.vendor-invoices.example" - 5.
Record the scope.
Every recipient, the delivery outcome for each, and who acted on it, with the evidence for each.
Common mistakes
Mistake: Searching on the subject line.
InsteadSearch on the Message-ID, or on the sender within a time window. Subjects vary within one campaign.
Mistake: Scoping to the person who reported it.
InsteadTrace every recipient. The person who reports a phish is often the one who did not click.
Mistake: Reading the
Fromline as the sender.InsteadCheck the envelope sender, the authentication results and the first
Receivedline your own servers added.Mistake: Treating quarantine as the end.
InsteadCheck what recipients did between delivery and removal.
Mistake: Trusting every
Receivedline equally.InsteadOnly the lines your own servers added are reliable. Anything below them was written by the sender.
Field references
| Field | What it tells you | Seen in |
|---|---|---|
| email.message_id | The Message-ID the sender set; the same on every copy. | Mail gateway, Microsoft 365 |
| email.from.address, email.to.address | The header sender and the recipients. | Mail gateway, Microsoft 365 |
| Return-Path | The envelope sender, where bounces go; often a different domain from From. | Message headers |
| Authentication-Results | SPF, DKIM and DMARC outcomes recorded by the receiving server. | Message headers |
| Received | One line per hop, newest at the top. | Message headers |
| queue ID | A self-hosted server's identifier for one message, shared by every log line about it on that server. | Mail server logs |
| url.domain | The domain of a requested link. | Proxy, DNS |
Apply it in a Case
Pick a case with mail telemetry. Before anything else, find the message, list every recipient and how delivery went for each, and only then look at what any of them did next.
- CuckooSkills: Investigation scoping · Log analysisTelemetry: Mail
- TollgateSkills: Investigation scoping · Log analysisTelemetry: Proxy
- DragnetSkills: Investigation scoping
References
- Message trace in the modern Exchange admin center · Microsoft
- Email authentication in Microsoft 365 · Microsoft
- Zero-hour auto purge (ZAP) in Exchange Online · Microsoft
- Domain-based Message Authentication, Reporting, and Conformance (DMARC), RFC 7489 · IETF
- Postfix logging · Postfix
- Email fields · Elastic Common Schema