Knowledge base

check-spf-inbound

<source>

Whether to check SPF for mail submitted to us
in the configuration this is a linecheck-spf-inbound falseinside the block <source>
Checking someone else’s mail on the way in

The flip side of check-spf-outbound: that one checks our outgoing mail, this one someone else’s incoming mail. The node checks the address a message came from against the SPF record of its sender’s domain and adds a header with the check result to the message.

By itself it rejects nothing. The result is only written into a header. Refusing on a failed check is controlled by three separate lines: reject-spf-check-fail, reject-spf-check-permerror and reject-spf-check-temperror — and all three reject by default.

Hence the order: by enabling the check, you immediately enable the refusals too. The line’s default is “do not check,” and that is the only thing keeping the node from refusing on the way in.

The main trap is that enabling it enables three refusals at once. The line looks observational: “check and record the result.” But the three refusal lines are already set to “reject,” and the very first message with a failed check will be rejected. If your own application submits mail through this source and the SPF record is not ready, submission will stop.
What the Hub does. It does not write it: nodes accept mail only from the Hub itself, and there is no point checking it against an SPF record — the submitter is known by the source address. The line will be needed if a node starts accepting mail from outside.
Recommended values

Enable it together with a decision about refusals. The three refusal lines reject by default; if only observation is needed, they have to be explicitly switched to “do not reject.”

Observation is a sensible first step. A week of recorded results with no refusals will show what you will reject once you turn them on.

For your own sources the check is redundant. The submitter is known by address; the SPF record answers a question that has already been settled.

The advice to start with observation is ours. From the manual here are the default, the added result header and the defaults of the three refusal lines.
Example configuration
# first we only observe: we check but do not reject
<source 10.0.0.0/8>
    check-spf-inbound true    reject-spf-check-fail false
    reject-spf-check-permerror false
    reject-spf-check-temperror false
</source>
Without the three lines below, enabling the check would immediately start rejecting messages: their default is to reject.
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▶

Enabling the check without touching the refusal lines

our experience

What it costsAll three reject by default. A message with a failed check is rejected in the same connection, and if it is your own application submitting, submission stops.
How to spot itAfter enabling it, the application gets refusals at the sender command.
How to do it rightFor the first week keep the three refusal lines off and watch the headers.

Enabling it for your own sources

our experience

What it costsThe submitter is already known by the source address, and the SPF record answers the same question via DNS. There is no benefit, but submission becomes dependent on someone else’s resolver.
How to spot itThe check is enabled in a source block with the addresses of your own machines.
How to do it rightLeave the check to external sources.
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
check-spf-inbound <boolean>
Values
yes or no; true and false are accepted on a par with them
Default
false § 3.3.7.22
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 precise one wins. It is picked up by pmta reload; it does not affect open connections.
How to check on the node
The value is set in the source configuration; the result is visible in the header the node adds to the message:
grep -n check-spf-inbound /etc/pmta/config
grep -i 'Authentication-Results' /var/log/pmta/pmta.log | tail -5
The header with check results is added when the check is enabled and stays in the message — that is where you look to see what the check showed. The Hub does not write this line.
In the Hub
Cost of a mistake
dangerous: effects outlast a rollback
Scenarios
Receiving inbound mail · Node security