| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187 |
- <?php
- namespace MailPoet\Mailer;
- if (!defined('ABSPATH')) exit;
- use MailPoet\Settings\SettingsController;
- class MailerLog {
- const SETTING_NAME = 'mta_log';
- const STATUS_PAUSED = 'paused';
- const RETRY_ATTEMPTS_LIMIT = 3;
- const RETRY_INTERVAL = 120; // seconds
- public static function getMailerLog($mailerLog = false) {
- if ($mailerLog) return $mailerLog;
- $settings = SettingsController::getInstance();
- $mailerLog = $settings->get(self::SETTING_NAME);
- if (!$mailerLog) {
- $mailerLog = self::createMailerLog();
- }
- return $mailerLog;
- }
- public static function createMailerLog() {
- $mailerLog = [
- 'sent' => null,
- 'started' => time(),
- 'status' => null,
- 'retry_attempt' => null,
- 'retry_at' => null,
- 'error' => null,
- ];
- $settings = SettingsController::getInstance();
- $settings->set(self::SETTING_NAME, $mailerLog);
- return $mailerLog;
- }
- public static function resetMailerLog() {
- return self::createMailerLog();
- }
- public static function updateMailerLog($mailerLog) {
- $settings = SettingsController::getInstance();
- $settings->set(self::SETTING_NAME, $mailerLog);
- return $mailerLog;
- }
- public static function enforceExecutionRequirements($mailerLog = false) {
- $mailerLog = self::getMailerLog($mailerLog);
- if ($mailerLog['retry_attempt'] === self::RETRY_ATTEMPTS_LIMIT) {
- $mailerLog = self::pauseSending($mailerLog);
- }
- if (self::isSendingPaused($mailerLog)) {
- throw new \Exception(__('Sending has been paused.', 'mailpoet'));
- }
- if (!is_null($mailerLog['retry_at'])) {
- if (time() <= $mailerLog['retry_at']) {
- throw new \Exception(__('Sending is waiting to be retried.', 'mailpoet'));
- } else {
- $mailerLog['retry_at'] = null;
- self::updateMailerLog($mailerLog);
- }
- }
- // ensure that sending frequency has not been reached
- if (self::isSendingLimitReached($mailerLog)) {
- throw new \Exception(__('Sending frequency limit has been reached.', 'mailpoet'));
- }
- }
- public static function pauseSending($mailerLog) {
- $mailerLog['status'] = self::STATUS_PAUSED;
- $mailerLog['retry_attempt'] = null;
- $mailerLog['retry_at'] = null;
- return self::updateMailerLog($mailerLog);
- }
- public static function resumeSending() {
- return self::resetMailerLog();
- }
- /**
- * Process error, doesn't increase retry_attempt so it will not block sending
- *
- * @param string $operation
- * @param string $errorMessage
- * @param int $retryInterval
- *
- * @throws \Exception
- */
- public static function processNonBlockingError($operation, $errorMessage, $retryInterval = self::RETRY_INTERVAL) {
- $mailerLog = self::getMailerLog();
- $mailerLog['retry_at'] = time() + $retryInterval;
- $mailerLog = self::setError($mailerLog, $operation, $errorMessage);
- self::updateMailerLog($mailerLog);
- self::enforceExecutionRequirements();
- }
- /**
- * Process error, increase retry_attempt and block sending if it goes above RETRY_INTERVAL
- *
- * @param string $operation
- * @param string $errorMessage
- * @param string $errorCode
- * @param bool $pauseSending
- *
- * @throws \Exception
- */
- public static function processError($operation, $errorMessage, $errorCode = null, $pauseSending = false, $throttledBatchSize = null) {
- $mailerLog = self::getMailerLog();
- if (!isset($throttledBatchSize) || $throttledBatchSize === 1) {
- $mailerLog['retry_attempt']++;
- }
- $mailerLog['retry_at'] = time() + self::RETRY_INTERVAL;
- $mailerLog = self::setError($mailerLog, $operation, $errorMessage, $errorCode);
- self::updateMailerLog($mailerLog);
- if ($pauseSending) {
- self::pauseSending($mailerLog);
- }
- self::enforceExecutionRequirements();
- }
- public static function setError($mailerLog, $operation, $errorMessage, $errorCode = null) {
- $mailerLog['error'] = [
- 'operation' => $operation,
- 'error_message' => $errorMessage,
- ];
- if ($errorCode) {
- $mailerLog['error']['error_code'] = $errorCode;
- }
- return $mailerLog;
- }
- public static function getError($mailerLog = false) {
- $mailerLog = self::getMailerLog($mailerLog);
- return isset($mailerLog['error']) ? $mailerLog['error'] : null;
- }
- public static function incrementSentCount() {
- $mailerLog = self::getMailerLog();
- // do not increment count if sending limit is reached
- if (self::isSendingLimitReached($mailerLog)) return;
- // clear previous retry count, errors, etc.
- if ($mailerLog['error']) {
- $mailerLog = self::clearSendingErrorLog($mailerLog);
- }
- (int)$mailerLog['sent']++;
- return self::updateMailerLog($mailerLog);
- }
- public static function clearSendingErrorLog($mailerLog) {
- $mailerLog['retry_attempt'] = null;
- $mailerLog['retry_at'] = null;
- $mailerLog['error'] = null;
- return self::updateMailerLog($mailerLog);
- }
- public static function isSendingLimitReached($mailerLog = false) {
- $settings = SettingsController::getInstance();
- $mailerConfig = $settings->get(Mailer::MAILER_CONFIG_SETTING_NAME);
- // do not enforce sending limit for MailPoet's sending method
- if ($mailerConfig['method'] === Mailer::METHOD_MAILPOET) return false;
- $mailerLog = self::getMailerLog($mailerLog);
- $elapsedTime = time() - (int)$mailerLog['started'];
- if (empty($mailer['frequency'])) {
- $defaultSettings = $settings->getAllDefaults();
- $mailer['frequency'] = $defaultSettings['mta']['frequency'];
- }
- $frequencyInterval = (int)$mailerConfig['frequency']['interval'] * Mailer::SENDING_LIMIT_INTERVAL_MULTIPLIER;
- $frequencyLimit = (int)$mailerConfig['frequency']['emails'];
- if ($mailerLog['sent'] >= $frequencyLimit) {
- if ($elapsedTime <= $frequencyInterval) return true;
- // reset mailer log as enough time has passed since the limit was reached
- self::resetMailerLog();
- }
- return false;
- }
- public static function isSendingPaused($mailerLog = false) {
- $mailerLog = self::getMailerLog($mailerLog);
- return $mailerLog['status'] === self::STATUS_PAUSED;
- }
- }
|