For years I've received occasional failed-delivery notifications from some domains, most notably sbcglobal.net:
<user>@*sbcglobal.net*: 550 5.7.1 Connections not accepted from servers without a valid sender domain.alph758 Fix reverse DNS for <ip address>
The perplexing part is that my mail server's IP address has the correct reverse DNS entry.
This is New
As noted above, I've had this problem off-and-on for years. This case, however, was new.
It started with a failed-delivery notification for an email I sent to a friend in reply to her email, replying to an initial email I sent. What made this case different was the initial email went through. In other words, the flow looked like:
- Self: Send to friend (no failure)
- Friend: Reply to received email
- Self: Reply to friend's email (failure notification)
Clearly it couldn't be a simple reverse DNS issue. That is, unless the owner of my IP is intermittently returning invalid results, which isn't likely. Nevertheless, the fact that one went through provided a clue to guide further research.
I began looking at mail headers:
- Received header - nothing notable
- DKIM-Signature - passed validation
I noticed a second Received header showing the rejected email came from localhost. Multiple Received headers aren't a problem. That happens all the time as an email passes from host to host. I continued scanning.
Then I noticed the Message-Id had the fully-qualified hostname (FQHN) of my laptop, not the mail server or the sending domain:
"Hmmm", I thought. "that's accurate, it came from my laptop, but there are no SPF or DMARC records for that FQHN."
At that moment I realized why the first email went through. Until today I had assumed the errors had to do with server or DNS configuration. I hadn't considered the MUA might be the problem. Yet there it was. The first email was sent from my desktop using Mail.app. The reply was sent from my laptop using mutt(1) through msmtp.
"Perhaps one of them is misconfigured, but which generates the Message-Id?", I wondered.
A quick check confirmed that mutt generates the Message-Id, leaving only one question: "Can I set the value mutt uses?"
It's mutt. Of course you can set it.
You just need to know what to set. In this case it wasn't hard to find.
If you search for Message-Id in muttrc(5), you'll discover two plausible options: hidden_host, and hostname.
hidden_host is not the answer. The documentation clearly states:
This variable does not affect the generation of Message-IDs, and it will not lead to the cut-off of first-level domains.
hostname is the correct option. With it you can set the FQHN mutt uses when generating Message-Ids. Left unset, however, the default is the FQHN of the host machine.1
hostname ... [s]pecifies the fully-qualified hostname of the system mutt is running on containing the host's name and the DNS domain it belongs to. It is used as the domain part (after "@") for local email addresses as well as Message-Id headers.
After some experimentation, and based on what I know about SPF, I determined the hostname value doesn't have to be the FQHN of the server hosting the MTA. It does, however, need to be the domain or FQHN with a valid SPF record pointing to the server of the MTA.2 Typically this will be the domain of your email address.
In other words, if you're sending mail as firstname.lastname@example.org from laptop.example.com through server mail.example.net, the Message-Id must set example.org as the FQHN. And example.org must publish an SPF record authorizing example.net to send email for the domain. You don't want to use mutt's default of laptop.example.org.3
Or in my case:
With that change, email from my laptop began flowing to my friend, and a perplexing, multi-year annoyance was resolved.4
More or less. Read the entry in muttrc(5) for complete details on how mutt determines which value to use.↩︎
It's not obvious to me from the spec that the FQHN in the Message-Id must have an SPF record.↩︎
You could set hostname to example.net if example.net publishes an SPF record authorizing the same mail server to send for example.net. I wouldn't do that. I tested it. it works for my domains, but it could lead to subtle issues later. The safest option is to always set hostname to the domain portion of the sender's email address.
The situation gets more complex when using mutt to send through msmtp to handle multiple From addresses. My mutt configuration allows me to send through Gmail. Setting hostname to my domain and then sending through msmtp to Gmail means the FQHN portion of the Message-Id generated by mutt will contain whatever is specified in hostname, not gmail.com. My personal mail server accepts those emails without issue. My guess is it will fail with servers like those at sbcglobal.net that are more pedantic in checking the Message-Id.↩︎
We'll overlook the fact that the failure-message from sbcglobal.net is wrong. It's not a reverse-look-up problem. It's an error in the SPF record or MUA configuration, as I discovered.
The issue may not be unique to sbcglobal.net. It may originate with their MTA, Sendmail 8.15.2, or perhaps a milter that handles SPF validation. Regardless, a more useful failure message might read:
No SPF record for host <host.domain.tld> in Message-Id↩︎