157 regels
5.3 KiB
PHP
157 regels
5.3 KiB
PHP
|
<?php
|
||
|
|
||
|
/**
|
||
|
* For the full copyright and license information, please view the LICENSE
|
||
|
* file that was distributed with this source code.
|
||
|
*
|
||
|
* https://www.d3data.de
|
||
|
*
|
||
|
* @copyright (C) D3 Data Development (Inh. Thomas Dartsch)
|
||
|
* @author D3 Data Development - Daniel Seifert <info@shopmodule.com>
|
||
|
* @link https://www.oxidmodule.com
|
||
|
*/
|
||
|
|
||
|
declare(strict_types=1);
|
||
|
|
||
|
namespace D3\MailAuthenticationCheck\Model;
|
||
|
|
||
|
use D3\MailAuthenticationCheck\Enum\DMARCMechanism as Mechanism;
|
||
|
use D3\MailAuthenticationCheck\Mechanism\AbstractMechanism;
|
||
|
use D3\MailAuthenticationCheck\Mechanism\DMARC\DkimAlignment;
|
||
|
use D3\MailAuthenticationCheck\Mechanism\DMARC\Percentage;
|
||
|
use D3\MailAuthenticationCheck\Mechanism\DMARC\ReportingFormat;
|
||
|
use D3\MailAuthenticationCheck\Mechanism\DMARC\ReportingInterval;
|
||
|
use D3\MailAuthenticationCheck\Mechanism\DMARC\SpfAlignment;
|
||
|
use D3\MailAuthenticationCheck\Mechanism\DMARC\ForensicReportOptions;
|
||
|
use D3\MailAuthenticationCheck\Mechanism\DMARC\RejectPolicy;
|
||
|
use D3\MailAuthenticationCheck\Mechanism\DMARC\ReportUriAggregateData;
|
||
|
use D3\MailAuthenticationCheck\Mechanism\DMARC\ReportUriForensicData;
|
||
|
use D3\MailAuthenticationCheck\Mechanism\DMARC\SubRejectPolicy;
|
||
|
use LogicException;
|
||
|
|
||
|
class DMARCRecord
|
||
|
{
|
||
|
private string $rawRecord;
|
||
|
|
||
|
public function __construct(string $rawRecord = '')
|
||
|
{
|
||
|
$this->rawRecord = $rawRecord;
|
||
|
}
|
||
|
|
||
|
public function getRawRecord(): string
|
||
|
{
|
||
|
return $this->rawRecord;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @return AbstractMechanism[]
|
||
|
*/
|
||
|
public function getTerms(): iterable
|
||
|
{
|
||
|
$terms = explode(' ', $this->rawRecord);
|
||
|
|
||
|
array_shift($terms); // Remove first part (v=DMARC1)
|
||
|
|
||
|
foreach ($terms as $term) {
|
||
|
if(empty($term)) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
preg_match('`^(?<qualifier>(p|rua|ruf|sp|aspf|adkim|fo|ri|rf|pct))=(?<term>[^;]*);*$`U', $term, $matches);
|
||
|
|
||
|
switch(strtolower($matches['qualifier'])) {
|
||
|
case Mechanism::REJECT_POLICY:
|
||
|
yield new RejectPolicy($term, $matches['qualifier'], $matches['term']);
|
||
|
break;
|
||
|
case Mechanism::SUB_REJECT_POLICY:
|
||
|
yield new SubRejectPolicy($term, $matches['qualifier'], $matches['term']);
|
||
|
break;
|
||
|
case Mechanism::REPORT_URI_AGGREGATE:
|
||
|
yield new ReportUriAggregateData($term, $matches['qualifier'], $matches['term']);
|
||
|
break;
|
||
|
case Mechanism::REPORT_URI_FORENSIC:
|
||
|
yield new ReportUriForensicData($term, $matches['qualifier'], $matches['term']);
|
||
|
break;
|
||
|
case Mechanism::SPF_ALIGNMENT:
|
||
|
yield new SpfAlignment($term, $matches['qualifier'], $matches['term']);
|
||
|
break;
|
||
|
case Mechanism::DKIM_ALIGNMENT:
|
||
|
yield new DkimAlignment($term, $matches['qualifier'], $matches['term']);
|
||
|
break;
|
||
|
case Mechanism::REPORTING_INTERVAL:
|
||
|
yield new ReportingInterval($term, $matches['qualifier'], $matches['term']);
|
||
|
break;
|
||
|
case Mechanism::REPORTING_FORMAT:
|
||
|
yield new ReportingFormat($term, $matches['qualifier'], $matches['term']);
|
||
|
break;
|
||
|
case Mechanism::FORENSIC_REPORT_OPTIONS:
|
||
|
yield new ForensicReportOptions($term, $matches['qualifier'], $matches['term']);
|
||
|
break;
|
||
|
case Mechanism::PERCENTAGE:
|
||
|
yield new Percentage($term, $matches['qualifier'], $matches['term']);
|
||
|
break;
|
||
|
default:
|
||
|
throw new LogicException('Unknown mechanism '.$matches['qualifier']);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public function isValid(): bool
|
||
|
{
|
||
|
return (bool) preg_match(
|
||
|
'/(^v=DMARC1;)?( +(p=(none|quarantine|reject);|rua=mailto:([^;]*);|ruf=mailto:([^;]*);|sp=(none|quarantine|reject);|aspf=s;|adkim=s;|fo=((?!:)(:?\w+)+);))/i',
|
||
|
$this->rawRecord
|
||
|
);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @return RejectPolicy
|
||
|
* @throws LogicException
|
||
|
*/
|
||
|
public function getRejectPolicy(): RejectPolicy
|
||
|
{
|
||
|
/** @var RejectPolicy $mechanism */
|
||
|
$mechanism = $this->getTerm(RejectPolicy::class);
|
||
|
return $mechanism;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @return ReportUriAggregateData
|
||
|
* @throws LogicException
|
||
|
*/
|
||
|
public function getReportUriAggregate(): ReportUriAggregateData
|
||
|
{
|
||
|
/** @var ReportUriAggregateData $mechanism */
|
||
|
$mechanism = $this->getTerm(ReportUriAggregateData::class);
|
||
|
return $mechanism;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @return ReportUriForensicData
|
||
|
* @throws LogicException
|
||
|
*/
|
||
|
public function getReportUriForensic(): ReportUriForensicData
|
||
|
{
|
||
|
/** @var ReportUriForensicData $mechanism */
|
||
|
$mechanism = $this->getTerm(ReportUriForensicData::class);
|
||
|
return $mechanism;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @param string $className
|
||
|
*
|
||
|
* @return AbstractMechanism
|
||
|
* @throws LogicException
|
||
|
*/
|
||
|
public function getTerm(string $className): AbstractMechanism
|
||
|
{
|
||
|
foreach ($this->getTerms() as $term) {
|
||
|
if ( $term instanceof $className ) {
|
||
|
return $term;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
throw new LogicException('undefined term '.$className);
|
||
|
}
|
||
|
}
|