Next: , Previous: , Up: Library   [Contents][Index]

5.37 SPF Functions

Sender Policy Framework, or SPF for short, is an extension to SMTP protocol that allows to identify forged identities supplied with the MAIL FROM and HELO commands. The framework is explained in detail in RFC 4408 (http://tools.ietf.org/html/rfc4408) and on the SPF Project Site. The following description is a short introduction only, and the users are encouraged to refer to the original specification for the detailed description of the framework.

The domain holder publishes an SPF record – a special DNS resource record that contains a set of rules declaring which hosts are, and are not, authorized to use a domain name for HELO and MAIL FROM identities. This resource record is usually of type TXT.27

The MFL script can verify if the identity matches the published SPF record by calling check_host function and analyzing its return code. The function can be called either in helo or in envfrom handler. Its arguments are:

ip

The IP address of the SMTP client that is emitting the mail. Usually it is $client_addr.

domain

The domain that provides the sought-after authorization information; Normally it is the domain portion of the MAIL FROM or HELO identity.

sender

The MAIL FROM identity.

helo_domain

The HELO identity.

my_domain

The SMTP domain served by the local server.

The function returns a numeric result code. For convenience, all possible return values are defined as macros in module spf.mfl. The table below describes each value along with the recommended actions for it:

None

A result of None means that no records were published by the domain or that no checkable sender domain could be determined from the given identity. The checking software cannot ascertain whether or not the client host is authorized. Such a message can be subject to further checks that will decide about its fate.

Neutral

The domain owner has explicitly stated that he cannot or does not want to assert whether or not the IP address is authorized. This result must be treated exactly like None; the distinction between them exists only for informational purposes

Pass

The client is authorized to send mail with the given identity. The message can be subject to further policy checks with confidence in the legitimate use of the identity or it can be accepted in the absence of such checks.

Fail

The client is not authorized to use the domain in the given identity. The proper action in this case can be to mark the message with a header explicitly stating it is spam, or to reject it outright.

If you choose to reject such mails, we suggest to use reject 550 5.7.1, as recommended by RFC 4408. The reject can return either a default explanation string, or the one supplied by the domain that published the SPF records, as in the example below:

  reject 550 5.7.1 "SPF check failed:\n%spf_explanation"

(for the description of spf_explanation, see spf_explanation)

SoftFail

The domain believes the host is not authorized but is not willing to make that strong of a statement. This result code should be treated as somewhere in between a Fail and a Neutral. It is not recommended to reject the message based solely on this result.

TempError

A transient error occurred while performing SPF check. The proper action in this case is to accept or temporarily reject the message. If you choose the latter, we suggest to use SMTP reply code of ‘451’ and DSN code ‘4.4.3’, for example:

  tempfail 451 4.4.3
           "Transient error while performing SPF verification"
PermError

This result means that the domain’s published records could not be correctly interpreted. This signals an error condition that requires manual intervention to be resolved, as opposed to the TempError result.

The following example illustrates the use of SPF verification in envfrom handler:

require 'status'
require 'spf'

prog envfrom
do
  switch check_host($client_addr, domainpart($f), $f, $s)
  do
  case Fail:
    string text ""
    if spf_explanation != ""
      set text "%text\n%spf_explanation"
    fi
    reject 550 5.7.1 "SPF MAIL FROM check failed: %text"

  case Pass:
    accept

  case TempError:
    tempfail 451 4.4.3
             "Transient error while performing SPF verification"

  default:
    on poll $f do
    when success:
      accept
    when not_found or failure:
      reject 550 5.1.0 "Sender validity not confirmed"
    when temp_failure:
      tempfail 450 4.7.0 "Temporary failure during sender verification"
    done
  done
done

The SPF support is implemented in MFL in two layers: a built-in layer that provides basic support, and a library layer that provides a convenience wrapper over the library function.

The library layer is implemented in the module spf.mfl (see Modules).

The rest of this node describes available SPF functions and variables.

Built-in Function: number spf_check_host (string ip, string domain, string sender, string helo_domain, string my_domain)

This function is the basic implementation of the check_host function, defined in RFC 4408, chapter 4. It fetches SPF records, parses them, and evaluates them to determine whether a particular host (ip) is or is not permitted to send mail from a given email address (sender). The function returns an SPF result code.

Arguments are:

ip

The IP address of the SMTP client that is emitting the mail. Usually it is $client_addr.

domain

The domain that provides the sought-after authorization information; Normally it is the domain portion of the MAIL FROM or HELO identity.

sender

The MAIL FROM identity.

helo_domain

The HELO identity.

my_domain

The SMTP domain served by the local server.

Before returning the spf_check_host function stores additional information in global variables:

spf_explanation

If the result code is Fail, this variable contains the explanation string as returned by the publishing domain, prefixed with the value of the global variable spf_explanation_prefix.

For example, if spf_explanation_prefix contains ‘The domain %{o} explains: ’, and the publishing domain ‘example.com’ returns the explanation string ‘Please see http://www.example.com/mailpolicy.html’, than the value of spf_explanation will be:

The domain example.com explains:
Please see http://www.example.com/mailpolicy.html

(see RFC 4408, chapter 8, for the description of SPF macro facility).

spf_mechanism

Name of the SPF mechanism that decided about the result code of the SPF record. If one or more ‘include’ or ‘redirect’ mechanisms were traversed before arriving at that mechanism, their values are appended in the reverse order.

Built-in Function: number spf_test_record (string record, string ip, string domain, string sender, string helo_domain, string my_domain)

Evaluate SPF record record as if it were published by domain. The rest of arguments are the same as for spf_check_host above.

This function is designed primarily for testing and debugging purposes. You would hardly need to use it.

The spf_test_record function sets the same global variables as spf_check_host.

Library Function: number check_host (string ip, string domain, string sender, string helo)

This function implements the check_host function, defined in RFC 4408, chapter 4. It fetches SPF records, parses them, and evaluates them to determine whether a particular host (ip) is or is not permitted to send mail from a given email address (sender). The function returns an SPF result code.

This function is a wrapper over the built-in spf_check_host.

The arguments are:

ip

The IP address of the SMTP client that is emitting the mail. Usually it is the same as the value of $client_addr.

domain

The domain that provides the sought-after authorization information; Normally it is the domain portion of the MAIL FROM or HELO identity.

sender

The MAIL FROM identity.

helo

The HELO identity.

Library Function: string spf_status_string (number code)

Converts numeric SPF result code to its string representation.

Built-in variable: string spf_explanation

If check_host (or spf_check_host or spf_test_record) returned Fail, this variable contains the explanation string as returned by the publishing domain, prefixed with the value of the global variable spf_explanation_prefix.

For example, if spf_explanation_prefix contains ‘The domain %{o} explains: ’, and the publishing domain ‘example.com’ returns the explanation string ‘Please see http://www.example.com/mailpolicy.html’, than the value of spf_explanation will be:

The domain example.com explains:
Please see http://www.example.com/mailpolicy.html
Built-in variable: string spf_mechanism

Set to the name of a SPF mechanism that decided about the result code of the SPF record.

Built-in variable: string spf_explanation_prefix

The prefix to be appended to the explanation string before storing it in the spf_explanation variable. This string can contain valid SPF macros (see RFC 4408, chapter 8), for example:

set spf_explanation_prefix "%{o} explains: "

The default value is ‘""’ (an empty string).


Footnotes

(27)

Although RFC 4408 introduces a special SPF record type for this purpose, it is not yet widely used. As of version 9.0, MFL does not support SPF DNS records.


Next: , Previous: , Up: Library   [Contents][Index]