This PHP library allows you to:
- get the SPF record from a domain name
- decode and validate the SPF record
- create the value of a TXT record
The implementation is based on RFC 7208.
You can install this library with Composer:
composer require mlocati/spf-lib
An SPF record is composed by zero or more terms. Every term can be a mechanism or a modifier.
This library allows you to inspect them:
$decoder = new \SPFLib\Decoder();
try {
$record = $decoder->getRecordFromDomain('example.com');
} catch (\SPFLib\Exception $x) {
// Problems retrieving the SPF record from example.com,
// or problems decoding it
return;
}
if ($record === null) {
// SPF record not found for example.com
return;
}
// List all terms (that is, mechanisms and modifiers)
foreach ($record->getTerms() as $term) {
// do your stuff
}
// List all mechanisms
foreach ($record->getMechanisms() as $mechanism) {
// do your stuff
}
// List all modifiers
foreach ($record->getModifiers() as $modifiers) {
// do your stuff
}
Please note that:
- all mechanisms extend the
SPFLib\Term\Mechanism
abstract class. - all modifiers extend the
SPFLib\Term\Modifier
abstract class. - both mechanisms and modifiers implement the
SPFLib\Term
interface.
$txtRecord = 'v=spf1 mx a -all';
$decoder = new \SPFLib\Decoder();
try {
$record = $decoder->getRecordFromTXT($txtRecord);
} catch (\SPFLib\Exception $x) {
// Problems decoding $txtRecord (it's malformed).
return;
}
if ($record === null) {
// $txtRecord is not an SPF record
return;
}
use SPFLib\Term\Mechanism;
$record = new \SPFLib\Record('example.org');
$record
->addTerm(new Mechanism\MxMechanism(Mechanism::QUALIFIER_PASS))
->addTerm(new Mechanism\IncludeMechanism(Mechanism::QUALIFIER_PASS, 'example.com'))
->addTerm(new Mechanism\AllMechanism(Mechanism::QUALIFIER_FAIL))
;
echo (string) $record;
Output:
v=spf1 mx include:example.com -all
$record = (new \SPFLib\Decoder())->getRecordFromTXT('v=spf1 all redirect=example1.org redirect=example2.org ptr:foo.bar mx include=example3.org');
$issues = (new \SPFLib\SemanticValidator())->validate($record);
foreach ($issues as $issue) {
echo (string) $issue, "\n";
}
Output:
[warning] 'all' should be the last mechanism (any other mechanism will be ignored)
[warning] The 'redirect' modifier will be ignored since there's a 'all' mechanism
[notice] The 'ptr' mechanism shouldn't be used because it's slow, resource intensive, and not very reliable
[notice] The modifiers ('redirect=example1.org', 'redirect=example2.org') should be after all the mechanisms
[fatal] The 'redirect' modifier is present more than once (2 times)
[notice] The 'include=example3.org' modifier is unknown
Please note that every item in the array returned by the validate
method is an instance of the SPFLib\Semantic\Issue
class.
You can offer me a monthly coffee or a one-time coffee 😉