I often refer to the “headers you don’t normally see” when talking about email, how your email gets routed to your email account, how it lands or doesn’t land in spam filters, and how it ultimately makes its way to you.
I think you’d be surprised at how much information accompanies each email message to accomplish those tasks.
I can’t explain them all, but I think it’ll be helpful to review where to find them and what the most useful ones might mean – particularly when it comes to trying to diagnose spam, or understand unexpected delays.
I will warn you: this isn’t for the faint of heart. Email headers are both complex and geeky.
Become a Patron of Ask Leo! and go ad-free!
So-called “email headers” included (but typically not displayed) in email messages contain additional information about the message’s source, validity, and path from sender to recipient. Most email programs have a mechanism to view the original message source to expose all headers. “Received:” headers are often of greatest interest, as they show the servers handling the message along its way.
An example message
Let’s examine this example message in more detail.
It’s a simple two-line message with an attachment sent from a Gmail account (firstname.lastname@example.org) directly to a Hotmail account (email@example.com), and viewed in the Outlook.com web interface.
It seems simple — on the outside, anyway.
The headers you see
First, let’s address the information you can see without any additional steps. Even though Outlook.com isn’t displaying them in “header format” (which I’ll explain later), I’ll list them here that way exactly as they appear in the email message source, which we’ll view in a moment.
Immediately visible are:
- From: AskLeo Test <firstname.lastname@example.org>
In the message list in the top pane, Outlook.com shows us only the “display name”, which is “AskLeo Test”. In the message preview pane below, however, both display name and email address are displayed.
- Subject: A test message for us to use
The subject appears in both the message list (followed by the first part of the message body) and the header to the message preview pane.
- Date: Mon, 14 Sep 2020 13:19:29 -0700
As we’ll see shortly, the date can be represented several ways. Outlook.com displays it in your local format in both the message list and preview pane.
- To: email@example.com
I find it a little funny that Outlook.com is not displaying the email address the message was sent to, other than to say “you” in the preview pane. It assumes you know who “you” is, and what your own email address is.
Not present in this example is the “Cc:” header listing additional recipients to the email. (The “Bcc:” header is not included when email is sent.)
Viewing the hidden headers
In order to view all the geeky details of a message, we need to examine the original source of the message. Outlook.com (and most email programs) show us a sanitized, easy-to-consume version of the header information. There’s much, much more.
In Outlook.com, right-click the message in the message list in the top pane, and click on View message source.
This will bring up a small window containing the actual source of the email message as received by your email service.
It’s much longer than the box displays and includes a scrollbar to the right. You may prefer to select the message and copy/paste it to a text editing program like Notepad that you can resize to be larger. As you can see by the extremely reduced image to the right, the actual source of our “simple” message is quite large: 798 lines, in fact. Click here to view or download the example message as a txt file.
I’ve used Outlook.com as the example here, but most — though not all — email programs and interfaces have some kind of “view source” or “view original” functionality. Gmail, for example, has “Show original”. The Mail program with Windows 10, on the other hand, does not appear to have the ability to view the original message.1
Once you have the entire message in some comfortable viewer, we can start to examine some of the specifics.
In order to understand where headers begin and end, and how multiple lines can combine to form a single email header, we need to understand the formatting rules.
Everything in the email source up to the first blank line is an email header.
Each header begins with some text followed by a colon and a space. For example, “From:<space>” begins a header.
Any line without space, or in which a space happens without a colon in front of it is a continuation of the preceding line. So:
From: AskLeo Test
Would be considered one header, and would be treated just like:
From: AskLeo Test <firstname.lastname@example.org>
Each header ends when the next header is identified, or by a blank line, which signals the beginning of the message body.
A word about “multipart”
Somewhere in most messages (line 55 in our example) there may be a line similar to this:
Content-Type: multipart/mixed; boundary=”00000000000014489905af4bc141″
This is an example of a hidden header.
“Content-Type:” indicates a header with information about the type of content the message contains. In our example, it has multiple parts (“multipart”), and they are of “mixed” types. The boundary between the types is that long random-looking string: “00000000000014489905af4bc141”. (While a message need not be multipart, most are these days.)
If you search for that random-looking string, you’ll find it occurs a couple of times later:
Starting with a two hyphens, this indicates a boundary between parts.
At the very end of the message you’ll find:
Starting and ending with two hyphens this indicates the end of all parts.
Our message contains two parts:
The message body, which itself is another multi-part message with its own internal Content-Type: header and boundaries (note that the random-looking string is different). Its two parts are a plain text and HTML versions of the message text.
The attachment, a PNG file.
This indicates there are no more parts.
It’s the attachment which makes up most of the 798 lines in the message. The email protocol was never designed to handle binary data directly, so attachments (including in-line images) are encoded as text and included as one of the multiple parts of the message.
The headers we know
With that out of the way, use the search function in whatever you’re using to view the message source to search for “From: “. Near the “From:” header you’ll also find headers we’ve already discussed — Date:, Subject:, To:, and Content-Type: — plus one more:
From: AskLeo Test <email@example.com>
Date: Mon, 14 Sep 2020 13:19:29 -0700
Subject: A test message for us to use
Content-Type: multipart/mixed; boundary=”00000000000014489905af4bc141″
“Message-ID:” is some kind of ID string that uniquely identifies this message to the sending mail service (in this case, gmail.com).
You’ll see, though, these headers — which from our perspective are the most important headers, since they define sender, recipient, and subject — are buried in the middle of a bunch of other gobbledygook.
They’re buried in all the other hidden-to-us headers.
And now you can see why all the gobbledygook is hidden.
Headers we’ll (mostly) ignore
Headers beginning with “X-” are generally extensions to the standard headers we’ll talk about below. If you review the headers in our example, you’ll see many that are clearly unique to Google or Microsoft, apparently used for their internal tracking. Others are an informal industry standard, but are not necessarily required. They may contain interesting information, or they may contain something completely unintelligible to you and me.
For the most part, we’ll ignore X- headers, with two exceptions. I want to address this because it’s often why people go digging into headers in the first place.
This is the IP address of the sending server. In this case, the IP address maps to one of Google’s mail servers: mail-wm1-f45.google.com. Not surprising, since the message was sent using Gmail.
When present, this is the IP address of the computer that originated the message. You’ll see it’s not present in our message. In fact, the IP address of the location from which I sent this message, is not present at all. This is common, and most frustrating for people trying to find the IP address of the person, not the server, who sent them a message. That information is rarely available.
The “Received:” headers document the server-to-server path the email message took on its way from sender to recipient. Each server adds a “Received:” header to the top of the message with various pieces of information (some of which are optional).
- The name and/or IP address of the mail server or program sending the message
- The name and/or IP address of the mail server receiving the message
- The email address of the message’s destination
- The date and time
- Additional encoding and transport information
As you view a messages’ source, starting at the From: line and working upwards, you’ll find one or more “Received:” headers. Returning to our example:
- Received: by mail-wm1-f45.google.com with SMTP id x23so1225329wmi.3 for <firstname.lastname@example.org>; Mon, 14 Sep 2020 13:19:43 -0700 (PDT)
This line indicates the message was received first by Google’s mail-wm1-f45.google.com server for email@example.com, at 1:19:43 PM Pacific Daylight Time on September 14, 2020. This is the first server in the chain, and where the message began, presumably receiving the message from the Gmail web interface.
- Received: from mail-wm1-f45.google.com (188.8.131.52) by AM6EUR05FT046.mail.protection.outlook.com (10.233.241.175) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3370.16 via Frontend Transport; Mon, 14 Sep 2020 20:19:43 +0000
The message was then received by Microsoft’s server (AM6EUR05FT046.mail.protection.outlook.com) from Google’s server (mail-wm1-f45.google.com) at 8:19:43 PM UTC on September 14, 2020. This represents the hop from Google’s server to Microsoft’s. Note the time notation has switched from local time (Pacific Daylight Time or “-7 hours”) to UTC (aka Greenwich time). It doesn’t matter which is used, as long as the time zone indicator (-0700 or +0000 in this example) is present.
- Received: from AM6EUR05FT046.eop-eur05.prod.protection.outlook.com (2a01:111:e400:fc11::40) by AM6EUR05HT008.eop-eur05.prod.protection.outlook.com (2a01:111:e400:fc11::293) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3370.16; Mon, 14 Sep 2020 20:19:43 +0000
The message then went on to be received by Microsoft’s AM6EUR05HT008.eop-eur05.prod.protection.outlook.com from Microsoft’s AM6EUR05FT046.eop-eur05.prod.protection.outlook.com at 8:19:43 PM UTC on September 14, 2020.
- Received: from AM6EUR05HT008.eop-eur05.prod.protection.outlook.com (2603:10b6:300:103::20) by MWHPR12MB1630.namprd12.prod.outlook.com with HTTPS via MWHPR12CA0058.NAMPRD12.PROD.OUTLOOK.COM; Mon, 14 Sep 2020 20:19:44 +0000
The message was finally received by Microsoft’s MWHPR12MB1630.namprd12.prod.outlook.com from AM6EUR05HT008.eop-eur05.prod.protection.outlook.com at 8:19:44 PM UTC on September 14, 2020.
It’s not at all uncommon for a message to be passed along several servers, even within the same organization, as it makes its way from sender to recipient.
Routing headers can be used in a several interesting ways:
- Ensuring email came from where it claims to have. For example, if an email “From:” a Gmail address never touched a Google server, that’s suspicious.
- Ensuring the chain of servers is complete. If a server magically appears mid-list sending a message it technically never received, that’s suspicious.
- Diagnosing delays. Our message took a second or two to hop from server to server to server. If there’s a delay, however, you’ll see where in the chain that delay may have happened.
Headers and spam
Diagnosing the chain of servers handling the mail is certainly one interesting tidbit of data that spam filters can use, but much more information has been added in recent years to aid in its detection and prevention.
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
This is an example of a DKIM (Domain Keys Identified Mail) header. DKIM uses a cryptographic signature to confirm email claiming to have been send by a specific domain — gmail.com in our example for firstname.lastname@example.org — has actually been sent by that domain.
Received-SPF: Pass (protection.outlook.com: domain of gmail.com designates
184.108.40.206 as permitted sender) receiver=protection.outlook.com;
This is information relating to SPF (Sender Policy Framework). SPF uses entries in the DNS system (the same system that maps domain names like askleo.com to IP addresses) to indicate which servers are authorized to send email for specific domains. In the example above, the server at 220.127.116.11 is officially specified as being allowed to send email on behalf of gmail.com.
Exactly how the information provided by DKIM and SPF is used is ultimately up to the receiving email system. They can be ignored, treated as “advisory”, or taken as absolute indications of a message’s validity. Unfortunately, the latter is difficult at best, because of slow or inconsistent adoption. Most systems at least treat the information as an advisory data point when considering whether or not a message should be considered spam.
So. Much. More.
You can see from the number of headers in our “simple” email that we’ve only touched the tip of the iceberg. Not only may vender-specific entries be present, but mailing list software, remailers, and just about any software interested in sending email can add their own headers to carry along otherwise hidden information.
Hopefully, the information above will help explain the most common and the most useful.
Subscribe to Confident Computing! Less frustration and more confidence, solutions, answers, and tips in your inbox every week.
I'll see you there!
Footnotes & References
1: It was my hope to use it in this article, but not being able to show the source is why I ended up using Outlook.com instead.