diff --git a/mailpoet/lib/Util/Notices/SenderDomainAuthenticationNotices.php b/mailpoet/lib/Util/Notices/SenderDomainAuthenticationNotices.php index bf91e09696..4cfa60261a 100644 --- a/mailpoet/lib/Util/Notices/SenderDomainAuthenticationNotices.php +++ b/mailpoet/lib/Util/Notices/SenderDomainAuthenticationNotices.php @@ -10,6 +10,7 @@ use MailPoet\Util\FreeDomains; use MailPoet\Util\Helpers; use MailPoet\Util\License\Features\Subscribers; use MailPoet\WP\Notice; +use MailPoetVendor\Carbon\Carbon; class SenderDomainAuthenticationNotices { @@ -19,6 +20,8 @@ class SenderDomainAuthenticationNotices { const FREE_MAIL_KB_URL = 'https://kb.mailpoet.com/article/259-your-from-address-cannot-be-yahoo-com-gmail-com-outlook-com'; const SPF_DKIM_DMARC_KB_URL = 'https://kb.mailpoet.com/article/295-spf-dkim-dmarc'; + const ENFORCEMENT_START_TIME = '2024-02-01 00:00:00 UTC'; + const INSTALLED_AFTER_NEW_RESTRICTIONS_OPTION = 'installed_after_new_domain_restrictions'; private SettingsController $settingsController; @@ -61,6 +64,11 @@ class SenderDomainAuthenticationNotices { return $this->freeDomains->isEmailOnFreeDomain($this->getDefaultFromDomain()); } + // TODO: Remove after the enforcement date has passed + public function isEnforcementOfNewRestrictionsInEffect(): bool { + return Carbon::now() >= Carbon::parse(self::ENFORCEMENT_START_TIME); + } + public function isNewUser(): bool { $installedVersion = $this->settingsController->get('version'); @@ -110,6 +118,9 @@ class SenderDomainAuthenticationNotices { } public function isErrorStyle(): bool { + if (!$this->isEnforcementOfNewRestrictionsInEffect()) { + return false; + } if ( $this->subscribersFeatures->getSubscribersCount() < self::UPPER_LIMIT || $this->isPartiallyVerified() @@ -125,6 +136,17 @@ class SenderDomainAuthenticationNotices { } public function getNoticeContentForFreeMailUsers(int $contactCount): string { + if (!$this->isEnforcementOfNewRestrictionsInEffect()) { + // translators: %1$s is the domain of the user's default from address, %2$s is a rewritten version of their default from address, %3$s is HTML for an 'update sender' button, and %4$s is HTML for a Learn More button + return sprintf(__("Update your sender email address to a branded domain by February 1st, 2024 to continue sending your campaigns. +Starting on February 1st, 2024, MailPoet will no longer be able to send from email addresses on shared 3rd party domains like %1\$s. Please change your campaigns to send from an email address on your site's branded domain. Your emails will temporarily be sent from %2\$s.
%3\$s %4\$s
", 'mailpoet'), + "@" . $this->getDefaultFromDomain(), + $this->authorizedSenderDomainController->getRewrittenEmailAddress($this->getDefaultFromAddress()), + $this->getUpdateSenderButton(), + $this->getLearnMoreAboutFreeMailButton() + ); + } + if ($contactCount <= self::UPPER_LIMIT) { // translators: %1$s is the domain of the user's default from address, %2$s is a rewritten version of their default from address, %3$s is HTML for an 'update sender' button, and %4$s is HTML for a Learn More button return sprintf(__("Update your sender email address to a branded domain to continue sending your campaigns. @@ -147,7 +169,7 @@ class SenderDomainAuthenticationNotices { } public function getNoticeContentForBrandedDomainUsers(bool $isPartiallyVerified, int $contactCount): string { - if ($isPartiallyVerified || $contactCount <= self::LOWER_LIMIT) { + if (!$this->isEnforcementOfNewRestrictionsInEffect() || $isPartiallyVerified || $contactCount <= self::LOWER_LIMIT) { // translators: %1$s is HTML for an 'authenticate domain' button, %2$s is HTML for a Learn More button return sprintf(__("Authenticate your sender domain to improve email delivery rates. Major mailbox providers require you to authenticate your sender domain to confirm you sent the emails, and may place unauthenticated emails in the \"Spam\" folder. Please authenticate your sender domain to ensure your marketing campaigns are compliant and will reach your contacts.%1\$s %2\$s
", 'mailpoet'), diff --git a/mailpoet/tests/integration/Util/Notices/SenderDomainAuthenticationNoticesTest.php b/mailpoet/tests/integration/Util/Notices/SenderDomainAuthenticationNoticesTest.php index b37b24c1e1..218252987a 100644 --- a/mailpoet/tests/integration/Util/Notices/SenderDomainAuthenticationNoticesTest.php +++ b/mailpoet/tests/integration/Util/Notices/SenderDomainAuthenticationNoticesTest.php @@ -8,6 +8,7 @@ use MailPoet\Test\DataFactories\Newsletter; use MailPoet\Test\DataFactories\StatisticsNewsletters; use MailPoet\Test\DataFactories\Subscriber; use MailPoet\Util\Notices\SenderDomainAuthenticationNotices; +use MailPoetVendor\Carbon\Carbon; class SenderDomainAuthenticationNoticesTest extends \MailPoetTest { /** @var SenderDomainAuthenticationNotices */ @@ -63,10 +64,18 @@ class SenderDomainAuthenticationNoticesTest extends \MailPoetTest { 'address' => $email, ]); $rewrittenEmail = $this->authorizedSenderDomainController->getRewrittenEmailAddress($email); - $message = $this->notice->getNoticeContentForFreeMailUsers(1001); - $this->assertStringContainsString('Your newsletters and post notifications have been paused. Update your sender email address to a branded domain to continue sending your campaigns', $message); - $this->assertStringContainsString(sprintf('Your marketing automations and transactional emails will temporarily be sent from %s', $rewrittenEmail), $message); - $this->assertStringContainsString('Update sender email', $message); + + Carbon::setTestNow(Carbon::parse('2024-01-31 00:00:00 UTC')); + $beforeRestrictionsInEffectMessage = $this->notice->getNoticeContentForFreeMailUsers(999); + $this->assertStringContainsString('Update your sender email address to a branded domain by February 1st, 2024 to continue sending your campaigns.', $beforeRestrictionsInEffectMessage); + $this->assertStringContainsString(sprintf('Your emails will temporarily be sent from %s', $rewrittenEmail), $beforeRestrictionsInEffectMessage); + $this->assertStringContainsString('Update sender email', $beforeRestrictionsInEffectMessage); + + Carbon::setTestNow(Carbon::parse('2024-02-01 00:00:00 UTC')); + $afterRestrictionsInEffectMessage = $this->notice->getNoticeContentForFreeMailUsers(1001); + $this->assertStringContainsString('Your newsletters and post notifications have been paused. Update your sender email address to a branded domain to continue sending your campaigns', $afterRestrictionsInEffectMessage); + $this->assertStringContainsString(sprintf('Your marketing automations and transactional emails will temporarily be sent from %s', $rewrittenEmail), $afterRestrictionsInEffectMessage); + $this->assertStringContainsString('Update sender email', $afterRestrictionsInEffectMessage); } public function testItRetrievesAppropriateMessageForFreeMailUsersWithLessThan1000Contacts(): void { @@ -76,10 +85,18 @@ class SenderDomainAuthenticationNoticesTest extends \MailPoetTest { 'address' => $email, ]); $rewrittenEmail = $this->authorizedSenderDomainController->getRewrittenEmailAddress($email); - $message = $this->notice->getNoticeContentForFreeMailUsers(999); - $this->assertStringContainsString('Update your sender email address to a branded domain to continue sending your campaigns', $message); - $this->assertStringContainsString(sprintf('Your existing scheduled and active emails will temporarily be sent from %s', $rewrittenEmail), $message); - $this->assertStringContainsString('Update sender email', $message); + + Carbon::setTestNow(Carbon::parse('2024-01-31 00:00:00 UTC')); + $beforeRestrictionsInEffectMessage = $this->notice->getNoticeContentForFreeMailUsers(999); + $this->assertStringContainsString('Update your sender email address to a branded domain by February 1st, 2024 to continue sending your campaigns.', $beforeRestrictionsInEffectMessage); + $this->assertStringContainsString(sprintf('Your emails will temporarily be sent from %s', $rewrittenEmail), $beforeRestrictionsInEffectMessage); + $this->assertStringContainsString('Update sender email', $beforeRestrictionsInEffectMessage); + + Carbon::setTestNow(Carbon::parse('2024-02-01 00:00:00 UTC')); + $afterRestrictionsInEffectMessage = $this->notice->getNoticeContentForFreeMailUsers(999); + $this->assertStringContainsString('Update your sender email address to a branded domain to continue sending your campaigns', $afterRestrictionsInEffectMessage); + $this->assertStringContainsString(sprintf('Your existing scheduled and active emails will temporarily be sent from %s', $rewrittenEmail), $afterRestrictionsInEffectMessage); + $this->assertStringContainsString('Update sender email', $afterRestrictionsInEffectMessage); } public function testItRetrievesAppropriateMessageForBrandedDomainsWithMoreThan1000Contacts(): void { @@ -89,11 +106,18 @@ class SenderDomainAuthenticationNoticesTest extends \MailPoetTest { 'address' => $email, ]); $rewrittenEmail = $this->authorizedSenderDomainController->getRewrittenEmailAddress($email); - $message = $this->notice->getNoticeContentForBrandedDomainUsers(false, 1001); - $this->assertStringContainsString('Your newsletters and post notifications have been paused. Authenticate your sender domain to continue sending.', $message); - $this->assertStringContainsString('Your marketing automations and transactional emails will temporarily be sent from', $message); - $this->assertStringContainsString($rewrittenEmail, $message); - $this->assertStringContainsString('Authenticate domain', $message); + + Carbon::setTestNow(Carbon::parse('2024-01-31 00:00:00 UTC')); + $beforeRestrictionsInEffectMessage = $this->notice->getNoticeContentForBrandedDomainUsers(false, 1001); + $this->assertStringContainsString('Authenticate your sender domain to improve email delivery rates.', $beforeRestrictionsInEffectMessage); + $this->assertStringContainsString('Please authenticate your sender domain to ensure your marketing campaigns are compliant and will reach your contacts', $beforeRestrictionsInEffectMessage); + + Carbon::setTestNow(Carbon::parse('2024-02-01 00:00:00 UTC')); + $afterRestrictionsInEffectMessage = $this->notice->getNoticeContentForBrandedDomainUsers(false, 1001); + $this->assertStringContainsString('Your newsletters and post notifications have been paused. Authenticate your sender domain to continue sending.', $afterRestrictionsInEffectMessage); + $this->assertStringContainsString('Your marketing automations and transactional emails will temporarily be sent from', $afterRestrictionsInEffectMessage); + $this->assertStringContainsString($rewrittenEmail, $afterRestrictionsInEffectMessage); + $this->assertStringContainsString('Authenticate domain', $afterRestrictionsInEffectMessage); } public function testItRetrievesAppropriateMessageForBrandedDomainsWithLessThan1000Contacts(): void { @@ -103,11 +127,18 @@ class SenderDomainAuthenticationNoticesTest extends \MailPoetTest { 'address' => $email, ]); $rewrittenEmail = $this->authorizedSenderDomainController->getRewrittenEmailAddress($email); - $message = $this->notice->getNoticeContentForBrandedDomainUsers(false, 999); - $this->assertStringContainsString('Authenticate your sender domain to send new emails.', $message); - $this->assertStringContainsString('Your existing scheduled and active emails will temporarily be sent from', $message); - $this->assertStringContainsString($rewrittenEmail, $message); - $this->assertStringContainsString('Authenticate domain', $message); + + Carbon::setTestNow(Carbon::parse('2024-01-31 00:00:00 UTC')); + $beforeRestrictionsInEffectMessage = $this->notice->getNoticeContentForBrandedDomainUsers(false, 1001); + $this->assertStringContainsString('Authenticate your sender domain to improve email delivery rates.', $beforeRestrictionsInEffectMessage); + $this->assertStringContainsString('Please authenticate your sender domain to ensure your marketing campaigns are compliant and will reach your contacts', $beforeRestrictionsInEffectMessage); + + Carbon::setTestNow(Carbon::parse('2024-02-01 00:00:00 UTC')); + $afterRestrictionsInEffectMessage = $this->notice->getNoticeContentForBrandedDomainUsers(false, 999); + $this->assertStringContainsString('Authenticate your sender domain to send new emails.', $afterRestrictionsInEffectMessage); + $this->assertStringContainsString('Your existing scheduled and active emails will temporarily be sent from', $afterRestrictionsInEffectMessage); + $this->assertStringContainsString($rewrittenEmail, $afterRestrictionsInEffectMessage); + $this->assertStringContainsString('Authenticate domain', $afterRestrictionsInEffectMessage); } public function testItRetrievesAppropriateMessageForBrandedDomainsWithLessThan500Contacts(): void { @@ -154,4 +185,11 @@ class SenderDomainAuthenticationNoticesTest extends \MailPoetTest { (new StatisticsNewsletters((new Newsletter())->withSendingQueue()->create(), (new Subscriber())->create()))->create(); $this->assertFalse($this->notice->isNewUser()); } + + public function testItKnowsWhenNewRestrictionsStartGettingEnforced(): void { + Carbon::setTestNow(Carbon::parse('2024-01-31 00:00:00 UTC')); + $this->assertFalse($this->notice->isEnforcementOfNewRestrictionsInEffect()); + Carbon::setTestNow(Carbon::parse('2024-02-01 00:00:01 UTC')); + $this->assertTrue($this->notice->isEnforcementOfNewRestrictionsInEffect()); + } } diff --git a/mailpoet/tests/integration/_bootstrap.php b/mailpoet/tests/integration/_bootstrap.php index 5388cc5848..6e661d996d 100644 --- a/mailpoet/tests/integration/_bootstrap.php +++ b/mailpoet/tests/integration/_bootstrap.php @@ -238,6 +238,8 @@ abstract class MailPoetTest extends \Codeception\TestCase\Test { // phpcs:ignore public function _after() { parent::_after(); $this->tester->cleanup(); + // Reset any overrides + Carbon::setTestNow(); } }