SPF not checked for incoming email (missing Envelope-From)
Describe the bug
When an incoming email is downloaded from the Postal web panel and then analyzed locally with SpamAssassin using:
spamassassin -t -D spf < email.eml
The SPF plugin does not evaluate the message properly and logs the following debug message:
Nov 8 10:57:12.553 [1244] dbg: spf: checking to see if the message has a Received-SPF header that we can use
Nov 8 10:57:12.573 [1244] dbg: spf: using Mail::SPF for SPF checks
Nov 8 10:57:12.573 [1244] dbg: spf: cannot get Envelope-From, cannot use SPF
This shows that SpamAssassin is unable to get the Envelope‑From (Return‑Path) from the downloaded .eml file and as a result the SPF check is skipped.
To Reproduce
- Receive an incoming email in Postal
- Open the Postal web panel
- Download the raw message (
.emlfile) - Run the command:
spamassassin -t -D spf < email.eml - Observe the SPF debug output
Expected behaviour
SpamAssassin should be able to extract or infer the Envelope‑From of the message (e.g. from the Return‑Path: header) and perform SPF verification successfully, even when the message is analyzed manually after download.
I'm going to label this as a bug, I don't know much about it but after a quick look at the code I wouldn't be surprised if the code just accidentally misses out the headers sometimes or always
Actually the code only checks in one place so probably not too difficult for someone who knows ruby on rails to figure out if the headers are present
https://github.com/postalserver/postal/blob/b7e5232e077b3c9b7a999dcb6676fba0ec61458e/lib/postal/message_db/message.rb#L521
I believe that a header like Envelope-From is not stored at all in the database in the raw-table.
I was able to fix this by exposing the SMTP Envelope-From to SpamAssassin.
At the DATA stage, @mail_from is available but not added to the message headers, so SpamAssassin can’t detect the envelope sender and skips SPF.
I added this in app/lib/smtp_server/client.rb (DATA handler):
envelope_header = "<#{@mail_from}>"
@data << "X-Envelope-From: #{envelope_header}\r\n"
@headers["x-envelope-from"] = [envelope_header]
And then told SpamAssassin to use it:
envelope_sender_header X-Envelope-From
After this, SPF checks run correctly and the “cannot get Envelope-From” issue is gone.
@willpower232
well if you wanted to make a PR, that would be grand