This documentation covers version 1.0.3 of libspf2. It does not yet cover all public functions; however, it contains more than enough information to effectively use this library. Read the header files for more information. Please submit corrections or requests for missing information to libspf2 [ta] rt.anarres.org.
#include <spf2/spf.h>
The main spf2 header file must be included.
#include <spf2/spf_dns_resolv.h>
Include this for definitions relating to the basic SPF resolver.
#include <spf2/spf_dns_cache.h>
Include this for definitions relating to the caching SPF resolver.
SPF_err_t
An error code: an integer. See 'Error Codes' below.
SPF_config_t
A handle to an instantiation of the SPF library.
SPF_dns_config_t
A handle to an SPF DNS resolver.
SPF_c_results_t
A struct which holds the output from the SPF bytecode compiler.
SPF_output_t
A response from the SPF engine. This is a struct containing the following fields:
result
:
One of SPF_RESULT_PASS, SPF_RESULT_FAIL, SPF_RESULT_SOFTFAIL,
SPF_RESULT_NEUTRAL, SPF_RESULT_UNKNOWN, SPF_RESULT_ERROR,
SPF_RESULT_NONE.received_spf
:
A header to be inserted into the checked mail.smtp_comment
:
An SMTP error message XXX(?)err
:
The error message from the SPF library (justifying a failure?)
SPF_config_t SPF_create_config()
Construct a new handle for accessing the SPF library.
Return values:
(SPF_config_t)0
: If construction of the handle fails.(an opaque handle)
: If construction of the handle succeeds.
SPF_config_t SPF_dup_config(SPF_config_t handle)
Duplicate a handle for accessing the SPF library.
Return values:
(SPF_config_t)0
: If construction of the handle fails.(an opaque handle)
: If construction of the handle succeeds.
void SPF_destroy_config(SPF_config_t handle)
Destroy a handle for accessing the SPF library.
void SPF_set_debug(SPF_config_t handle, int debug)
Set the debugging level for an SPF handle. The SPF library allows a certain amount of debugging output to be generated for help in determining why things succeeded or failed. Currently, only the following debug levels are implemented:
SPF_dns_config_t SPF_dns_create_config_resolv(SPF_dns_config_t layer_below, int debug)
Create a handle for accessing a non-caching DNS resolver. The value passed for layer_below will be 0.
void SPF_dns_destroy_config_resolv(SPF_dns_config_t handle)
Destroy a handle for accessing a non-caching DNS resolver.
SPF_dns_config_t SPF_dns_create_config_cache(SPF_dns_config_t layer_below, int debug)
Create a handle for accessing a caching DNS resolver. The value passed
for layer_below will be a handle to a non-caching DNS resolver created
using SPF_dns_create_config_resolv
.
void SPF_dns_destroy_config_cache(SPF_dns_config_t handle)
Destroy a handle for accessing a caching DNS resolver.
void SPF_init_c_results(SPF_c_results_t *data)
Initialize the given compiler results structure so that it may receive the output of a compilation. This must be freed when it is no longer to be used.
void SPF_free_c_results(SPF_c_results_t *data)
Frees the bytecode contained in the SPF_c_results_t structure.
SPF_err_t SPF_compile_local_policy(SPF_config_t handle, const char *spf_record, int use_default_whitelist, SPF_c_results_t *c_results)
Several of the SPF specifications support a "local policy" option. This is both very important, and not particularly obvious how it works.
Email may come from many sources, sometimes these sources are not direct, and not all of these indirect sources correctly rewrite the envelope-from to specify the new domain that is resending the email. This can happen on incorrectly configured mailing lists, or from people who have set up unix-like .forward files.
Often, you want to accept these emails, even if they would technically fail the SPF check. So, you can set up a "local policy" that lists these sources of known-ok emails. If a local policy is set, it will allow you to whitelist these sources. There is a default globally maintained whitelist of known trusted email forwarders that is generally a good idea to use.
SPF checks that pass due to local policies will be noted in the messages generated from SPF_result(). As such, it is best if the local policy option is check only right before the SPF check is sure to fail. SPF records that say that a domain never sends email should not do any checking of the local policy.
The exact spot in the evaluation of the SPF record was defined in a message sent to the SPF-devel mailing list. It said in part:
Philip Gladstone says: Message-ID: <400B56AB.30702@gladstonefamily.net> Date: Sun, 18 Jan 2004 23:01:47 -0500 I think that the localpolicy should only be inserted if the final mechanism is '-all', and it should be inserted after the last mechanism which is not '-'. Thus for the case of 'v=spf1 +a +mx -all', this would be interpreted as 'v=spf1 +a +mx +localpolicy -all'. Whereas 'v=spf1 -all' would remain the same (no non-'-' mechanism). 'v=spf1 +a +mx -exists:%stuff -all' would become 'v=spf1 +a +mx +localpolicy -exists:%stuff -all'. This local policy string can be any string with macro variables included. It is first byte compiled, and then the result can be set in the configuration.
void SPF_set_local_policy(SPF_config_t handle, SPF_c_results_t c_results)
SPF_err_t SPF_compile_exp(SPF_config_t handle, const char *exp, SPF_c_results_t *c_results)
When the SPF check fails, an "explanation" string is generated for use by the MTA during the 4xx or 5xx reject code.
This explanation string can be any string with macro variables included. It is first byte compiled, and then the result can be set in the configuration. If an SPF record does not use the "exp=" modifier to specify a more appropriate explanation string, this default explanation string will be used.
int SPF_set_exp(SPF_config_t handle, SPF_c_results_t c_results)
Set the explanation string for the given SPF handle.
int SPF_set_rec_dom(SPF_config_t handle, const char *receiving_hostname)
Set the local hostname. Part of the Received-SPF: email header requires the domain name of the receiving MTA.
int SPF_set_ipv4(SPF_config_t handle, struct in_addr ipv4)
Set the IPv4 address of the SMTP client.
int SPF_set_ipv4_str(SPF_config_t handle, const char *ipv4_address)
Set the IPv4 address of the SMTP client.
int SPF_set_ipv6(SPF_config_t handle, struct in6_addr ipv6)
Set the IPv6 address of the SMTP client.
int SPF_set_ipv6_str(SPF_config_t handle, const char *ipv6_address)
Set the IPv6 address of the SMTP client.
int SPF_set_helo_dom(SPF_config_t handle, char *helohost)
Set the helo address of the SMTP client.
SPF needs both an IP address and a domain name to do its checking. The IP address is set by one of the above routines, but the domain name is not so simple.
The domain name is normally obtained from the envelope-from (SMTP MAIL FROM: command), but if that is null (MAIL FROM:<>), then the HELO domain is used (SMTP HELO or EHLO commands).
If there is no local part to the envelope-from email address, the name "postmaster" is used instead. This is the case when the HELO domain has to be used, but it might be able to happen with the envelope-from also, depending on how the MTA works.
Whatever the source of the domain name, the SPF spec defines this as the "current domain". Normally, you wouldn't set this directly, you would call the SPF_set_helo_dom() and SPF_set_env_from() routines. However, when an SPF record is being evaluated, the current domain is changed when an include or redirect mechanism is executed.
int SPF_set_env_from(SPF_config_t handle, char *from)
Set the 'MAIL FROM' address from the SMTP client.
SPF_output_t SPF_result(SPF_config_t handle, SPF_dns_config_t resolver)
Perform an SPF query based on the parameters specified in the handle, and return a result. The SPF_result() function does most of the real, important work.
SPF_result() checks the IP address and the envelope-from (or HELO domain) as was configured using the spfcid variable and sees if it is valid. It returns all the info that the caller will need to use the SPF check results. See the description of the structure SPF_output_t for details about the return value of SPF_result() and how they should be used.
It may use the DNS configuration to fetch additional information.
Actually, SPF_result() is just an easy-to-use wrapper around SPF_get_spf(), SPF_eval_id() and SPF_result_comments().
SPF_output_t SPF_result_2mx(SPF_config_t handle, SPF_dns_config_t resolver)
SPF_result_2mx() does everything that SPF_result() does, but it first checks to see if the sending system is a recognized MX secondary for the email recipient. If so, then it returns "pass" and does not perform the SPF query. Note that the sending system may be a MX secondary for some (but not all) of the recipients for a multi-recipient message, which is why SPF_result_2mx may be called many times with the final result being obtained from SPF_result_2mx_msg().
In effect, SPF_result_2mx() adds the mechanism "mx:
If you do not know what a secondary MX is, you probably don't have one. Use the SPF_result() function instead.
SPF_E_SUCCESS
SPF_E_NO_MEMORY
SPF_E_NOT_SPF
SPF_E_SYNTAX
SPF_E_MOD_W_PREF
SPF_E_INVALID_CHAR
SPF_E_UNKNOWN_MECH
SPF_E_INVALID_OPT
SPF_E_INVALID_CIDR
SPF_E_MISSING_OPT
SPF_E_INTERNAL_ERROR
SPF_E_INVALID_ESC
SPF_E_INVALID_VAR
SPF_E_BIG_SUBDOM
SPF_E_INVALID_DELIM
SPF_E_BIG_STRING
SPF_E_BIG_MECH
SPF_E_BIG_MOD
SPF_E_BIG_DNS
SPF_E_INVALID_IP4
SPF_E_INVALID_IP6
SPF_E_INVALID_PREFIX
SPF_E_RESULT_UNKNOWN
SPF_E_UNINIT_VAR
SPF_E_MOD_NOT_FOUND
SPF_E_NOT_CONFIG
SPF_E_DNS_ERROR
SPF_E_BAD_HOST_IP
SPF_E_BAD_HOST_TLD
SPF_E_MECH_AFTER_ALL