Knowledge base

reject-spf-check-fail

<source>

Whether to reject a message when the SPF check explicitly fails
in the configuration this is a linereject-spf-check-fail trueinside the block <source>
The sender said “this is not us”

Of the three check outcomes this one is the most definite: the domain’s SPF record exists, it can be read, and it says that sending mail from this address is not allowed. The domain owner declared this themselves.

The line decides whether to reject such a message at the sender command — with a permanent refusal. The default is to reject.

Of the three, this is the only one whose default is beyond dispute. In the other two outcomes — an error in the record and a temporary failure — the sender declared nothing; here the declaration is explicit.

The main trap is forwarding. A message resent by a mailing list or a mail gateway arrives from the forwarder’s address, while its return address belongs to someone else. Such a message fails the check because of how the mechanism works, not because of forgery. By rejecting on the check, you reject all forwarded mail.
What the Hub does. It does not write it: nodes accept mail only from the Hub itself, and inbound checking is not enabled at all.
Recommended values

Keeping the refusal is fine. This is the only outcome where the sender has spoken directly.

But not where forwarding is expected. Mailing lists and mail gateways fail the check by design; for such sources the refusal has to be turned off.

The refusal is permanent. The sender will not retry — unlike with a temporary error.

The caveat about forwarding is ours. From the manual here come the default, the refusal code and the exact outcome on which the line triggers.
Example configuration
# we reject what the sender's domain itself did not acknowledge
<source 0/0>
    check-spf-inbound true
    reject-spf-check-fail true</source>
For sources through which forwarded mail arrives, this line is turned off: forwarding fails the check by design.
yellow — — directive names, blue — blocks. They are highlighted the same way in the text of the card.
▲

Common mistakes and problems

what people get wrong and how it ends2 mistakes▶

Rejecting on a source that forwarding goes through

our experience

What it costsA forwarded message arrives from the forwarder’s address with someone else’s return address — the check always fails. All forwarded mail is rejected, and it looks like a selective loss of messages.
How to spot itMessages from mailing lists and mail gateways do not arrive.
How to do it rightFor such sources, turn off the refusal while keeping the check and the header with the result.

Enabling it together with the other two without looking

our experience

What it costsThe three outcomes differ in nature: here the sender has spoken, while with an error in the record or a DNS failure it has not. The same decision for three different cases rejects more than necessary.
How to spot itRefusals fall on domains with sloppy rather than forged records.
How to do it rightDecide for each outcome separately.
Compatibility
PowerMTA 6.0
described in the manual of this version · platform: any
The vendor does not state the first version for every directive — there is no note here. The name also appears in the 5.0 edition of the manual.
Reference data
Syntax
reject-spf-check-fail <boolean>
Values
yes or no; true and false are accepted on a par with them
Default
true § 3.3.7.71
Applying
reload, no restart needed
Queue
will not touch what is already queued
Where to write it
<source>
How many times
once in the block
Everything here comes from the manual, with the section.
Inheritance
The value is set in a <source> block and applies to mail submitted through a matching source; with several matching blocks the most specific wins. It triggers only with check-spf-inbound enabled. It is picked up by pmta reload.
How to check on the node
The value is set in the source configuration; refusals are visible in the receiving log:
grep -n reject-spf-check /etc/pmta/config
grep -i 'spf' /var/log/pmta/pmta.log | tail -5
The refusal is issued at the sender command, that is, before the message is transferred — in the log it looks like a rejected command. The Hub does not write this line.
In the Hub
Cost of a mistake
dangerous: effects outlast a rollback
Scenarios
Bounce classification · Receiving inbound mail