Files
piratepoet/mailpoet/lib/Mailer/Methods/ErrorMappers/MailPoetMapper.php
2023-05-10 13:05:37 +02:00

280 lines
10 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php // phpcs:ignore SlevomatCodingStandard.TypeHints.DeclareStrictTypes.DeclareStrictTypesMissing
namespace MailPoet\Mailer\Methods\ErrorMappers;
use InvalidArgumentException;
use MailPoet\Config\ServicesChecker;
use MailPoet\Mailer\Mailer;
use MailPoet\Mailer\MailerError;
use MailPoet\Mailer\SubscriberError;
use MailPoet\Services\Bridge\API;
use MailPoet\Util\Helpers;
use MailPoet\Util\License\Features\Subscribers as SubscribersFeature;
use MailPoet\Util\Notices\UnauthorizedEmailNotice;
use MailPoet\WP\Functions as WPFunctions;
use MailPoetVendor\Carbon\Carbon;
class MailPoetMapper {
use BlacklistErrorMapperTrait;
use ConnectionErrorMapperTrait;
const METHOD = Mailer::METHOD_MAILPOET;
const TEMPORARY_UNAVAILABLE_RETRY_INTERVAL = 300; // seconds
/** @var ServicesChecker */
private $servicesChecker;
/** @var SubscribersFeature */
private $subscribersFeature;
/** @var WPFunctions */
private $wp;
public function __construct(
ServicesChecker $servicesChecker,
SubscribersFeature $subscribers,
WPFunctions $wp
) {
$this->servicesChecker = $servicesChecker;
$this->subscribersFeature = $subscribers;
$this->wp = $wp;
}
public function getInvalidApiKeyError() {
return new MailerError(
MailerError::OPERATION_SEND,
MailerError::LEVEL_HARD,
__('MailPoet API key is invalid!', 'mailpoet')
);
}
public function getErrorForResult(array $result, $subscribers, $sender = null, $newsletter = null) {
$level = MailerError::LEVEL_HARD;
$operation = MailerError::OPERATION_SEND;
$retryInterval = null;
$subscribersErrors = [];
$resultCode = !empty($result['code']) ? $result['code'] : null;
switch ($resultCode) {
case API::RESPONSE_CODE_NOT_ARRAY:
$message = __('JSON input is not an array', 'mailpoet');
break;
case API::RESPONSE_CODE_PAYLOAD_ERROR:
$resultParsed = json_decode($result['message'], true);
$message = __('Error while sending.', 'mailpoet');
if (!is_array($resultParsed)) {
if (isset($result['error']) && $result['error'] === API::ERROR_MESSAGE_DMRAC) {
$message .= $this->getDmarcMessage($result, $sender);
} else {
$message .= ' ' . $result['message'];
}
break;
}
try {
$subscribersErrors = $this->getSubscribersErrors($resultParsed, $subscribers);
$level = MailerError::LEVEL_SOFT;
} catch (InvalidArgumentException $e) {
$message .= ' ' . $e->getMessage();
}
break;
case API::RESPONSE_CODE_INTERNAL_SERVER_ERROR:
case API::RESPONSE_CODE_BAD_GATEWAY:
case API::RESPONSE_CODE_TEMPORARY_UNAVAILABLE:
case API::RESPONSE_CODE_GATEWAY_TIMEOUT:
$message = __('Email service is temporarily not available, please try again in a few minutes.', 'mailpoet');
$retryInterval = self::TEMPORARY_UNAVAILABLE_RETRY_INTERVAL;
break;
case API::RESPONSE_CODE_CAN_NOT_SEND:
[$operation, $message] = $this->getCanNotSendError($result, $sender);
break;
case API::RESPONSE_CODE_KEY_INVALID:
case API::RESPONSE_CODE_PAYLOAD_TOO_BIG:
default:
$message = $result['message'];
}
return new MailerError($operation, $level, $message, $retryInterval, $subscribersErrors);
}
private function getSubscribersErrors($resultParsed, $subscribers) {
$errors = [];
foreach ($resultParsed as $resultError) {
if (!is_array($resultError) || !isset($resultError['index']) || !isset($subscribers[$resultError['index']])) {
throw new InvalidArgumentException(__('Invalid MSS response format.', 'mailpoet'));
}
$subscriberErrors = [];
if (isset($resultError['errors']) && is_array($resultError['errors'])) {
array_walk_recursive($resultError['errors'], function($item) use (&$subscriberErrors) {
$subscriberErrors[] = $item;
});
}
$message = join(', ', $subscriberErrors);
$errors[] = new SubscriberError($subscribers[$resultError['index']], $message);
}
return $errors;
}
private function getUnauthorizedEmailMessage($sender) {
$email = $sender ? $sender['from_email'] : __('Unknown address', 'mailpoet');
$validationError = ['invalid_sender_address' => $email];
$notice = new UnauthorizedEmailNotice($this->wp, null);
$message = $notice->getMessage($validationError);
return $message;
}
private function getSubscribersLimitReachedMessage(): string {
$message = __('You have reached the subscriber limit of your plan. Please [link1]upgrade your plan[/link1], or [link2]contact our support team[/link2] if you have any questions.', 'mailpoet');
$message = Helpers::replaceLinkTags(
$message,
'https://account.mailpoet.com/account/',
[
'target' => '_blank',
'rel' => 'noopener noreferrer',
],
'link1'
);
$message = Helpers::replaceLinkTags(
$message,
'https://www.mailpoet.com/support/',
[
'target' => '_blank',
'rel' => 'noopener noreferrer',
],
'link2'
);
return "{$message}<br/>";
}
private function getAccountBannedMessage(): string {
$message = __('MailPoet Sending Service has been temporarily suspended for your site due to [link1]degraded email deliverability[/link1]. Please [link2]contact our support team[/link2] to resolve the issue.', 'mailpoet');
$message = Helpers::replaceLinkTags(
$message,
'https://kb.mailpoet.com/article/231-sending-does-not-work#suspended',
[
'target' => '_blank',
'rel' => 'noopener noreferrer',
],
'link1'
);
$message = Helpers::replaceLinkTags(
$message,
'https://www.mailpoet.com/support/',
[
'target' => '_blank',
'rel' => 'noopener noreferrer',
],
'link2'
);
return "{$message}<br/>";
}
private function getDmarcMessage($result, $sender): string {
$messageToAppend = __('[link1]Click here to start the authentication[/link1].', 'mailpoet');
$senderEmail = $sender['from_email'] ?? '';
$appendMessage = Helpers::replaceLinkTags(
$messageToAppend,
'#',
[
'class' => 'mailpoet-js-button-authorize-email-and-sender-domain',
'data-email' => $senderEmail,
'data-type' => 'domain',
'rel' => 'noopener noreferrer',
],
'link1'
);
$final = ' ' . $result['message'] . ' ' . $appendMessage;
return $final;
}
private function getEmailVolumeLimitReachedMessage(): string {
$partialApiKey = $this->servicesChecker->generatePartialApiKey();
$emailVolumeLimit = $this->subscribersFeature->getEmailVolumeLimit();
$date = Carbon::now()->startOfMonth()->addMonth();
if ($emailVolumeLimit) {
$message = sprintf(
// translators: %1$s is email volume limit and %2$s the date when you can resume sending.
__('You have sent more emails this month than your MailPoet plan includes (%1$s), and sending has been temporarily paused. To continue sending with MailPoet Sending Service please [link]upgrade your plan[/link], or wait until sending is automatically resumed on %2$s.', 'mailpoet'),
$emailVolumeLimit,
$this->wp->dateI18n($this->wp->getOption('date_format'), $date->getTimestamp())
);
} else {
$message = sprintf(
// translators: %1$s the date when you can resume sending.
__('You have sent more emails this month than your MailPoet plan includes, and sending has been temporarily paused. To continue sending with MailPoet Sending Service please [link]upgrade your plan[/link], or wait until sending is automatically resumed on %1$s.', 'mailpoet'),
$this->wp->dateI18n($this->wp->getOption('date_format'), $date->getTimestamp())
);
}
$message = Helpers::replaceLinkTags(
$message,
"https://account.mailpoet.com/orders/upgrade/{$partialApiKey}",
[
'target' => '_blank',
'rel' => 'noopener noreferrer',
]
);
return "{$message}<br/>";
}
private function getPendingApprovalMessage(): string {
$message = __("Your subscription is currently [link]pending approval[/link]. Youll soon be able to send once our team reviews your account. In the meantime, you can send previews to your authorized emails.", 'mailpoet');
$message = Helpers::replaceLinkTags(
$message,
'https://kb.mailpoet.com/article/350-pending-approval-subscription',
[
'target' => '_blank',
'rel' => 'noopener noreferrer',
'data-beacon-article' => '5fbd3942cff47e00160bd248',
]
);
return "{$message}<br/>";
}
/**
* Returns error $message and $operation for API::RESPONSE_CODE_CAN_NOT_SEND
*/
private function getCanNotSendError(array $result, $sender): array {
if ($result['error'] === API::ERROR_MESSAGE_PENDING_APPROVAL) {
$operation = MailerError::OPERATION_PENDING_APPROVAL;
$message = $this->getPendingApprovalMessage();
return [$operation, $message];
}
// Backward compatibility for older blocked keys.
// Exceeded subscribers limit used to use the same error message as insufficient privileges.
// We can change the message to "Insufficient privileges" like wording a couple of months after releasing SHOP-1228
if ($result['error'] === API::ERROR_MESSAGE_INSUFFICIENT_PRIVILEGES) {
$operation = MailerError::OPERATION_INSUFFICIENT_PRIVILEGES;
$message = $this->getSubscribersLimitReachedMessage();
return [$operation, $message];
}
if ($result['error'] === API::ERROR_MESSAGE_SUBSCRIBERS_LIMIT_REACHED) {
$operation = MailerError::OPERATION_SUBSCRIBER_LIMIT_REACHED;
$message = $this->getSubscribersLimitReachedMessage();
return [$operation, $message];
}
if ($result['error'] === API::ERROR_MESSAGE_EMAIL_VOLUME_LIMIT_REACHED) {
$operation = MailerError::OPERATION_EMAIL_LIMIT_REACHED;
$message = $this->getEmailVolumeLimitReachedMessage();
return [$operation, $message];
}
if ($result['error'] === API::ERROR_MESSAGE_INVALID_FROM) {
$operation = MailerError::OPERATION_AUTHORIZATION;
$message = $this->getUnauthorizedEmailMessage($sender);
return [$operation, $message];
}
$message = $this->getAccountBannedMessage();
$operation = MailerError::OPERATION_SEND;
return [$operation, $message];
}
}