2024-06-04 14:01:00 +02:00

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);
}
}