0

An SPF record has several tags of which one can be the include tag, and the SPF record ends with a quantifier like +, ?, ~ or -.

When an include tag is used, the included SPF record has it’s own SPF quantifier. Let’s call the quantifier from the included SPF record “child-quantifier”.

Does that “child-quantifier” apply on the hosts it defines only and the “parent-quantifier” on everything but the child-defined hosts? Or does the parent-quantifier always overrule all included (child-)quantifiers?

For example:

  1. example1.com (let’s say parent) contains the following SPF record: v=spf1 a include:example2.com -all
  2. example2.com (let’s say child) contains the following SPF record: v=spf1 a ip4:1.2.3.4 ?all

Now does the ?all (child-)quantifier or the -all (parent-)quantifier apply on ip4:1.2.3.4?

The included SPF record might also have includes, and so it can reach a depth of multiple levels on which my question also applies.

1

With the include mechanism the "included" SPF statement is not literally included in the original one but only the result of it is used. From section 5.2 of RFC 7208:

In hindsight, the name "include" was poorly chosen. Only the evaluated result of the referenced SPF record is used, rather than literally including the mechanisms of the referenced record in the first. For example, evaluating a "-all" directive in the referenced record does not terminate the overall processing and does not necessarily result in an overall "fail".

This means, that the result of the "included" SPF statement is treated as a match, not match or permerror similar to every other SPF statement. The standard even explicitly contains a table how the result of the "included" SPF statement affects the main statement:

+---------------------------------+---------------------------------+
| A recursive check_host() result | Causes the "include" mechanism  |
| of:                             | to:                             |
+---------------------------------+---------------------------------+
| pass                            | match                           |
|                                 |                                 |
| fail                            | not match                       |
|                                 |                                 |
| softfail                        | not match                       |
|                                 |                                 |
| neutral                         | not match                       |
|                                 |                                 |
| temperror                       | return temperror                |
|                                 |                                 |
| permerror                       | return permerror                |
|                                 |                                 |
| none                            | return permerror                |
+---------------------------------+---------------------------------+
0

Translating the documentation to your example:

In the following example, the client IP is 1.2.3.4 and the current-domain is example1.com.

v=spf1 include:example2.com -all

If example2.com has no SPF record, the result is PermError.

Suppose example2.com's SPF record were v=spf1 a -all.

Look up the A record for example2.com. If it matches 1.2.3.4, return Pass.

If there is no match, other than example2.com's -all, the include as a whole fails to match; the eventual result is still Fail from the outer directive set in this example.

Trust relationships — The include: mechanism is meant to cross administrative boundaries. Great care is needed to ensure that include: mechanisms do not place domains at risk for giving SPF Pass results to messages that result from cross user forgery. Unless technical mechanisms are in place at the specified otherdomain to prevent cross user forgery, include: mechanisms should give a Neutral rather than Pass result. This is done by adding ? in front of include:. The example above would be:

v=spf1 ?include:example.com -all


So, trust is transferred to the "child" domain (and there are mechanisms to limit that impact).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.