diff --git a/mailpoet/lib/API/JSON/v1/Settings.php b/mailpoet/lib/API/JSON/v1/Settings.php index d7a4f32d84..eec0f306b5 100644 --- a/mailpoet/lib/API/JSON/v1/Settings.php +++ b/mailpoet/lib/API/JSON/v1/Settings.php @@ -197,6 +197,55 @@ class Settings extends APIEndpoint { return $this->successResponse(); } + /** + * Makes POST request to Bridge endpoint to add email to user email authorization list + */ + public function authorizeSenderEmailAddress($data = []) { + $emailAddress = $data['email'] ?? null; + + if (!$emailAddress) { + return $this->badRequest([ + APIError::BAD_REQUEST => WPFunctions::get()->__('No email address specified.', 'mailpoet'), + ]); + } + + $emailAddress = trim($emailAddress); + + try { + $response = $this->authorizedEmailsController->createAuthorizedEmailAddress($emailAddress); + } catch (\InvalidArgumentException $e) { + if ( + $e->getMessage() === AuthorizedEmailsController::AUTHORIZED_EMAIL_ERROR_ALREADY_AUTHORIZED || + $e->getMessage() === AuthorizedEmailsController::AUTHORIZED_EMAIL_ERROR_PENDING_CONFIRMATION + ) { + // return true if the email is already authorized or pending confirmation + $response = true; + } else { + return $this->badRequest([ + APIError::BAD_REQUEST => WPFunctions::get()->__($e->getMessage(), 'mailpoet'), + ]); + } + } + + return $this->successResponse($response); + } + + public function confirmSenderEmailAddressIsAuthorized($data = []) { + $emailAddress = $data['email'] ?? null; + + if (!$emailAddress) { + return $this->badRequest([ + APIError::BAD_REQUEST => WPFunctions::get()->__('No email address specified.', 'mailpoet'), + ]); + } + + $emailAddress = trim($emailAddress); + + $response = ['isAuthorized' => $this->authorizedEmailsController->isEmailAddressAuthorized($emailAddress)]; + + return $this->successResponse($response); + } + private function onSettingsChange($oldSettings, $newSettings) { // Recalculate inactive subscribers $oldInactivationInterval = $oldSettings['deactivate_subscriber_after_inactive_days']; diff --git a/mailpoet/lib/Services/AuthorizedEmailsController.php b/mailpoet/lib/Services/AuthorizedEmailsController.php index 450f1886a6..3b09a0d56d 100644 --- a/mailpoet/lib/Services/AuthorizedEmailsController.php +++ b/mailpoet/lib/Services/AuthorizedEmailsController.php @@ -13,6 +13,12 @@ use MailPoet\Settings\SettingsController; class AuthorizedEmailsController { const AUTHORIZED_EMAIL_ADDRESSES_ERROR_SETTING = 'authorized_emails_addresses_check'; + const AUTHORIZED_EMAIL_ADDRESSES_API_TYPE_AUTHORIZED = 'authorized'; + const AUTHORIZED_EMAIL_ADDRESSES_API_TYPE_PENDING = 'pending'; + const AUTHORIZED_EMAIL_ADDRESSES_API_TYPE_ALL = 'all'; + const AUTHORIZED_EMAIL_ERROR_ALREADY_AUTHORIZED = 'Email address is already authorized'; + const AUTHORIZED_EMAIL_ERROR_PENDING_CONFIRMATION = 'Email address is pending confirmation'; + /** @var Bridge */ private $bridge; @@ -58,6 +64,37 @@ class AuthorizedEmailsController { $this->settings->set(self::AUTHORIZED_EMAIL_ADDRESSES_ERROR_SETTING, null); } + public function getAllAuthorizedEmailAddress() { + return $this->bridge->getAuthorizedEmailAddresses(self::AUTHORIZED_EMAIL_ADDRESSES_API_TYPE_ALL); + } + + public function createAuthorizedEmailAddress(string $email) { + $allEmails = $this->getAllAuthorizedEmailAddress(); + + $authorizedEmails = array_map('strtolower', $allEmails[self::AUTHORIZED_EMAIL_ADDRESSES_API_TYPE_AUTHORIZED]); + $isAuthorized = $this->validateAuthorizedEmail($authorizedEmails, $email); + + if ($isAuthorized) { + throw new \InvalidArgumentException(self::AUTHORIZED_EMAIL_ERROR_ALREADY_AUTHORIZED); + } + + $pendingEmails = array_map('strtolower', $allEmails[self::AUTHORIZED_EMAIL_ADDRESSES_API_TYPE_PENDING]); + $isPending = $this->validateAuthorizedEmail($pendingEmails, $email); + + if ($isPending) { + throw new \InvalidArgumentException(self::AUTHORIZED_EMAIL_ERROR_PENDING_CONFIRMATION); + } + + $finalData = $this->bridge->createAuthorizedEmailAddress($email); + + return $finalData; + } + + public function isEmailAddressAuthorized(string $email): bool { + $authorizedEmails = array_map('strtolower', $this->bridge->getAuthorizedEmailAddresses() ?: []); + return $this->validateAuthorizedEmail($authorizedEmails, $email); + } + public function checkAuthorizedEmailAddresses() { if (!Bridge::isMPSendingServiceEnabled()) { $this->settings->set(self::AUTHORIZED_EMAIL_ADDRESSES_ERROR_SETTING, null); diff --git a/mailpoet/lib/Services/Bridge.php b/mailpoet/lib/Services/Bridge.php index 73441d1c77..abcd1d6049 100644 --- a/mailpoet/lib/Services/Bridge.php +++ b/mailpoet/lib/Services/Bridge.php @@ -118,11 +118,26 @@ class Bridge { return $this->api; } - public function getAuthorizedEmailAddresses(): array { + public function getAuthorizedEmailAddresses($type = 'authorized'): array { $data = $this ->getApi($this->settings->get(self::API_KEY_SETTING_NAME)) ->getAuthorizedEmailAddresses(); - return $data ? $data['authorized'] : []; + if ($data && $type === 'all') { + return $data; + } + return $data ? $data[$type] : []; + } + + /** + * Create Authorized Email Address + * Return true if done, false for errors + */ + public function createAuthorizedEmailAddress(string $emailAdress): bool { + $data = $this + ->getApi($this->settings->get(self::API_KEY_SETTING_NAME)) + ->createAuthorizedEmailAddress($emailAdress); + + return $data; } public function checkMSSKey($apiKey) { diff --git a/mailpoet/lib/Services/Bridge/API.php b/mailpoet/lib/Services/Bridge/API.php index 050a8da536..8241f3b75d 100644 --- a/mailpoet/lib/Services/Bridge/API.php +++ b/mailpoet/lib/Services/Bridge/API.php @@ -15,6 +15,7 @@ class API { const RESPONSE_CODE_KEY_INVALID = 401; const RESPONSE_CODE_STATS_SAVED = 204; + const RESPONSE_CODE_CREATED = 201; const RESPONSE_CODE_INTERNAL_SERVER_ERROR = 500; const RESPONSE_CODE_BAD_GATEWAY = 502; const RESPONSE_CODE_TEMPORARY_UNAVAILABLE = 503; @@ -179,6 +180,27 @@ class API { return is_array($data) ? $data : null; } + public function createAuthorizedEmailAddress(string $emailAdress): bool { + $body = ['email' => $emailAdress]; + $result = $this->request( + $this->urlAuthorizedEmailAddresses, + $body + ); + + $code = $this->wp->wpRemoteRetrieveResponseCode($result); + $isSuccess = $code === self::RESPONSE_CODE_CREATED; + + if (!$isSuccess) { + $logData = [ + 'code' => $code, + 'error' => is_wp_error($result) ? $result->get_error_message() : null, + ]; + $this->loggerFactory->getLogger(LoggerFactory::TOPIC_BRIDGE)->error('CreateAuthorizedEmailAddress API call failed.', $logData); + } + + return $isSuccess; + } + public function setKey($apiKey) { $this->apiKey = $apiKey; }