From 860de39a7903d5e38a16e313be8e084e8209b800 Mon Sep 17 00:00:00 2001 From: Daniel Seifert Date: Tue, 4 Jun 2024 14:20:20 +0200 Subject: [PATCH 1/4] 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 --- Application/Controller/Admin/SpfChecker.php | 60 ++++++++++++++++++++- Application/Model/DmarcResult.php | 42 +++++++++++++++ Application/Model/SpfResult.php | 2 +- Application/views/admin/tpl/spfCheck.tpl | 59 +++++++++++++++++--- Application/views/de/translations.php | 14 ++++- Application/views/en/translations.php | 16 +++++- 6 files changed, 181 insertions(+), 12 deletions(-) create mode 100644 Application/Model/DmarcResult.php diff --git a/Application/Controller/Admin/SpfChecker.php b/Application/Controller/Admin/SpfChecker.php index 798ac38..a87534f 100644 --- a/Application/Controller/Admin/SpfChecker.php +++ b/Application/Controller/Admin/SpfChecker.php @@ -16,6 +16,10 @@ declare(strict_types=1); namespace D3\MailConfigChecker\Application\Controller\Admin; 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 Mika56\SPFCheck\DNS\DNSRecordGetter; use Mika56\SPFCheck\Model\Query; @@ -32,6 +36,7 @@ class SpfChecker extends AdminDetailsController public function render() { $this->checkSpf(); + $this->checkDmarc(); 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 */ $shop = Registry::getConfig()->getActiveShop(); @@ -119,4 +138,41 @@ class SpfChecker extends AdminDetailsController 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'; + } + } } diff --git a/Application/Model/DmarcResult.php b/Application/Model/DmarcResult.php new file mode 100644 index 0000000..5d6e0a4 --- /dev/null +++ b/Application/Model/DmarcResult.php @@ -0,0 +1,42 @@ + + * @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; + } +} diff --git a/Application/Model/SpfResult.php b/Application/Model/SpfResult.php index 6cd9b8d..e8e1cfe 100644 --- a/Application/Model/SpfResult.php +++ b/Application/Model/SpfResult.php @@ -17,7 +17,7 @@ namespace D3\MailConfigChecker\Application\Model; class SpfResult { - public const SET = 'set'; + public const SET = 'set'; public const MISSING = 'missing'; public const ERROR = 'error'; diff --git a/Application/views/admin/tpl/spfCheck.tpl b/Application/views/admin/tpl/spfCheck.tpl index 9301fd4..3cca203 100644 --- a/Application/views/admin/tpl/spfCheck.tpl +++ b/Application/views/admin/tpl/spfCheck.tpl @@ -10,15 +10,16 @@
-
+
+

[{oxmultilang ident="D3_MAILCHECKER_SPFRESULT_HL"}]

[{oxmultilang ident="D3_MAILCHECKER_SPFRESULT_DESC"}]
-
+
- [{foreach from=$result key="domain" item="spf"}] -
+ [{foreach from=$spf_result key="domain" item="spf"}] +
[{$domain}] @@ -27,8 +28,8 @@

[{oxmultilang ident="D3_MAILCHECKER_SPFRESULT_"|cat:$spf->getStatus()|upper}]

[{if $spf->getRecord()}]

- - + +

[{/if}] @@ -45,7 +46,6 @@ [{oxmultilang ident="D3_MAILCHECKER_SPFRESULT_LINK_GENERATOR"}] - [{/if}]
  • @@ -62,6 +62,51 @@
  • +
    +
    +

    [{oxmultilang ident="D3_MAILCHECKER_DMARCRESULT_HL"}]

    + [{oxmultilang ident="D3_MAILCHECKER_DMARCRESULT_DESC"}] +
    +
    +
    +
    +
    + [{foreach from=$dmarc_result key="domain" item="dmarc"}] +
    +
    +
    + [{$domain}] +
    +
    +

    [{oxmultilang ident="D3_MAILCHECKER_DMARCRESULT_"|cat:$dmarc->getStatus()|upper}]

    + [{if $dmarc->getRecord()}] +

    + + +

    + [{/if}] + +
    [{oxmultilang ident="D3_MAILCHECKER_DMARCRESULT_LINKS"}]
    + +
    +
    +
    + [{/foreach}] +
    +
    +
    + [{include file="bottomnaviitem.tpl"}] [{include file="bottomitem.tpl"}] diff --git a/Application/views/de/translations.php b/Application/views/de/translations.php index 68b220c..b4e115d 100644 --- a/Application/views/de/translations.php +++ b/Application/views/de/translations.php @@ -6,7 +6,7 @@ return [ 'D3_TAB_MAILCHECKER_MODULEDESCRIPTION' => 'Beschreibung', 'D3_TAB_MAILCHECKER_CONFIGCHECK' => 'Konfigurationsprüfung', 'D3_TAB_MAILCHECKER_SMTPCHECK' => 'SMTP Check', - 'D3_TAB_MAILCHECKER_SPFCHECK' => 'SPF Check', + 'D3_TAB_MAILCHECKER_SPFCHECK' => 'Authentisierung Check', '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.', @@ -41,6 +41,9 @@ return [ 'D3_MAILCHECKER_SMTPCHECK_NOTRANSMIT' => 'Datenübertragung nicht erfolgreich', '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_SET' => 'Es ist ein SPF-Eintrag gesetzt', '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_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_HEADERANALYSIS' => 'Email Header Analyzer', 'D3_MAILCHECKER_TESTMAIL_SUBJECT' => 'Betreff', diff --git a/Application/views/en/translations.php b/Application/views/en/translations.php index d5ec530..88cb8c6 100644 --- a/Application/views/en/translations.php +++ b/Application/views/en/translations.php @@ -6,7 +6,7 @@ return [ "D3_TAB_MAILCHECKER_MODULEDESCRIPTION" => "Description", "D3_TAB_MAILCHECKER_CONFIGCHECK" => "Configuration 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_MAILCHECKER_ASSERTIONS_FAILED" => "The following %d checks failed:", "D3_MAILCHECKER_ASSERTIONS_NOTSET" => "is not (correctly) set", @@ -34,6 +34,10 @@ return [ "D3_MAILCHECKER_SMTPCHECK_TRANSMIT" => "Data transfer", "D3_MAILCHECKER_SMTPCHECK_NOTRANSMIT" => "Data transfer not successful", "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_SET" => "An SPF entry is set", "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_GENERATOR" => "SPF generator", "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_HEADERANALYSIS" => "Email Header Analyzer", "D3_MAILCHECKER_TESTMAIL_SUBJECT" => "Regarding", From a119ae868734e5b91d15a2db7479a5168db4780a Mon Sep 17 00:00:00 2001 From: Daniel Seifert Date: Tue, 4 Jun 2024 16:21:56 +0200 Subject: [PATCH 2/4] add missing DMARC package --- Application/Controller/Admin/SpfChecker.php | 1 - composer.json | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/Application/Controller/Admin/SpfChecker.php b/Application/Controller/Admin/SpfChecker.php index a87534f..81a05fd 100644 --- a/Application/Controller/Admin/SpfChecker.php +++ b/Application/Controller/Admin/SpfChecker.php @@ -18,7 +18,6 @@ namespace D3\MailConfigChecker\Application\Controller\Admin; 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 Mika56\SPFCheck\DNS\DNSRecordGetter; diff --git a/composer.json b/composer.json index 2c11c15..ebb1560 100644 --- a/composer.json +++ b/composer.json @@ -34,6 +34,7 @@ "oxid-esales/oxideshop-ce": "6.10 - 6.14", "pear/net_smtp": "^1.11", "mika56/spfcheck": "^2.1.1", + "d3/mailauthenticationcheck": "^0.1.0", "beberlei/assert": "^3.3" }, "require-dev": { From d3e94b218a81967fd5029c58a02d143e3abb3769 Mon Sep 17 00:00:00 2001 From: Daniel Seifert Date: Wed, 5 Jun 2024 08:33:14 +0200 Subject: [PATCH 3/4] remove unnecessary migration --- migration/README.md | 38 -------------------------------------- migration/migrations.yml | 4 ---- 2 files changed, 42 deletions(-) delete mode 100644 migration/README.md delete mode 100644 migration/migrations.yml diff --git a/migration/README.md b/migration/README.md deleted file mode 100644 index b6a412c..0000000 --- a/migration/README.md +++ /dev/null @@ -1,38 +0,0 @@ -# Arbeiten mit [Doctrine Migrations](https://www.doctrine-project.org/projects/doctrine-migrations/en/3.6/reference/introduction.html) - -Migrations bilden die Veränderung der Datenbankstruktur in programmierter Form ab. Jede Strukturänderung wird in einer einzelnen (jeweils neuen) Migrationsdatei abgelegt, die Teil des Moduls ist. - -Passe die `migrations.yml` an Dein Modul an. - -## Erstellen eines Skeletons für die erste oder zusätzliche Migrationen - -``` -./vendor/bin/oe-eshop-doctrine_migration migrations:generate d3moduleid -``` - -Arbeite die angelegte Datei entsprechend Deinen Anforderungen um. - -## Ausführen der noch nicht ausgeführten Migrations - -Doctrine überwacht selbst, welche Migrationen schon ausgeführt wurden und verhindert damit mehrfache Ausführungen der selben Migration. - -Im OXID-Shop werden Migrations mit folgendem Befehl ausgeführt: - -``` -./vendor/bin/oe-eshop-db_migrate migrations:migrate -``` - -Als Argument kann noch die Suite mitgegeben werden, wenn nur bestimmte Migrations ausgeführt werden sollen. Mögliche Angaben sind: - -- CE - für alle CE-Migrations -- PE - für alle PE-Migrations -- EE - für alle EE-Migrations -- PR - für alle Projekt-Migrations -- ModuleId - für alle Migrations des jeweiligen Moduls -- ohne Angabe - werden die Migrations aller Suiten nacheinander ausgeführt - -## Abweichungen zwischen Doctrine Migrations und dem OXID Migration Wrapper - -In den originalen Doctrine Migrations können keine Suiten angegeben werden. Dafür gibt es die Möglichkeit, die Richtung (up / down) und eine Zielversion anzugeben. - -Bei OXID können Migrations ausschließlich aufwärts (up) und immer fix bis zur aktuellsten Version ausgeführt werden. \ No newline at end of file diff --git a/migration/migrations.yml b/migration/migrations.yml deleted file mode 100644 index ea631eb..0000000 --- a/migration/migrations.yml +++ /dev/null @@ -1,4 +0,0 @@ -name: D3 module name -migrations_namespace: D3\ThisModule\Migrations -table_name: d3migrations_modulename -migrations_directory: data \ No newline at end of file From 5352571623b8cbe4e283fea28d810426c0edc6b5 Mon Sep 17 00:00:00 2001 From: Daniel Seifert Date: Wed, 5 Jun 2024 08:33:37 +0200 Subject: [PATCH 4/4] align version information --- CHANGELOG.md | 8 ++++++-- composer.json | 1 + metadata.php | 2 +- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 30a4754..8d69767 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,9 +4,13 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [Unreleased](https://git.d3data.de/D3Public/MyModule/compare/2.0.0.0...rel_2.x) +## [Unreleased](https://git.d3data.de/D3Public/MyModule/compare/2.1.0.0...rel_2.x) -## [2.0.0.1](https://git.d3data.de/D3Public/MailConfigChecker/releases/tag/2.0.0.1) - 2024-04-11 +## [2.1.0.0](https://git.d3data.de/D3Public/MailConfigChecker/compare/2.0.0.1...2.1.0.0) - 2024-06-05 +### Added +- check for DMARC DNS record + +## [2.0.0.1](https://git.d3data.de/D3Public/MailConfigChecker/compare/2.0.0.0...2.0.0.1) - 2024-04-11 ### Fixed - MailConfigCheck need a valid "from" mailadress to check smtp correctly diff --git a/composer.json b/composer.json index ebb1560..6edb1ad 100644 --- a/composer.json +++ b/composer.json @@ -12,6 +12,7 @@ "SMTP", "phpMailer", "SPF", + "DMARC". "testing" ], "authors": [ diff --git a/metadata.php b/metadata.php index 9b57179..372415f 100644 --- a/metadata.php +++ b/metadata.php @@ -40,7 +40,7 @@ $aModule = [ 'en' => '', ], 'thumbnail' => 'picture.svg', - 'version' => '2.0.0.1', + 'version' => '2.1.0.0', 'author' => 'D³ Data Development (Inh.: Thomas Dartsch)', 'email' => 'support@shopmodule.com', 'url' => 'https://www.oxidmodule.com/',