Email·8 min read·

Mail-Tester, Headers, and Received Chains

A 10/10 mail-tester score is not inbox placement. Read Authentication-Results, the Received chain, and spam headers on a real Gmail or Outlook copy.

NB

Netbay Engineering

Netbay Engineering

On this page

mail-tester.com is a useful linter. It is not a delivery guarantee. A 10/10 means your SPF, DKIM, DMARC, PTR, and message structure look correct to that one checker. Gmail can still junk you. The skill is reading the headers on a message that actually arrived, especially the Received chain and Authentication-Results.

What mail-tester is good for

Send a message to the unique address the site gives you. It will flag:

  • Missing or over-permissive SPF, broken DKIM, absent DMARC.
  • PTR / HELO mismatch.
  • A blacklisted IP.
  • Missing Message-ID, Date, or a From that does not match DKIM d=.
  • Spammy content scores from SpamAssassin on that replica.

Fix everything it reports. Then go to a real inbox. The two tests answer different questions: "is my identity configured" versus "does this provider trust this IP today."

Read the Received chain upward top Received: last hop (inbox provider) middle Received: ESP or your VPS public IP bottom Received: local pickup / 127.0.0.1 Authentication-Results is the verdict spf, dkim, dmarc on the provider that mattered

Authentication-Results is the verdict line

On Gmail, open the message, three dots, Show original. You want a block similar to:

spf=pass (google.com: domain of bounce@example.com designates 203.0.113.40 as permitted sender) smtp.mailfrom=bounce@example.com dkim=pass header.d=example.com header.s=s1 dmarc=pass (p=REJECT) header.from=example.com

If SPF is pass and DMARC is fail, alignment is broken: mailfrom domain is not the From domain and DKIM d= does not match either. If DKIM is fail, the body or a signed header changed, or the TXT key is truncated. If everything passes and the mail is still in spam, the problem is reputation or content, not DNS.

Outlook's Authentication-Results and X-Forefront-Antispam-Report tell a similar story with different field names. CAT:SPM in the Forefront header means they classified it as spam after auth. Auth passing is necessary and not sufficient.

Walk the Received chain

Received headers are prepended, so read from the bottom up.

  1. Bottom: your app or pickup daemon on 127.0.0.1. This hop is unsigned and unsigned is fine.
  2. Next: your Postfix announcing HELO mail.example.com from the public IP, or your ESP's submission edge.
  3. Top: the receiving MX. This is the hop that ran SPF against the connecting IP.

If the public hop IP is not the IP in your PTR, you are looking at the wrong host (IPv6 surprise, or an outbound NAT). If you expected an ESP IP and see your VPS IP, the smarthost did not apply and you sent direct. That single observation explains a lot of "but SES is configured" tickets.

python
# Pull a raw message and print auth plus Received
import sys
text = sys.stdin.read().splitlines()
headers = []
for line in text:
    if line == "":
        break
    headers.append(line)
wanted = ("authentication-results", "received", "dkim-signature", "return-path")
idx = 0
while idx < len(headers):
    line = headers[idx]
    name = line.split(":", 1)[0].lower()
    if name in wanted:
        print(line)
        idx = idx + 1
        while idx < len(headers) and headers[idx][:1].isspace():
            print(headers[idx])
            idx = idx + 1
        print()
        continue
    idx = idx + 1

Pipe a saved .eml into that script. Folded header lines start with space or tab; do not treat them as new fields.

Other headers worth grepping

  • Return-Path: the envelope sender SPF used.
  • Message-ID: should be unique and from a domain you control, not localhost.
  • List-Unsubscribe: required for bulk; harmless on transactional if you omit it, dangerous if you send bulk without it.
  • X-Spam-Status or X-Spam-Score: added by the receiver or by Rspamd if you run a filter. A local 10/10 with a remote score of 8 means content or lists, not DKIM.

mxtoolbox, Google Postmaster Tools, and Microsoft SNDS are the ongoing monitors. mail-tester is a snapshot. Postmaster Tools needs DNS verification and days of volume before charts exist; set it up before you have a crisis.

Send a controlled test with a unique subject so you can find the copy later, then save the raw source.

bash
STAMP=$(date -u +%Y%m%dT%H%M%SZ)
sendmail -i you@gmail.com << END
Subject: probe $STAMP
From: alerts@example.com
To: you@gmail.com

probe body
END
dig +short TXT example.com
dig +short TXT s1._domainkey.example.com
dig +short TXT _dmarc.example.com
dig -x 203.0.113.40 +short

Compare the IP in the first public Received hop to the PTR you just looked up. If they disagree, stop sending and fix identity before you chase content scores.

Takeaway

Use mail-tester to catch identity bugs, then read Authentication-Results and Received on Gmail and Outlook. The chain tells you which IP actually sent. You can spin up an Ubuntu 24.04 instance on Netbay in under 60 seconds and send a test from a static Lucknow IP through a smarthost — netbayhosts.in.

Keep reading

Follow along on a real VPS

Deploy Linux in under 60 seconds

These guides are written against Ubuntu, Debian, and RHEL-family images — the same ones on NetBay.

Deploy an instance