diff --git a/mailpoet/lib/DI/ContainerConfigurator.php b/mailpoet/lib/DI/ContainerConfigurator.php index 11b0ed0371..fb1d0e4aa2 100644 --- a/mailpoet/lib/DI/ContainerConfigurator.php +++ b/mailpoet/lib/DI/ContainerConfigurator.php @@ -377,6 +377,7 @@ class ContainerConfigurator implements IContainerConfigurator { $container->autowire(\MailPoet\Services\Bridge::class)->setPublic(true); $container->autowire(\MailPoet\Services\AuthorizedEmailsController::class)->setPublic(true); $container->autowire(\MailPoet\Services\CongratulatoryMssEmailController::class)->setPublic(true); + $container->autowire(\MailPoet\Services\AuthorizedSenderDomainController::class)->setPublic(true); // Tasks $container->autowire(\MailPoet\Tasks\State::class); // Settings @@ -464,6 +465,7 @@ class ContainerConfigurator implements IContainerConfigurator { $container->register(\MailPoet\Util\CdnAssetUrl::class) ->setPublic(true) ->setFactory([__CLASS__, 'getCdnAssetsUrl']); + $container->autowire(\MailPoet\Util\DmarcPolicyChecker::class)->setPublic(true); $container->autowire(\MailPoet\Newsletter\Scheduler\Scheduler::class)->setPublic(true); // Validator $container->autowire(Validator::class)->setPublic(true); diff --git a/mailpoet/lib/Services/AuthorizedSenderDomainController.php b/mailpoet/lib/Services/AuthorizedSenderDomainController.php new file mode 100644 index 0000000000..b1af729c96 --- /dev/null +++ b/mailpoet/lib/Services/AuthorizedSenderDomainController.php @@ -0,0 +1,68 @@ +bridge = $bridge; + $this->dmarcPolicyChecker = $dmarcPolicyChecker; + } + + /** + * Get all Authorized Sender Domains + * + * Note: This includes both verified and unverified domains + */ + public function getAllSenderDomains(): array { + $records = $this->bridge->getAuthorizedSenderDomains(); + $domains = array_keys($records); + return $domains; + } + + /** + * Get all Verified Sender Domains + */ + public function getVerifiedSenderDomains(): array { + $records = $this->bridge->getAuthorizedSenderDomains(); + $verifiedDomains = []; + + foreach ($records as $key => $value) { + [$domainKey1, $domainKey2, $secretRecord] = $value; + if ( + $domainKey1['status'] === self::DOMAIN_VERIFICATION_STATUS_VALID && + $domainKey2['status'] === self::DOMAIN_VERIFICATION_STATUS_VALID && + $secretRecord['status'] === self::DOMAIN_VERIFICATION_STATUS_VALID + ) { + $verifiedDomains[] = $key; + } + } + + return $verifiedDomains; + } + + /** + * Check Domain DMARC Policy + * + * returns `true` if domain has Retricted policy e.g policy === reject or quarantine + * otherwise returns `false` + */ + public function isDomainDmarcRetricted(string $domain): bool { + $result = $this->dmarcPolicyChecker->getDomainDmarcPolicy($domain); + return $result !== DmarcPolicyChecker::POLICY_NONE; + } +} diff --git a/mailpoet/lib/Util/DmarcPolicyChecker.php b/mailpoet/lib/Util/DmarcPolicyChecker.php index 2b49ccfdee..06282ac097 100644 --- a/mailpoet/lib/Util/DmarcPolicyChecker.php +++ b/mailpoet/lib/Util/DmarcPolicyChecker.php @@ -47,7 +47,7 @@ class DmarcPolicyChecker { $item = explode('=', $value); $dKey = $item[0] ?? ''; $dValue = $item[1] ?? ''; - $dmarcInfo[trim($dKey)] = trim($dValue); + $dmarcInfo[strtolower(trim($dKey))] = strtolower(trim($dValue)); } // policy can either be reject or quarantine or none diff --git a/mailpoet/tests/integration/Services/AuthorizedSenderDomainControllerTest.php b/mailpoet/tests/integration/Services/AuthorizedSenderDomainControllerTest.php new file mode 100644 index 0000000000..a9f3f3de04 --- /dev/null +++ b/mailpoet/tests/integration/Services/AuthorizedSenderDomainControllerTest.php @@ -0,0 +1,72 @@ +markTestSkipped("Skipping, 'WP_TEST_MAILER_MAILPOET_API' not set."); + } + + $this->bridge = new Bridge(); + $this->bridge->api = new API($apiKey, new WPFunctions()); + + $this->settings = SettingsController::getInstance(); + $this->settings->set( + Mailer::MAILER_CONFIG_SETTING_NAME, + [ + 'method' => 'MailPoet', + 'mailpoet_api_key' => $apiKey, + ] + ); + } + + public function testItFetchSenderDomains() { + $domains = ['mailpoet.com', 'GOOD', 'testdomain.com']; + + $controller = $this->getController(); + $allDomains = $controller->getAllSenderDomains(); + expect($allDomains)->same($domains); + } + + public function testItReturnsVerifiedSenderDomains() { + $controller = $this->getController(); + $verifiedDomains = $controller->getVerifiedSenderDomains(); + expect($verifiedDomains)->same(['mailpoet.com']); // only this is Verified for now + } + + public function testItReturnsTrueWhenDmarcIsEnabled() { + $controller = $this->getController(); + $isRetricted = $controller->isDomainDmarcRetricted('mailpoet.com'); + expect($isRetricted)->same(true); + } + + public function testItReturnsFalseWhenDmarcIsNotEnabled() { + $controller = $this->getController(); + $isRetricted = $controller->isDomainDmarcRetricted('example.com'); + expect($isRetricted)->same(false); + } + + private function getController(): AuthorizedSenderDomainController { + $dmarcPolicyChecker = $this->diContainer->get(DmarcPolicyChecker::class); + return new AuthorizedSenderDomainController($this->bridge, $dmarcPolicyChecker); + } +}