add DMARC check

# Conflicts:
#	Application/Controller/Admin/SpfChecker.php
#	Application/views/admin/tpl/mailTester.tpl
#	Application/views/admin/tpl/mailconfigcheck.tpl
#	Application/views/admin/tpl/mailinfopage.tpl
#	Application/views/admin/tpl/smtpCheck.tpl
#	Application/views/admin/tpl/spfCheck.tpl
This commit is contained in:
Daniel Seifert 2024-06-04 14:20:20 +02:00
parent c414117143
commit 860de39a79
6 changed files with 181 additions and 12 deletions

View File

@ -16,6 +16,10 @@ declare(strict_types=1);
namespace D3\MailConfigChecker\Application\Controller\Admin; namespace D3\MailConfigChecker\Application\Controller\Admin;
use Assert\InvalidArgumentException; use Assert\InvalidArgumentException;
use D3\MailAuthenticationCheck\DMARCCheck;
use D3\MailAuthenticationCheck\Model\DMARCResult;
use D3\MailConfigChecker\Application\Model\Constants;
use D3\MailConfigChecker\Application\Model\DmarcResult as OxDmarcResult;
use D3\MailConfigChecker\Application\Model\SpfResult; use D3\MailConfigChecker\Application\Model\SpfResult;
use Mika56\SPFCheck\DNS\DNSRecordGetter; use Mika56\SPFCheck\DNS\DNSRecordGetter;
use Mika56\SPFCheck\Model\Query; use Mika56\SPFCheck\Model\Query;
@ -32,6 +36,7 @@ class SpfChecker extends AdminDetailsController
public function render() public function render()
{ {
$this->checkSpf(); $this->checkSpf();
$this->checkDmarc();
return parent::render(); return parent::render();
} }
@ -46,10 +51,24 @@ class SpfChecker extends AdminDetailsController
} }
); );
$this->addTplParam('result', $result); $this->addTplParam('spf_result', $result);
} }
protected function getMailDomains() protected function checkDmarc()
{
$result = [];
$mailDomains = $this->getMailDomains();
array_walk(
$mailDomains,
function ($domain) use (&$result) {
$this->checkDmarcByDomain($domain, $result);
}
);
$this->addTplParam('dmarc_result', $result);
}
protected function getMailDomains(): array
{ {
/** @var Shop $shop */ /** @var Shop $shop */
$shop = Registry::getConfig()->getActiveShop(); $shop = Registry::getConfig()->getActiveShop();
@ -119,4 +138,41 @@ class SpfChecker extends AdminDetailsController
return 'danger'; return 'danger';
} }
} }
public function checkDmarcByDomain($domain, &$summarize)
{
try {
$check = new DMARCCheck(new DNSRecordGetter());
$query = new Query('', $domain);
$record = $check->getResult($query)->getRecord();
switch ( $record->getRejectPolicy()->getValue() ) {
case DMARCResult::REJECT_QUARANTINE:
case DMARCResult::REJECT_REJECT:
$status = OxDmarcResult::SET;
break;
case DMARCResult::REJECT_NONE:
$status = OxDmarcResult::MISSING;
break;
default:
$status = OxDmarcResult::ERROR;
}
$summarize[$domain] = oxNew( OxDmarcResult::class, $status, $record->getRawRecord());
} catch (\LogicException) {
$summarize[$domain] = oxNew( OxDmarcResult::class, OxDmarcResult::MISSING, '');
}
}
public function getDmarcStatusColor(OxDmarcResult $result)
{
switch ($result->getStatus()) {
case SpfResult::SET:
return 'success';
case SpfResult::ERROR:
return 'warning';
default:
return 'danger';
}
}
} }

View File

@ -0,0 +1,42 @@
<?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\MailConfigChecker\Application\Model;
class DmarcResult
{
public const SET = 'set';
public const MISSING = 'missing';
public const ERROR = 'error';
protected $status;
protected $record;
public function __construct(string $status, ?string $record = null)
{
$this->status = $status;
$this->record = $record;
}
public function getStatus()
{
return $this->status;
}
public function getRecord()
{
return $this->record;
}
}

View File

@ -17,7 +17,7 @@ namespace D3\MailConfigChecker\Application\Model;
class SpfResult class SpfResult
{ {
public const SET = 'set'; public const SET = 'set';
public const MISSING = 'missing'; public const MISSING = 'missing';
public const ERROR = 'error'; public const ERROR = 'error';

View File

@ -10,15 +10,16 @@
</form> </form>
<div class="row"> <div class="row">
<div class="col-12 col-md-10 col-lg-8 mb-4"> <div class="col-12 mb-4">
<h4>[{oxmultilang ident="D3_MAILCHECKER_SPFRESULT_HL"}]</h4>
[{oxmultilang ident="D3_MAILCHECKER_SPFRESULT_DESC"}] [{oxmultilang ident="D3_MAILCHECKER_SPFRESULT_DESC"}]
</div> </div>
</div> </div>
<div class="row"> <div class="row">
<div class="col-12 col-md-10 col-lg-8 mb-4"> <div class="col-12 mb-4">
<div class="row"> <div class="row">
[{foreach from=$result key="domain" item="spf"}] [{foreach from=$spf_result key="domain" item="spf"}]
<div class="col-12 col-md-6 col-lg-4"> <div class="col-12 col-md-6 col-lg-3">
<div class="card mb-3"> <div class="card mb-3">
<div class="card-header text-white bg-[{$oView->getSpfStatusColor($spf)}]"> <div class="card-header text-white bg-[{$oView->getSpfStatusColor($spf)}]">
[{$domain}] [{$domain}]
@ -27,8 +28,8 @@
<p>[{oxmultilang ident="D3_MAILCHECKER_SPFRESULT_"|cat:$spf->getStatus()|upper}]</p> <p>[{oxmultilang ident="D3_MAILCHECKER_SPFRESULT_"|cat:$spf->getStatus()|upper}]</p>
[{if $spf->getRecord()}] [{if $spf->getRecord()}]
<p> <p>
<label for="[{$domain}]_record">Eintrag:</label> <label for="[{$domain}]_record">[{oxmultilang ident="D3_MAILCHECKER_RECORD" suffix="COLON"}]</label>
<input type="text" id="[{$domain}]_record" value="[{$spf->getRecord()}]" readonly disabled> <input type="text" id="[{$domain}]_record" value="[{$spf->getRecord()}]" style="width: 50%;" readonly disabled>
</p> </p>
[{/if}] [{/if}]
@ -45,7 +46,6 @@
<a href="https://mxtoolbox.com/SPFRecordGenerator.aspx?domain=[{$domain}]&prefill=true"> <a href="https://mxtoolbox.com/SPFRecordGenerator.aspx?domain=[{$domain}]&prefill=true">
[{oxmultilang ident="D3_MAILCHECKER_SPFRESULT_LINK_GENERATOR"}] [{oxmultilang ident="D3_MAILCHECKER_SPFRESULT_LINK_GENERATOR"}]
</a> </a>
</li> </li>
[{/if}] [{/if}]
<li> <li>
@ -62,6 +62,51 @@
</div> </div>
</div> </div>
<div class="row">
<div class="col-12 mb-4">
<h4>[{oxmultilang ident="D3_MAILCHECKER_DMARCRESULT_HL"}]</h4>
[{oxmultilang ident="D3_MAILCHECKER_DMARCRESULT_DESC"}]
</div>
</div>
<div class="row">
<div class="col-12 mb-4">
<div class="row">
[{foreach from=$dmarc_result key="domain" item="dmarc"}]
<div class="col-12 col-md-6 col-lg-3">
<div class="card mb-3">
<div class="card-header text-white bg-[{$oView->getDmarcStatusColor($dmarc)}]">
[{$domain}]
</div>
<div class="card-body">
<p>[{oxmultilang ident="D3_MAILCHECKER_DMARCRESULT_"|cat:$dmarc->getStatus()|upper}]</p>
[{if $dmarc->getRecord()}]
<p>
<label for="[{$domain}]_record">[{oxmultilang ident="D3_MAILCHECKER_RECORD" suffix="COLON"}]</label>
<input type="text" id="[{$domain}]_record" value="[{$dmarc->getRecord()}]" style="width: 50%;" readonly disabled>
</p>
[{/if}]
<h5>[{oxmultilang ident="D3_MAILCHECKER_DMARCRESULT_LINKS"}]</h5>
<ul>
<li>
<a href="https://mxtoolbox.com/SuperTool.aspx?action=dmarc%3a[{$domain}]&run=toolpage">
[{oxmultilang ident="D3_MAILCHECKER_DMARCRESULT_LINK_ANALYSIS"}]
</a>
</li>
<li>
<a href="https://mxtoolbox.com/DMARCRecordGenerator.aspx?domain=[{$domain}]&prefill=true">
[{oxmultilang ident="D3_MAILCHECKER_DMARCRESULT_LINK_GENERATOR"}]
</a>
</li>
</ul>
</div>
</div>
</div>
[{/foreach}]
</div>
</div>
</div>
[{include file="bottomnaviitem.tpl"}] [{include file="bottomnaviitem.tpl"}]
[{include file="bottomitem.tpl"}] [{include file="bottomitem.tpl"}]

View File

@ -6,7 +6,7 @@ return [
'D3_TAB_MAILCHECKER_MODULEDESCRIPTION' => 'Beschreibung', 'D3_TAB_MAILCHECKER_MODULEDESCRIPTION' => 'Beschreibung',
'D3_TAB_MAILCHECKER_CONFIGCHECK' => 'Konfigurationsprüfung', 'D3_TAB_MAILCHECKER_CONFIGCHECK' => 'Konfigurationsprüfung',
'D3_TAB_MAILCHECKER_SMTPCHECK' => 'SMTP Check', 'D3_TAB_MAILCHECKER_SMTPCHECK' => 'SMTP Check',
'D3_TAB_MAILCHECKER_SPFCHECK' => 'SPF Check', 'D3_TAB_MAILCHECKER_SPFCHECK' => 'Authentisierung Check',
'D3_TAB_MAILCHECKER_TESTMAIL' => 'Testmail', 'D3_TAB_MAILCHECKER_TESTMAIL' => 'Testmail',
'D3_MAILCHECKER_INFO_1' => 'Dieses Modul kann Ihnen helfen, um Schwierigkeiten beim Versand von Mails oder bei nicht zugestellten Mails zu identifizieren. Gehen Sie bitte die folgenden Tabs durch. Nötige Nacharbeiten werden Ihnen dort angezeigt.', 'D3_MAILCHECKER_INFO_1' => 'Dieses Modul kann Ihnen helfen, um Schwierigkeiten beim Versand von Mails oder bei nicht zugestellten Mails zu identifizieren. Gehen Sie bitte die folgenden Tabs durch. Nötige Nacharbeiten werden Ihnen dort angezeigt.',
@ -41,6 +41,9 @@ return [
'D3_MAILCHECKER_SMTPCHECK_NOTRANSMIT' => 'Datenübertragung nicht erfolgreich', 'D3_MAILCHECKER_SMTPCHECK_NOTRANSMIT' => 'Datenübertragung nicht erfolgreich',
'D3_MAILCHECKER_SMTPCHECK_SUCCESS' => 'Die SMTP-Kommunikation wurde erfolgreich abgeschlossen.', 'D3_MAILCHECKER_SMTPCHECK_SUCCESS' => 'Die SMTP-Kommunikation wurde erfolgreich abgeschlossen.',
'D3_MAILCHECKER_RECORD' => 'Eintrag',
'D3_MAILCHECKER_SPFRESULT_HL' => 'SPF (Herkunftsprüfung)',
'D3_MAILCHECKER_SPFRESULT_DESC' => 'Mit dem Sender Policy Framework (SPF) definiert der Domaininhaber, welcher Server E-Mails mit dem Domainabsender versenden darf. Diese Angabe wird vom Empfangsserver geprüft. Fehlt der SPF-Eintrag, werden E-Mails üblicherweise als Spam klassifiziert.', 'D3_MAILCHECKER_SPFRESULT_DESC' => 'Mit dem Sender Policy Framework (SPF) definiert der Domaininhaber, welcher Server E-Mails mit dem Domainabsender versenden darf. Diese Angabe wird vom Empfangsserver geprüft. Fehlt der SPF-Eintrag, werden E-Mails üblicherweise als Spam klassifiziert.',
'D3_MAILCHECKER_SPFRESULT_SET' => 'Es ist ein SPF-Eintrag gesetzt', 'D3_MAILCHECKER_SPFRESULT_SET' => 'Es ist ein SPF-Eintrag gesetzt',
'D3_MAILCHECKER_SPFRESULT_MISSING' => 'Es ist kein SPF-Eintrag gesetzt, dieser sollte dringend nachgetragen werden', 'D3_MAILCHECKER_SPFRESULT_MISSING' => 'Es ist kein SPF-Eintrag gesetzt, dieser sollte dringend nachgetragen werden',
@ -50,6 +53,15 @@ return [
'D3_MAILCHECKER_SPFRESULT_LINK_GENERATOR' => 'SPF Generator', 'D3_MAILCHECKER_SPFRESULT_LINK_GENERATOR' => 'SPF Generator',
'D3_MAILCHECKER_SPFRESULT_LINK_BLACKLISTCHECK' => 'Blacklist Check', 'D3_MAILCHECKER_SPFRESULT_LINK_BLACKLISTCHECK' => 'Blacklist Check',
'D3_MAILCHECKER_DMARCRESULT_HL' => 'DMARC (Ablehnungsrichtlinien und Berichterstattung)',
'D3_MAILCHECKER_DMARCRESULT_DESC' => 'Der DMARC-Eintrag definiert, wie mit Mails umgegangen wird, bei denen die Authentisierungsprüfungen fehlgeschlagen sind. Dort können auch Mailadressen für Reporte angegeben werden.',
'D3_MAILCHECKER_DMARCRESULT_SET' => 'Es ist ein DMARC-Eintrag gesetzt, das Verhalten ist nicht auf "ignorieren" gestellt.',
'D3_MAILCHECKER_DMARCRESULT_MISSING' => 'Es ist kein DMARC-Eintrag gesetzt oder mit "ignorieren" konfiguriert. Dies sollte dringend geändert werden.',
'D3_MAILCHECKER_DMARCRESULT_ERROR' => 'Der DMARC-Eintrag kann nicht geprüft werden',
'D3_MAILCHECKER_DMARCRESULT_LINKS' => 'weiterführende Links',
'D3_MAILCHECKER_DMARCRESULT_LINK_ANALYSIS' => 'DMARC Analyse',
'D3_MAILCHECKER_DMARCRESULT_LINK_GENERATOR' => 'DMARC Generator',
'D3_MAILCHECKER_TESTMAIL_DESC' => 'Die Testmail wird auf identischem Weg geschickt, den auch alle regulären Mails aus dem Shop nehmen (z.B. Bestellbestätigungen, ...) und kann z.B. zur Headeranalyse dienen.', 'D3_MAILCHECKER_TESTMAIL_DESC' => 'Die Testmail wird auf identischem Weg geschickt, den auch alle regulären Mails aus dem Shop nehmen (z.B. Bestellbestätigungen, ...) und kann z.B. zur Headeranalyse dienen.',
'D3_MAILCHECKER_TESTMAIL_HEADERANALYSIS' => 'Email Header Analyzer', 'D3_MAILCHECKER_TESTMAIL_HEADERANALYSIS' => 'Email Header Analyzer',
'D3_MAILCHECKER_TESTMAIL_SUBJECT' => 'Betreff', 'D3_MAILCHECKER_TESTMAIL_SUBJECT' => 'Betreff',

View File

@ -6,7 +6,7 @@ return [
"D3_TAB_MAILCHECKER_MODULEDESCRIPTION" => "Description", "D3_TAB_MAILCHECKER_MODULEDESCRIPTION" => "Description",
"D3_TAB_MAILCHECKER_CONFIGCHECK" => "Configuration check", "D3_TAB_MAILCHECKER_CONFIGCHECK" => "Configuration check",
"D3_TAB_MAILCHECKER_SMTPCHECK" => "SMTP check", "D3_TAB_MAILCHECKER_SMTPCHECK" => "SMTP check",
"D3_TAB_MAILCHECKER_SPFCHECK" => "SPF check", "D3_TAB_MAILCHECKER_SPFCHECK" => "Authentication check",
"D3_TAB_MAILCHECKER_TESTMAIL" => "Test email", "D3_TAB_MAILCHECKER_TESTMAIL" => "Test email",
"D3_MAILCHECKER_ASSERTIONS_FAILED" => "The following %d checks failed:", "D3_MAILCHECKER_ASSERTIONS_FAILED" => "The following %d checks failed:",
"D3_MAILCHECKER_ASSERTIONS_NOTSET" => "is not (correctly) set", "D3_MAILCHECKER_ASSERTIONS_NOTSET" => "is not (correctly) set",
@ -34,6 +34,10 @@ return [
"D3_MAILCHECKER_SMTPCHECK_TRANSMIT" => "Data transfer", "D3_MAILCHECKER_SMTPCHECK_TRANSMIT" => "Data transfer",
"D3_MAILCHECKER_SMTPCHECK_NOTRANSMIT" => "Data transfer not successful", "D3_MAILCHECKER_SMTPCHECK_NOTRANSMIT" => "Data transfer not successful",
"D3_MAILCHECKER_SMTPCHECK_SUCCESS" => "SMTP communication was completed successfully.", "D3_MAILCHECKER_SMTPCHECK_SUCCESS" => "SMTP communication was completed successfully.",
'D3_MAILCHECKER_RECORD' => 'Record',
'D3_MAILCHECKER_SPFRESULT_HL' => 'SPF (Origin verification)',
"D3_MAILCHECKER_SPFRESULT_DESC" => "With the Sender Policy Framework (SPF), the domain owner defines which server is allowed to send emails with the domain sender. This information is checked by the receiving server. If the SPF entry is missing, emails are usually sent as ", "D3_MAILCHECKER_SPFRESULT_DESC" => "With the Sender Policy Framework (SPF), the domain owner defines which server is allowed to send emails with the domain sender. This information is checked by the receiving server. If the SPF entry is missing, emails are usually sent as ",
"D3_MAILCHECKER_SPFRESULT_SET" => "An SPF entry is set", "D3_MAILCHECKER_SPFRESULT_SET" => "An SPF entry is set",
"D3_MAILCHECKER_SPFRESULT_MISSING" => "There is no SPF entry set, this should be added urgently", "D3_MAILCHECKER_SPFRESULT_MISSING" => "There is no SPF entry set, this should be added urgently",
@ -42,6 +46,16 @@ return [
"D3_MAILCHECKER_SPFRESULT_LINK_ANALYSIS" => "SPF analysis", "D3_MAILCHECKER_SPFRESULT_LINK_ANALYSIS" => "SPF analysis",
"D3_MAILCHECKER_SPFRESULT_LINK_GENERATOR" => "SPF generator", "D3_MAILCHECKER_SPFRESULT_LINK_GENERATOR" => "SPF generator",
"D3_MAILCHECKER_SPFRESULT_LINK_BLACKLISTCHECK" => "Blacklist check", "D3_MAILCHECKER_SPFRESULT_LINK_BLACKLISTCHECK" => "Blacklist check",
'D3_MAILCHECKER_DMARCRESULT_HL' => 'DMARC (Reject policy and reporting)',
'D3_MAILCHECKER_DMARCRESULT_DESC' => 'The DMARC entry defines how to deal with mails for which the authentication checks have failed. Mail addresses for reports can also be specified there.',
'D3_MAILCHECKER_DMARCRESULT_SET' => 'A DMARC entry is set, the behaviour is not set to ignore.',
'D3_MAILCHECKER_DMARCRESULT_MISSING' => 'No DMARC entry is set or configured with ignore. This should be changed urgently.',
'D3_MAILCHECKER_DMARCRESULT_ERROR' => 'The DMARC record cannot be checked',
'D3_MAILCHECKER_DMARCRESULT_LINKS' => 'Related Links',
'D3_MAILCHECKER_DMARCRESULT_LINK_ANALYSIS' => 'DMARC analysis',
'D3_MAILCHECKER_DMARCRESULT_LINK_GENERATOR' => 'DMARC generator',
"D3_MAILCHECKER_TESTMAIL_DESC" => "The test email is sent in the same way as all regular emails from the shop (e.g..B. order confirmations, ...) and can ", "D3_MAILCHECKER_TESTMAIL_DESC" => "The test email is sent in the same way as all regular emails from the shop (e.g..B. order confirmations, ...) and can ",
"D3_MAILCHECKER_TESTMAIL_HEADERANALYSIS" => "Email Header Analyzer", "D3_MAILCHECKER_TESTMAIL_HEADERANALYSIS" => "Email Header Analyzer",
"D3_MAILCHECKER_TESTMAIL_SUBJECT" => "Regarding", "D3_MAILCHECKER_TESTMAIL_SUBJECT" => "Regarding",