The Apache Software Foundation

Setting up SPF

You just finished installing a James IMAP server and wonder how to gain trust for it?

The Sender Policy Framework (SPF) is an open standard specifying a technical method to prevent sender address forgery. It might help you to do this.

More precisely, SPF protects the envelope sender address, which is used for the delivery of messages. It allows the owner of a domain to specify their mail sending policy, e.g. which mail servers they use to send emails from their domain.

To correctly configure SPF for your domain, you need to answer the following questions:

  • From what server or servers will email from my domain originate? In our case, we only want our James Server to be able to send emails from our domain.
  • How do you want illegitimate email to be handled? -all is an SPF fail and usually means dropping such emails, whereas ~all is an SPF softfail and traditionally means accepting but marking them.

Therefore, we add the following DNS records to our DNS zone file:

@ IN TXT “v=spf1 +a:james.test-domain.com -all”
@ IN SPF “v=spf1 +a:james.test-domain.com -all”

That way other mail servers know only james.test-domain.com can send mails for test-domain.com.

Verifying SPF for incoming emails

Now we will see how to verify SPF records of incoming emails. For this we can customize mail processing, and specify actions upon SPF record validity. For introducing these components, James relies on the JSPF library.

We just need to edit the mailetcontainer.xml configuration file as follow:

We are going to create a new processor called SPFProcessor. It will handle emails after the root processor but before the transport processor. Moreover, we do not need to perform a SPF check or take a decision if the sender is authenticated or is a local user, because we already trust him. In all other cases, we add a SPF header using the SPF mailet. Then we need to take a decision about incoming emails. We use the HasMailAttributeWithValue matcher which has seven possible values to handle in the case of SPF: permerror, temperror, none, pass, neutral, fail and softfail. What action you choose for each of these values depends on what you want to do. In our case, we redirect SPF errors and fails to the error processor, whereas all other cases lead directly to the transport processor for further normal processing. We are rather tolerant since we authorize softfails.

For example:

[...]

<processors>
  <processor state="root" enableJmx="true">
    <mailet match="All" class="PostmasterAlias"/>
    <mailet match="RelayLimit=30" class="Null"/>
    <mailet match="All" class="ToProcessor">
      <processor>SPFProcessor</processor>
    </mailet>
  </processor>

  <processor state="error" enableJmx="true">
    [...]
  </processor>

  <processor state="SPFProcessor">
    <mailet match="SenderIsLocal" class="ToProcessor">
      <processor>transport</processor>
    </mailet>
    <mailet match="SMTPAuthSuccessful" class="ToProcessor">
      <processor>transport</processor>
    </mailet>
    <mailet match="All" class="SPF">
      <addHeader>true</addHeader>
    </mailet>
    <mailet match="HasMailAttributeWithValue=org.apache.james.transport.mailets.spf.result, permerror" class="ToProcessor">
      <processor>error</processor>
    </mailet>
    <mailet match="HasMailAttributeWithValue=org.apache.james.transport.mailets.spf.result, temperror" class="ToProcessor">
      <processor>error</processor>
    </mailet>
    <mailet match="HasMailAttributeWithValue=org.apache.james.transport.mailets.spf.result, none" class="ToProcessor">
      <processor>transport</processor>
    </mailet>
    <mailet match="HasMailAttributeWithValue=org.apache.james.transport.mailets.spf.result, pass" class="ToProcessor">
      <processor>transport</processor>
    </mailet>
    <mailet match="HasMailAttributeWithValue=org.apache.james.transport.mailets.spf.result, neutral" class="ToProcessor">
      <processor>transport</processor>
    </mailet>
    <mailet match="HasMailAttributeWithValue=org.apache.james.transport.mailets.spf.result, fail" class="ToProcessor">
      <processor>error</processor>
    </mailet>
    <mailet match="HasMailAttributeWithValue=org.apache.james.transport.mailets.spf.result, softfail" class="ToProcessor">
      <processor>transport</processor>
    </mailet>
    <mailet match="All" class="LogMessage">
      <headers>true</headers>
      <body>false</body>
      <comment>Unknown SPF result</comment>
    </mailet>
  </processor>

[...]