Posted:

How to read your e-mail headers

9 minute read

This is a corollary to E-Mail Done My Way, Part 3 - DKIM/DMARC/SPF. To really understand what problems exist with E-Mail since many years and how DKIM, DMARC, SPF and fail2ban help to deal with these problems, we need to understand what we can learn from good and bad e-mails reaching your InBox in 2022.

So that’s what we are going to do. We will look at the headers of a good and a bad e-mail. And I will explain what we can see there and how it helps to tune your mail server.

Same principle as in the series. I will show you the headers and we will go through it line by line to understand what happened and how we can solve problems with them.

Bad e-mail

Let’s start with a bad e-mail. This one (a real example) made it past all the tools I use on my mail server. It’s a rather typical Spam e-mail, that my mail client immediately put in the spam/junk mail folder.

Return-Path: <kanewilliamson038g@gmail.com>
Delivered-To: jan@wildeboer.net
Received: from mailhub.wildeboer.net
	by mailhub.wildeboer.net with LMTP
	id tcpZC0GzD2NGLwMA2EPHzg
	(envelope-from <kanewilliamson038g@gmail.com>)
	for <jan@wildeboer.net>; Wed, 31 Aug 2022 21:15:13 +0200
Received: from mail-pf1-x435.google.com (mail-pf1-x435.google.com [IPv6:2607:f8b0:4864:20::435])
	by mailhub.wildeboer.net (Postfix) with ESMTPS id 94EF52000542
	for <jan@wildeboer.net>; Wed, 31 Aug 2022 21:15:12 +0200 (CEST)
DMARC-Filter: OpenDMARC Filter v1.4.1 mailhub.wildeboer.net 94EF52000542
Authentication-Results: OpenDMARC; dmarc=pass (p=none dis=none) header.from=gmail.com
Authentication-Results: OpenDMARC; spf=pass smtp.mailfrom=gmail.com
DKIM-Filter: OpenDKIM Filter v2.11.0 mailhub.wildeboer.net 94EF52000542
Authentication-Results: mailhub.wildeboer.net;
	dkim=pass (2048-bit key, unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20210112 header.b=KY+YbDxR
Received: by mail-pf1-x435.google.com with SMTP id 199so15299077pfz.2
        for <jan@wildeboer.net>; Wed, 31 Aug 2022 12:15:12 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=gmail.com; s=20210112;
        h=date:organization:mime-version:to:subject:from:message-id:from:to
         :cc;
        bh=q3VIshMZEFrIZtHocrE19l2X8Om6eaIzu9zilRD46nE=;
        b=KY+YbDxR7UCJ/VPYZvYU5xltFzzyUhyO2F4fvgqqGqN83oWGl4afNQ5yqg0LV+8ZXx
         k4TUduHYpAQBEAZah9/tvA8o/3s2biRYdF7iSCqJtTd0PBARQgZ7YV7D2PQ0JlOE+TEk
         8Y1LFalLbFb4UHgM3HD7+//Cq5auRHl6J+P5jCpsCJJPpAQnpi53iwhLNPtWCDchNJFd
         voJ4TzXIjQnn2VdWNF0kM6p5lJQpbIy/67wSu4pUxBCOdpLsu3OARG5f3vwKDZ6r6o/C
         SDFzjJ7Cl4V/OxaOPpi0TNLJ/tRMIpd/AbC9SdrtiVqIa+BoeUJROQYp0tSlUTM66g3r
         TDmg==
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=1e100.net; s=20210112;
        h=date:organization:mime-version:to:subject:from:message-id
         :x-gm-message-state:from:to:cc;
        bh=q3VIshMZEFrIZtHocrE19l2X8Om6eaIzu9zilRD46nE=;
        b=7FdrrdWlXSJ8y1TwCtlS+MkXmCirJZ7Ym67QWNIgF2mULcEZeVtlnpWz0wJoFeE3KS
         1pUk6BsVNQAJM7oDnWcJb52ckTu7pvO1MmUctgbFj6L4I2mE+WWbCIY1xSrgC1wc5RRr
         eIkDrTkzq3RXqz1HSLuk9Mzz20PyyB8Z3YHOCVS6yGq32MSAGGaNJH17LREOL3lEMMBa
         RHSiUKe4c6objP3CjzKJkssQauM87PgMA6+D6NBXBdMVmLfEVIy0FDVNn6MeTI7vw8Z/
         0a+puab/7S4TQa0lDX54DwJFXiCHXlGF+GXT37I8zK/28AAiPpU53XEfEwxEX4DASdux
         ATPg==
X-Gm-Message-State: ACgBeo123Fcj8a0bt2b7JvhRrRx6lwdMH5v3yupVcXMPXEcUcuysueRU
	+rmL6EpcR0pzdMwu8SQzjZadIA4qEahG3khe
X-Google-Smtp-Source: AA6agR46uPA1NUCApjTC6xMYz5GFpm94g6POGj0noLz89fAzgLRjoHVCPPlUkMDR4lxWuo3q8r/6fg==
X-Received: by 2002:a63:2142:0:b0:42c:87a1:723a with SMTP id s2-20020a632142000000b0042c87a1723amr9142297pgm.319.1661973310220;
        Wed, 31 Aug 2022 12:15:10 -0700 (PDT)
Received: from 185.216.74.107 ([185.216.74.107])
        by smtp.gmail.com with ESMTPSA id je17-20020a170903265100b001754cfb5e21sm1207218plb.96.2022.08.31.12.15.08
        for <jan@wildeboer.net>
        (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128);
        Wed, 31 Aug 2022 12:15:09 -0700 (PDT)
Message-ID: <630fb33d.170a0220.ad19b.272b@mx.google.com>
From: "Lewis" <kanewilliamson038g@gmail.com>
Subject: Amount receiveing ID{874TG8734/U08}
To: "jan" <jan@wildeboer.net>
Content-Type: multipart/alternative; boundary="Kp7lxk13ALtOpaqV=_LgfLyjPflwfnI9D7"
MIME-Version: 1.0
Organization: Shipping & Handeling Team
Date: Thu, 1 Sep 2022 00:45:08 +0530

This is a multi-part message in MIME format

Wow. That’s a lot! But once you understand how e-mail works deep inside, it becomes quite obvious.

The way this e-mail is presented in my mail client is a dead give-away it is spam. I supposedly ordered something expensive (I didn’t) and it tries to coerce me into contacting them to clear this up (which I won’t).

spam

My mail client has an option to view the raw content of the email. which I used to extract all the headers.

E-Mail servers talk to each other using the SMTP protocol. This packages the content in an envelope, which your receiving e-mail server interprets and does away with before handing it over for local delivery. But we can see the important stuff from the headers that remain. So. Let’s go.

Return-Path: <kanewilliamson038g@gmail.com>
Delivered-To: jan@wildeboer.net
Received: from mailhub.wildeboer.net
	by mailhub.wildeboer.net with LMTP
	id tcpZC0GzD2NGLwMA2EPHzg
	(envelope-from <kanewilliamson038g@gmail.com>)
	for <jan@wildeboer.net>; Wed, 31 Aug 2022 21:15:13 +0200
Received: from mail-pf1-x435.google.com (mail-pf1-x435.google.com
[IPv6:2607:f8b0:4864:20::435])

This is the important part. Our mail server informs us it has received a message supposedly from <kanewilliamson038g@gmail.com>. It was delivered to me, Delivered-To: jan@wildeboer.net. My mail server, mailhub.wildeboer.net gives me a few more details from the envelope. The most important part being that the e-mail was sent to me from mail-pf1-x435.google.com.

That’s the first really important lesson. Only trust the information on the last hop before the e-mail reached my server. Whatever other claims exist about the chain of servers this e-mail went through - they can all be faked. As is typical for spam.

In this case there isn’t. This e-mail came from the IPv6 address 2607:f8b0:4864:20::435 (yes, my mail server does IPv4 and IPv6) which is a Google mail server.

So. What next?

DMARC-Filter: OpenDMARC Filter v1.4.1 mailhub.wildeboer.net 94EF52000542
Authentication-Results: OpenDMARC; dmarc=pass (p=none dis=none) header.from=gmail.com
Authentication-Results: OpenDMARC; spf=pass smtp.mailfrom=gmail.com
DKIM-Filter: OpenDKIM Filter v2.11.0 mailhub.wildeboer.net 94EF52000542
Authentication-Results: mailhub.wildeboer.net;
	dkim=pass (2048-bit key, unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20210112 header.b=KY+YbDxR

My e-mail server did a few checks using opendmarc and opendkim. The DMARC check came back with (p=none dis=none) using a dns lookup on gmail.com. This tells us that gmail unfortunately doesn’t really care and tells my mail server to just suck it up and accept everything. Hrmpf. Spammers love that policy. p=none means if an e-mail fails the DMARC test, there is no policy by the sending domain to do anything.

The next check is SPF. And it passed. So the IPv6 address 2607:f8b0:4864:20::435 is included in gmails SPF policy. Which according to another DNS check is:

gmail.com.		300	IN	TXT	"v=spf1 redirect=_spf.google.com"

So we need to ask again for the TXT entry in DNS on _spf.google.com which tells us:

_spf.google.com.	279	IN	TXT	"v=spf1 include:_netblocks.google.com include:_netblocks2.google.com include:_netblocks3.google.com ~all"

And to stop making this post too long - the IPv6 address is contained in there. So the SPF check passes.

Next, my mail server verifies the DKIM part:

DKIM-Filter: OpenDKIM Filter v2.11.0 mailhub.wildeboer.net 94EF52000542
Authentication-Results: mailhub.wildeboer.net;
	dkim=pass (2048-bit key, unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20210112 header.b=KY+YbDxR

Again, I will spare you the details, but gmail.com has a DKIM key in DNS with the selector 20210112 that my server got and used to verify the e-mail. The result: pass.

So the e-mail made it past all my checks because Google couldn’t be bothered to care :) Thanks, Google.

What normally happens to spam

Why do most spam and phishing don’t even make it my InBox? Mostly because they try to send from IP addresses that don’t have a reverse lookup delivering a hostname. That’s an immediate signal for my mail server to refuse:

Aug 31 19:57:59 mailhub postfix/smtpd[207687]: connect from unknown[193.239.164.117]
Aug 31 19:57:59 mailhub postfix/smtpd[207687]: NOQUEUE: reject: RCPT from unknown[193.239.164.117]: 450 4.7.25 Client host rejected: cannot find your hostname, [193.239.164.117]; from=<spameri@tiscali.it> to=<spameri@tiscali.it> proto=ESMTP helo=<WIN-CLJ1B0GQ6JP>

Hey, they are even friendly enough to say they are spammers ;)

Good e-mail

OK. So we just had a complicated example of a spammer successfully fooling Google to send out their sh*t. Now let’s look at a legitimate e-mail I got today. Again, look at the raw content and analyse the headers.

Return-Path: <bounces+715912-c849-jan=wildeboer.net@email.bandcamp.com>
Delivered-To: jan@wildeboer.net
Received: from mailhub.wildeboer.net
	by mailhub.wildeboer.net with LMTP
	id LJ7MLajlEGPqnQMA2EPHzg
	(envelope-from <bounces+715912-c849-jan=wildeboer.net@email.bandcamp.com>)
	for <jan@wildeboer.net>; Thu, 01 Sep 2022 19:02:32 +0200
Received: from o3.email.bandcamp.com (o3.email.bandcamp.com [198.21.0.215])
	by mailhub.wildeboer.net (Postfix) with ESMTPS id 515272000544
	for <jan@wildeboer.net>; Thu,  1 Sep 2022 19:02:32 +0200 (CEST)
DMARC-Filter: OpenDMARC Filter v1.4.1 mailhub.wildeboer.net 515272000544
Authentication-Results: OpenDMARC; dmarc=pass (p=none dis=none) header.from=bandcamp.com
Authentication-Results: OpenDMARC; spf=pass smtp.mailfrom=email.bandcamp.com
DKIM-Filter: OpenDKIM Filter v2.11.0 mailhub.wildeboer.net 515272000544
Authentication-Results: mailhub.wildeboer.net;
	dkim=pass (1024-bit key, unprotected) header.d=email.bandcamp.com header.i=@email.bandcamp.com header.a=rsa-sha256 header.s=smtpapi header.b=Tkgyw+fv
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=email.bandcamp.com;
	h=from:subject:mime-version:content-type:reply-to:to:cc;
	s=smtpapi; bh=VbFFXqpGTfLG7Yx/9l9qJh97tsfEP8MevzLoVUU1FQw=;
	b=Tkgyw+fvHdnc24K81wOBauh00f6LNnKt5CLzu2l0OhEe9HcfCQl75KcAmxRPGaniF+uo
	T1aIqTsfJrTFGI87HKKtP0ELNMCRJ953THzKf9YOdFdyTyFiYYd92JheWZ6E1HnJAL+PmS
	50HdL+GAGV1Hv4B/F11WJv7Uu8epktiy4=
Received: by filterdrecv-86d8dbf8cd-65vkw with SMTP id filterdrecv-86d8dbf8cd-65vkw-1-6310E5A7-8
        2022-09-01 17:02:31.039481173 +0000 UTC m=+586290.827290341
Received: from bandcamp.com (unknown)
	by geopod-ismtpd-canary-0 (SG)
	with ESMTP id -t9GSHgGQYyh_h_H8zdvEw
	for <jan@wildeboer.net>;
	Thu, 01 Sep 2022 17:02:30.971 +0000 (UTC)
From: Bandcamp <noreply@bandcamp.com>
Subject: New message from Austin Archer
MIME-Version: 1.0
Content-Type: multipart/alternative;
 boundary="it_was_only_a_kiss"
Message-ID: <-t9GSHgGQYyh_h_H8zdvEw@geopod-ismtpd-canary-0>
Reply-To: noreply@bandcamp.com
Date: Thu, 01 Sep 2022 17:02:31 +0000 (UTC)
X-SG-EID: 
 =?us-ascii?Q?MaCFGT5XhjPhXD86jTBuRKAKntck7LiU+1yGdAQOt1cpheZwrGzWrUQxJlUDvz?=
 =?us-ascii?Q?drCywp4GzhtFm4jL95LOuRAdaco=2FEueswhenRVe?=
 =?us-ascii?Q?u7IVRuofpWpoYcaO6RWwUD3t8hJu4+82R=2FSwdU5?=
 =?us-ascii?Q?NAp8SsY8WVvtif3uzPs+RL8HUmzy=2Fuq62mD5gIb?=
 =?us-ascii?Q?qUcMieA7YwkpxcCCkbmIjqE3dRbXx2PsmkB20+M?=
 =?us-ascii?Q?b60sT4OczCczpuHCw=3D?=
To: POKEY <jan@wildeboer.net>
X-Entity-ID: TYI/rBBQ/j3k7mGE92RFTA==

This is a multi-part message in MIME format.

Damn! That’s even more! But as we know our way around, we can read this fast and accurately.

Return-Path: <bounces+715912-c849-jan=wildeboer.net@email.bandcamp.com>
Delivered-To: jan@wildeboer.net
Received: from mailhub.wildeboer.net
	by mailhub.wildeboer.net with LMTP
	id LJ7MLajlEGPqnQMA2EPHzg
	(envelope-from <bounces+715912-c849-jan=wildeboer.net@email.bandcamp.com>)
	for <jan@wildeboer.net>; Thu, 01 Sep 2022 19:02:32 +0200
Received: from o3.email.bandcamp.com (o3.email.bandcamp.com [198.21.0.215])
	by mailhub.wildeboer.net (Postfix) with ESMTPS id 515272000544
	for <jan@wildeboer.net>; Thu,  1 Sep 2022 19:02:32 +0200 (CEST)

We can see: o3.email.bandcamp.com [198.21.0.215]) talked to our mail server. To deliver an e-mail to Delivered-To: jan@wildeboer.net which is me :)

DMARC-Filter: OpenDMARC Filter v1.4.1 mailhub.wildeboer.net 515272000544
Authentication-Results: OpenDMARC; dmarc=pass (p=none dis=none) header.from=bandcamp.com
Authentication-Results: OpenDMARC; spf=pass smtp.mailfrom=email.bandcamp.com
DKIM-Filter: OpenDKIM Filter v2.11.0 mailhub.wildeboer.net 515272000544
Authentication-Results: mailhub.wildeboer.net;
	dkim=pass (1024-bit key, unprotected) header.d=email.bandcamp.com header.i=@email.bandcamp.com header.a=rsa-sha256 header.s=smtpapi header.b=Tkgyw+fv
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=email.bandcamp.com;

It’s almost the same. My mail server looked up the DMARC/DKIM/SPF stuff and it all passed.

So what do we learn from here? My mail server does a lot of checks. Spammers know how to abuse that stuff. Google lets them happily do that. So. Sorry Google, I don’t really trust you. Whatever gmail address comes in - if I don’t have a history with that specific gmail address, it’s spam. Fix your stuff.

But stupid spammers that use infected Windows machines (typically) to send out thousands of spam emails - they are reliably caught and refused by my e-mail server.

Detecting spam is complicated. Because companies like Google just happily accept this kind of abuse. It’s disappointing, but that’s the way it is. Hrmpf.

COMMENTS

You can use your Mastodon or other ActivityPub account to comment on this article by replying to the associated post.