PluginProbe
AcyMailing – An Ultimate Newsletter Plugin and Marketing Automation Solution for WordPress / 10.2.2
AcyMailing – An Ultimate Newsletter Plugin and Marketing Automation Solution for WordPress v10.2.2
11.1.1 11.1.0 11.0.5 11.0.4 11.0.3 11.0.2 11.0.1 11.0.0 10.11.1 10.11.0 10.10.2 10.10.1 10.10.0 10.9.1 trunk 10.0.0 10.0.1 10.1.0 10.1.1 10.1.2 10.1.3 10.1.4 10.2.0 10.2.1 10.2.2 All 62 releases
acymailing / back / dynamics / acymailer / plugin.php

plugin.php in AcyMailing – An Ultimate Newsletter Plugin and Marketing Automation Solution for WordPress 10.2.2, at back/dynamics/acymailer/plugin.php

1,213 lines 52.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 use AcyMailing\Classes\MailClass;
4 use AcyMailing\Classes\QueueClass;
5 use AcyMailing\Core\AcymPlugin;
6
7 class plgAcymAcymailer extends AcymPlugin
8 {
9 const SENDING_METHOD_ID = 'acymailer';
10 const SENDING_METHOD_NAME = 'AcyMailing sending service';
11 const SENDING_METHOD_API_URL = 'https://api.acymailer.com/';
12 const CREDITS_RELOAD_DELAY = 900;
13 const TRANSLATIONS = [
14 0 => 'ACYM_ERROR_OCCURRED',
15 1 => 'ACYM_PLEASE_INSTALL_LATEST_VERSION',
16 2 => 'ACYM_ERROR_OCCURRED_WHEN_TRYING_TO_SEND_THE_EMAIL',
17 3 => 'ACYM_DOMAIN_NOT_ATTACHED_TO_THE_SITE',
18 4 => 'ACYM_NOT_ALLOWED_TO_DELETE_THIS_DOMAIN',
19 5 => 'ACYM_DOMAIN_DOES_NOT_EXIST',
20 6 => 'ACYM_DOMAIN_STATUS_SUCCESSFULLY_OBTAINED',
21 7 => 'ACYM_AN_ERROR_RELATED_TO_THE_REMAINING_CREDITS_OCCURRED',
22 8 => 'ACYM_LICENSE_EXPIRED',
23 9 => 'ACYM_IDENTITY_CREATED',
24 10 => 'ACYM_DOMAIN_ALREADY_EXISTS_FOR_THIS_WEBSITE',
25 11 => 'ACYM_DOMAIN_ALREADY_EXISTS_AND_DOES_NOT_BELONG_TO_YOU',
26 12 => 'ACYM_NO_DOMAINS_TO_CHECK',
27 13 => 'ACYM_DOMAINS_VERIFIED',
28 14 => 'ACYM_ERROR_WHILE_CHECKING_DOMAINS',
29 15 => 'ACYM_BLOCKED_LICENSE',
30 16 => 'ACYM_MISSING_EMAIL',
31 17 => 'ACYM_MISSING_ARGUMENTS',
32 18 => 'ACYM_NO_CREDITS_LEFT',
33 19 => 'ACYM_MISSING_API_KEY',
34 20 => 'ACYM_DOMAIN_NOT_FOUND',
35 21 => 'ACYM_LICENSE_NOT_FOUND',
36 22 => 'ACYM_EMAIL_SENT',
37 23 => 'ACYM_INVALID_API_KEY',
38 24 => 'ACYM_LICENSE_BLOCKED',
39 25 => 'ACYM_SEE_LOGS_FILE',
40 26 => 'ACYM_SERVICE_TEMPORARY_UNAVAILABLE',
41 27 => 'ACYM_DOMAIN_ONLY_ON_ONE_LICENSE',
42 28 => 'ACYM_EMAIL_UNDER_VERIFICATION',
43 ];
44 private $errorCodes = [0, 1, 2, 3, 4, 5, 7, 8, 10, 11, 12, 14, 15, 16, 17, 18, 19, 20, 21, 23, 24, 25, 26, 27, 28];
45 private $cnameErrors = [];
46
47 public function __construct()
48 {
49 parent::__construct();
50 $this->pluginDescription->name = self::SENDING_METHOD_NAME;
51 }
52
53 protected function callApiSendingMethod($url, $data = [], $headers = [], $type = 'GET', $authentication = [], $dataDecoded = false)
54 {
55 if (strpos($url, self::SENDING_METHOD_API_URL) === false) {
56 $url = self::SENDING_METHOD_API_URL.'api/'.$url;
57 }
58
59 $defaultHeaders = [
60 'accept' => 'application/json',
61 'content-type' => 'application/json',
62 'API-KEY' => $this->config->get(self::SENDING_METHOD_ID.'_apikey', ''),
63 'Version' => $this->config->get('version'),
64 ];
65
66 foreach ($defaultHeaders as $key => $value) {
67 if (!isset($headers[$key])) {
68 $headers[$key] = $value;
69 }
70 }
71
72 $result = parent::callApiSendingMethod($url, $data, $headers, $type, $authentication, $dataDecoded);
73 if (!empty($result['error_curl'])) {
74 $result['message'] = $result['error_curl'];
75 $this->errors[] = $result['error_curl'];
76 $this->errorCallback();
77 } else {
78 $result['message'] = $this->translate($result);
79 }
80
81 return $result;
82 }
83
84 public function onAcymGetSendingMethods(&$data, $isMailer = false)
85 {
86 $data['sendingMethods'][self::SENDING_METHOD_ID] = [
87 'name' => $this->pluginDescription->name,
88 'image' => ACYM_IMAGES.'mailers/'.self::SENDING_METHOD_ID.'.png',
89 'recommended' => true,
90 'image_class' => '',
91 ];
92 }
93
94 public function onAcymAttachedLicenseOption()
95 {
96 $licenseKey = $this->config->get('license_key');
97 $acyMailerKey = $this->config->get('acymailer_apikey');
98 $mailerMethod = $this->config->get('mailer_method');
99
100 if (empty($licenseKey) || empty($acyMailerKey) || $mailerMethod === self::SENDING_METHOD_ID) {
101 return;
102 }
103 ?>
104 <div class="grid-x grid-margin-x margin-top-1" id="activate_ass_method_notice">
105 <label class="cell medium-7 acym_vcenter">
106 <i class="acymicon-info-circle" id="acymailer_info_icon"></i>
107 <?php echo acym_translation('ACYM_ACTIVATE_ACYMAILER'); ?>
108 </label>
109 <button type="button"
110 id="acym__configuration__activate__acymailer"
111 class="cell shrink button margin-bottom-0">
112 <?php echo acym_translation('ACYM_SEE_THE_SENDING_METHOD'); ?>
113 </button>
114 </div>
115 <?php
116 }
117
118 public function onAcymGetSendingMethodsHtmlSetting(&$data)
119 {
120 $licenseKey = $this->config->get('license_key');
121 $acyMailerKey = $this->config->get('acymailer_apikey');
122 $domains = $this->config->get(self::SENDING_METHOD_ID.'_domains', []);
123 $domainsWaiting = [];
124 if (!empty($domains)) {
125 $domains = json_decode($domains, true);
126 $domainsWaiting = array_filter($domains, function ($domain) {
127 return $domain['status'] !== 'SUCCESS';
128 });
129 }
130
131 $unverifiedDomains = $this->getDomainsUnVerified();
132
133 ob_start();
134 ?>
135 <div class="send_settings cell grid-x acym_vcenter" id="<?php echo self::SENDING_METHOD_ID; ?>_settings">
136 <div class="cell grid-x acym__sending__methods__one__settings <?php echo empty($data['step']) ? 'xlarge-10 xxlarge-8' : '' ?>">
137 <?php if (!acym_level(ACYM_ESSENTIAL) && empty($data['step'])) { ?>
138 <div class="acym_vcenter acym__config__acymailer__warning margin-top-1 cell grid-x large-8 xlarge-6 xxlarge-5">
139 <label for="acym__configuration__license-key" class="cell">
140 <?php echo acym_translation('ACYM_YOUR_LICENSE_KEY'); ?>
141 </label>
142 <input type="text" name="config[license_key]" id="acym__configuration__license-key" class="cell auto" value="<?php echo acym_escape($licenseKey); ?>">
143 <button type="button"
144 id="acym__configuration__button__license"
145 class="cell shrink medium-3 button margin-top-1 medium-margin-top-0 medium-margin-left-1"
146 data-acym-linked="<?php echo empty($licenseKey) ? 0 : 1; ?>">
147 <?php echo acym_translation(empty($licenseKey) ? 'ACYM_ATTACH_MY_LICENSE' : 'ACYM_UNLINK_MY_LICENSE'); ?>
148 </button>
149 </div>
150 <?php }
151 if (empty($licenseKey)) { ?>
152 <div class="cell acym_vcenter acym__config__acymailer__warning margin-top-1">
153 <i class="acymicon-exclamation-triangle acym__color__orange"></i>
154 <span class="margin-right-1">
155 <?php
156 $pricingPage = ACYM_ACYMAILING_WEBSITE.'pricing?utm_source=acymailing_plugin&utm_medium=sendingmethod&utm_campaign=purchase';
157 echo acym_translation(acym_level(ACYM_ESSENTIAL) ? 'ACYM_NO_LICENSE' : 'ACYM_NO_LICENSE_STARTER');
158 ?>
159 <a target="_blank" href="<?php echo $pricingPage; ?>"><?php echo acym_translation('ACYM_GET_A_LICENSE'); ?></a>
160 </span>
161 </div>
162 <?php } elseif (empty($acyMailerKey)) { ?>
163 <div class="cell acym_vcenter acym__config__acymailer__warning margin-top-1">
164 <i class="acymicon-exclamation-triangle acym__color__orange"></i>
165 <span>
166 <?php
167 $subscriptionsPage = ACYM_ACYMAILING_WEBSITE.'account/license?utm_source=acymailing_plugin&utm_medium=sendingmethod&utm_campaign=purchase';
168 echo acym_translation('ACYM_API_KEY_NOT_ALLOWING_METHOD');
169 ?>
170 <a target="_blank" href="<?php echo $subscriptionsPage; ?>"><?php echo acym_translation('ACYM_SWITCH_MY_LICENSE'); ?></a>
171 </span>
172 </div>
173
174 <div class="acym__configuration__acymailer__check-license cell grid-x">
175 <div class="cell"><?php echo acym_translation('ACYM_CHECK_SENDING_SERVICE_LICENSE'); ?></div>
176 <button
177 data-task="attachLicenseAcymailer"
178 id="acym__configuration__acymailer__verify-license"
179 class="cell medium-shrink button margin-left-0 margin-top-1 acy_button_submit">
180 <?php echo acym_translation('ACYM_CHECK_LICENSE'); ?>
181 </button>
182 </div>
183 <?php } else { ?>
184 <div class="cell grid-x">
185 <?php if (!empty($domainsWaiting)) { ?>
186 <div class="cell <?php echo empty($data['step']) ? 'large-8' : '' ?> grid-x acym_vcenter acym__config__acymailer__warning">
187 <i class="cell small-2 margin-right-0 acymicon-access-time acym__color__orange"></i>
188 <div class="cell small-10 grid-x">
189 <span class="cell"><?php echo acym_translation('ACYM_DOMAINS_WAITING_VALIDATION_ADD_CNAME'); ?></span>
190 <a href="<?php echo ACYM_DOCUMENTATION; ?>external-sending-method/acymailing-sending-service#how-to-add-the-dns-entries-on-my-server"
191 target="_blank"
192 class="cell">
193 <?php echo acym_translation('ACYM_CHECK_THIS_TUTORIAL'); ?>
194 </a>
195 </div>
196 </div>
197 <div class="cell <?php echo empty($data['step']) ? 'large-4' : '' ?> margin-top-1 margin-bottom-1">
198 <button id="acym__config__acymailer__update-domain-status"
199 type="button"
200 class="button button-secondary float-right"
201 sending-method-id="<?php echo self::SENDING_METHOD_ID; ?>">
202 <i class="acymicon-autorenew"></i><?php echo acym_translation('ACYM_UPDATE_DOMAIN_STATUS'); ?>
203 </button>
204 </div>
205 <?php } ?>
206 </div>
207 <div class="grid-x acym__listing cell">
208 <div class="grid-x cell acym__listing__header">
209 <div class="grid-x medium-auto small-11 cell acym__listing__header__title__container">
210 <div class="cell small-8 medium-auto acym__listing__header__title">
211 <?php echo acym_translation('ACYM_DOMAIN_NAME'); ?>
212 </div>
213 <div class="cell hide-for-small-only medium-2 acym__listing__header__title text-center">
214 <?php echo acym_translation('ACYM_STATUS'); ?>
215 </div>
216 <div class="cell hide-for-small-only medium-2 acym__listing__header__title text-center">
217 <?php echo acym_translation('ACYM_BOUNCE_RATE').acym_info('ACYM_BOUNCE_RATE_DESC'); ?>
218 </div>
219 <div class="cell hide-for-small-only medium-2 acym__listing__header__title text-center">
220 <?php echo acym_translation('ACYM_COMPLAINT_RATE').acym_info('ACYM_COMPLAINT_RATE_DESC'); ?>
221 </div>
222 <div class="cell small-4 medium-2 acym__listing__header__title text-center">
223 <?php echo acym_translation('ACYM_ACTIONS'); ?>
224 </div>
225 </div>
226 </div>
227 <?php if (empty($domains)) { ?>
228 <div class="grid-x cell margin-top-1 align-center">
229 <?php echo acym_translation('ACYM_NO_DOMAINS_YET'); ?>
230 </div>
231 <?php } else {
232 foreach ($domains as $domain) {
233 $bounceRateParams = $this->getRateColor(
234 empty($domain['bounce_rate']) ? 0 : $domain['bounce_rate'],
235 empty($domain['allowed_bounce_rate']) ? 0 : $domain['allowed_bounce_rate'],
236 empty($domain['warning_bounce_rate']) ? 0 : $domain['warning_bounce_rate']
237 );
238 $complaintRateParams = $this->getRateColor(
239 empty($domain['complaint_rate']) ? 0 : $domain['complaint_rate'],
240 empty($domain['allowed_complaint_rate']) ? 0 : $domain['allowed_complaint_rate'],
241 empty($domain['warning_complaint_rate']) ? 0 : $domain['warning_complaint_rate']
242 );
243 ?>
244 <div acym-data-domain="<?php echo $domain['domain'] ?>" class="grid-x cell align-middle acym__listing__row">
245 <div class="cell small-6 medium-auto grid-x acym__listing__title__container">
246 <?php echo acym_escape($domain['domain']); ?>
247 </div>
248 <div class="cell small-1 medium-2 grid-x acym__listing__title__container align-center">
249 <?php
250 switch ($domain['status']) {
251 case 'SUCCESS':
252 $iconClass = 'acymicon-check-circle acym__color__green';
253 $tooltipText = acym_translation('ACYM_VALIDATED');
254 break;
255 case 'FAILED':
256 $iconClass = 'acymicon-close acym__color__red notValidated';
257 $tooltipText = acym_translation('ACYM_APPROVAL_FAILED');
258 break;
259 default:
260 $iconClass = 'acymicon-access-time acym__color__orange notValidated';
261 $tooltipText = acym_translation('ACYM_A_CNAME_MISSING');
262 }
263 echo acym_tooltip(
264 [
265 'hoveredText' => '<i class="acym__config__acymailer__status__icon '.$iconClass.'"></i>',
266 'textShownInTooltip' => $tooltipText,
267 ]
268 );
269 ?>
270 </div>
271 <div class="cell hide-for-small-only medium-2 grid-x acym__listing__title__container align-center <?php echo $bounceRateParams['color']; ?>">
272 <?php echo empty($domain['bounce_rate']) ? '-' : round($domain['bounce_rate'], 2).'%';
273 echo $bounceRateParams['icon'];
274 ?>
275 </div>
276 <div class="cell hide-for-small-only medium-2 grid-x acym__listing__title__container align-center <?php echo $complaintRateParams['color']; ?>">
277 <?php echo empty($domain['complaint_rate']) ? '-' : round($domain['complaint_rate'], 2).'%';
278 echo $complaintRateParams['icon'];
279 ?>
280 </div>
281 <div class="cell small-4 medium-2 grid-x margin-left-1 medium-margin-left-0 acym__listing__title__container align-center">
282 <?php ob_start(); ?>
283 <div class="cell grid-x acym__config__acymailer__cname__modal">
284 <h6 class="cell text-center margin-top-2 margin-bottom-1"><?php echo acym_translation('ACYM_DNS_ENTRIES'); ?></h6>
285 <div class="grid-x cell align-center margin-top-1 margin-bottom-2 acym_vcenter">
286 <p class="cell shrink"><?php echo acym_translation('ACYM_DO_NOT_KNOW_HOW_DO_IT'); ?> </p>
287 <a href="<?php echo ACYM_DOCUMENTATION; ?>external-sending-method/acymailing-sending-service#how-to-add-the-dns-entries-on-my-server"
288 class="cell shrink acym__config__acymailer__cname__modal__link"
289 target="_blank">
290 <?php echo acym_translation('ACYM_STEP_BY_STEP_GUIDE'); ?>
291 </a>
292 </div>
293 <div class="grid-x acym__listing cell">
294 <div class="grid-x acym__listing cell">
295 <div class="cell grid-x grid-margin-x margin-left-0 padding-bottom-1 acym__listing__header">
296 <div class="cell small-10 hide-for-medium acym__listing__header__title">
297 <?php echo acym_translation('ACYM_NAME').' / '.acym_translation('ACYM_VALUE'); ?>
298 </div>
299 <div class="cell small-5 show-for-medium acym__listing__header__title">
300 <?php echo acym_translation('ACYM_NAME'); ?>
301 </div>
302 <div class="cell small-5 show-for-medium acym__listing__header__title">
303 <?php echo acym_translation('ACYM_VALUE'); ?>
304 </div>
305 <div class="cell small-2 acym__listing__header__title text-center">
306 <?php echo acym_translation('ACYM_STATUS'); ?>
307 </div>
308 </div>
309 <?php
310 foreach ($domain['CnameRecords'] as $cnameRecord) {
311 if ($this->checkCnameEntry($cnameRecord['name'], $cnameRecord['value'])) {
312 $cnameStatus = '<i class="acym__config__acymailer__status__icon acymicon-check-circle acym__color__green"></i>';
313 } else {
314 $cnameStatus = acym_tooltip(
315 [
316 'hoveredText' => '<i class="acym__config__acymailer__status__icon acymicon-close acym__color__red"></i>',
317 'textShownInTooltip' => implode('<br/>', $this->cnameErrors),
318 ]
319 );
320 $this->cnameErrors = [];
321 }
322 ?>
323 <div class="cell grid-x grid-margin-x margin-left-0 align-middle acym__listing__row">
324 <div class="cell small-11 medium-5 cname-name">
325 <?php echo $cnameRecord['name']; ?>
326 </div>
327 <div class="cell small-1 hide-for-medium cname-value">
328 <?php echo $cnameStatus; ?>
329 </div>
330 <div class="cell small-11 medium-5 cname-value">
331 <?php echo $cnameRecord['value']; ?>
332 </div>
333 <div class="cell medium-2 show-for-medium text-center">
334 <?php echo $cnameStatus; ?>
335 </div>
336 </div>
337 <?php } ?>
338 </div>
339 </div>
340 </div>
341 <?php
342 $modalContent = ob_get_clean();
343 $buttonModal = acym_tooltip(
344 [
345 'hoveredText' => '<i class="acymicon-cogs acym__config__acymailer__domain--settings cursor-pointer acym__color__blue" acym-data-domain="'.$domain['domain'].'"></i>',
346 'textShownInTooltip' => acym_translation('ACYM_SHOW_DNS_SETTINGS'),
347 ]
348 );
349 echo acym_modal(
350 $buttonModal,
351 $modalContent,
352 null,
353 '',
354 '',
355 true,
356 true,
357 'acym__config__acymailer__cname__modal__container'
358 );
359
360 echo acym_tooltip(
361 [
362 'hoveredText' => '<i class="acymicon-delete acym__config__acymailer__domain--delete cursor-pointer" acym-data-domain="'.acym_escape(
363 $domain['domain']
364 ).'"></i>',
365 'textShownInTooltip' => acym_translation('ACYM_DELETE'),
366 ]
367 );
368 ?>
369 </div>
370 </div>
371 <?php } ?>
372 <?php } ?>
373 </div>
374 <div class="cell grid-x acym_vcenter acym__sending__methods__one__settings padding-top-1">
375 <div class="cell grid-x">
376 <div class="cell small-7 medium-4 large-3">
377 <input id="<?php echo self::SENDING_METHOD_ID; ?>_domain"
378 class="cell medium-6 large-4 xlarge-3"
379 type="text"
380 autocomplete="off"
381 value="">
382 <span id="<?php echo self::SENDING_METHOD_ID; ?>_domain_error" class="medium-6 large-4 xlarge-3"></span>
383 <?php
384 if (!empty($unverifiedDomains)) { ?>
385 <span id="acym__acymailer__unverifiedDomains">
386 <?php foreach ($unverifiedDomains as $oneDomain) { ?>
387 <span class="acym__acymailer__oneSuggestion"><?php echo $oneDomain; ?></span>
388 <?php } ?>
389 </span>
390 <?php } ?>
391 </div>
392 <div id="acym__configuration__sending__method_addDomain_submit" class="cell grid-x small-4 medium-6 large-8 margin-left-1 acym_vcenter">
393 <button type="button"
394 id="acym__configuration__sending__method-addDomain"
395 class="cell shrink button button-secondary">
396 <?php echo acym_translation('ACYM_ADD_A_DOMAIN'); ?>
397 </button>
398 <i class="margin-left-1 acym_vcenter acymicon-circle-o-notch acymicon-spin is-hidden"
399 id="acym__configuration__sending__method_add_domain-wait"></i>
400 <div class="cell shrink grid-x acym_vcenter" id="acym__configuration__acymailer__add__error">
401 <i class="acymicon-close acym__color__red cell shrink"></i>
402 <span class="cell shrink" id="acym__configuration__acymailer__add__error__message"></span>
403 </div>
404 </div>
405 </div>
406 </div>
407 <?php if (!$this->isLogFileEmpty()) { ?>
408 <div class="cell grid-x acym__sending__methods__log">
409 <?php
410 echo acym_modal(
411 acym_translation('ACYM_REPORT_SEE'),
412 '',
413 null,
414 '',
415 [
416 'class' => 'button',
417 'data-ajax' => 'true',
418 'data-iframe' => '&ctrl=configuration&task=seeLogs&filename='.$this->logFilename,
419 ]
420 );
421 ?>
422 </div>
423 <?php } ?>
424 <?php } ?>
425 </div>
426 </div>
427 <?php
428 $data['sendingMethodsHtmlSettings'][self::SENDING_METHOD_ID] = ob_get_clean();
429 }
430
431 public function onAcymTestCredentialSendingMethod($sendingMethod, $credentials)
432 {
433 if ($sendingMethod !== self::SENDING_METHOD_ID) return;
434
435 if (empty($credentials[self::SENDING_METHOD_ID.'_apikey'])) {
436 acym_sendAjaxResponse(acym_translation('ACYM_MISSING_API_KEY'), [], false);
437 }
438
439 $response = $this->callApiSendingMethod(
440 'get_credits',
441 [],
442 [
443 'API-KEY' => $credentials[self::SENDING_METHOD_ID.'_apikey'],
444 ]
445 );
446
447 if (empty($response)) {
448 $errorMsg = acym_translation('ACYM_NO_ANSWER');
449 acym_sendAjaxResponse(acym_translationSprintf('ACYM_ERROR_OCCURRED_WHILE_CALLING_API', $errorMsg), [], false);
450 } elseif (!empty($response['error_curl'])) {
451 acym_sendAjaxResponse(acym_translationSprintf('ACYM_ERROR_OCCURRED_WHILE_CALLING_API', $response['error_curl']), [], false);
452 } elseif (!empty($response['message']) && $response['message'] == 'Invalid private key') {
453 acym_sendAjaxResponse(acym_translation('ACYM_AUTHENTICATION_FAILS_WITH_API_KEY'), [], false);
454 } elseif (!empty($response['message']) && !$this->checkSuccessCode($this->responseCode)) {
455 if ($this->responseCode === 401) {
456 acym_sendAjaxResponse(
457 acym_translationSprintf(
458 'ACYM_SENDING_METHOD_ERROR_WHILE_ACTION',
459 self::SENDING_METHOD_NAME,
460 acym_translation('ACYM_GETTING_REMAINING_CREDITS'),
461 $response['message']
462 ),
463 [],
464 false
465 );
466 }
467 acym_sendAjaxResponse($response['message'], [], false);
468 } else {
469 acym_sendAjaxResponse(acym_translation('ACYM_API_KEY_CORRECT'));
470 }
471 }
472
473 public function onAcymProcessQueueExternalSendingCampaign(&$externalSending, $transactional = false)
474 {
475 if ($this->config->get('mailer_method') == self::SENDING_METHOD_ID) $externalSending = false;
476 }
477
478 public function onAcymSendEmail(&$response, $mailerHelper, $to, $from, $replyTo, $bcc = [], $attachments = [], $sendingMethodListParams = [])
479 {
480 if ($mailerHelper->externalMailer !== self::SENDING_METHOD_ID) {
481 return;
482 }
483
484 $apikey = $this->config->get(self::SENDING_METHOD_ID.'_apikey');
485 if (empty($apikey)) {
486 $mailerHelper->failedCounting = false;
487 $response['error'] = true;
488 $response['message'] = acym_translation('ACYM_MISSING_API_KEY');
489
490 return;
491 }
492
493 if ($this->isUnsubscribeLinkMissing($mailerHelper)) {
494 $mailerHelper->failedCounting = false;
495 $response['error'] = true;
496 $response['message'] = acym_translation('ACYM_MISSING_UNSUBSCRIBE_LINK');
497
498 return;
499 }
500
501 $domainsUsed = [
502 acym_getDomain($from['email']),
503 acym_getDomain($replyTo['email']),
504 ];
505 $bounceAddress = $this->getBounceAddress($mailerHelper);
506 if (!empty($bounceAddress)) {
507 $domainsUsed[] = acym_getDomain($bounceAddress);
508 }
509
510 $domainsUsed = array_unique($domainsUsed);
511
512 $verifiedDomains = $this->getVerifiedDomains();
513
514 $unverifiedDomains = array_diff($domainsUsed, $verifiedDomains);
515 if (!empty($unverifiedDomains)) {
516 $mailerHelper->failedCounting = false;
517 $response['error'] = true;
518 $response['message'] = acym_translationSprintf('ACYM_UNVERIFIED_DOMAINS_PREVENTING_EMAILS_FROM_BEING_SENT_X', implode(', ', $unverifiedDomains));
519
520 return;
521 }
522
523 $responseMailer = $this->callApiSendingMethod(
524 'send',
525 [
526 'email' => $mailerHelper->getSentMIMEMessage(),
527 'domainsUsed' => $domainsUsed,
528 'isTransactional' => $mailerHelper->isTransactional,
529 'isOneTimeMail' => $mailerHelper->isOneTimeMail,
530 ],
531 [],
532 'POST'
533 );
534
535 if (!empty($responseMailer['logs'])) {
536 acym_logError($responseMailer['logs'], self::SENDING_METHOD_ID);
537 }
538
539 if (!empty($responseMailer['error_curl'])) {
540 $mailerHelper->failedCounting = false;
541 $response['error'] = true;
542 $response['message'] = acym_translationSprintf('ACYM_ERROR_OCCURRED_WHILE_CALLING_API', $responseMailer['error_curl']);
543 } elseif (!$this->checkSuccessCode($this->responseCode)) {
544 $response['error'] = true;
545 $response['message'] = $this->translate($responseMailer);
546
547 if ($response['message'] === acym_translation('ACYM_NO_CREDITS_LEFT')) {
548 $response['message'] = acym_translation('ACYM_NOT_ENOUGH_CREDITS').' : ';
549 $response['message'] .= '<a target="_blank" class="acym__color__blue" href="'.ACYM_ACYMAILING_WEBSITE.'">';
550 $response['message'] .= acym_translation('ACYM_GET_MORE_CREDITS');
551 $response['message'] .= '</a>';
552 }
553
554 if (!empty($responseMailer['code']) && in_array($responseMailer['code'], [18, 26, 28])) {
555 $mailerHelper->failedCounting = false;
556 }
557
558 if ($responseMailer['code'] == 26) {
559 $queueClass = new QueueClass();
560 $queueClass->delayAll(24);
561 }
562 } else {
563 $response['error'] = false;
564 }
565 }
566
567 public function replaceUserInformation(&$email, &$user, $send = true)
568 {
569 if (empty($email->externalMailer) || $email->externalMailer !== self::SENDING_METHOD_ID) return;
570
571 $bounceAddress = $this->getBounceAddress($email);
572
573 if (!empty($bounceAddress) && method_exists($email, 'addCustomHeader')) {
574 $email->addCustomHeader('Return-Path', $bounceAddress);
575 }
576 }
577
578 public function ajaxCheckDomain()
579 {
580 $sendingMethod = acym_getVar('string', 'sendingMethod', '');
581 if ($sendingMethod != self::SENDING_METHOD_ID) {
582 acym_sendAjaxResponse();
583 }
584
585 $domains = json_decode($this->config->get(self::SENDING_METHOD_ID.'_domains', '[]'), true);
586 if (empty($domains)) {
587 acym_sendAjaxResponse();
588 }
589
590 $remainingDomains = $this->checkDomainsDNS($domains);
591
592 if (empty($remainingDomains)) {
593 acym_sendAjaxResponse('', ['domains' => $domains]);
594 }
595
596 $prepareDomains = array_map(
597 function ($domain) {
598 return $domain['domain'];
599 },
600 $remainingDomains
601 );
602
603 $responseApi = $this->callApiSendingMethod(
604 'getDomainStatus',
605 ['domains' => $prepareDomains],
606 [],
607 'POST'
608 );
609
610 if (empty($responseApi)) {
611 acym_sendAjaxResponse('', ['domains' => $domains]);
612 }
613
614 if (!$this->checkSuccessCode($this->responseCode)) {
615 acym_sendAjaxResponse(acym_translation('ACYM_ERROR_ON_CALL_ACYBA_WEBSITE').': '.$responseApi['message'], ['domains' => $domains], false);
616 }
617
618 $errorDomains = [];
619 foreach ($domains as $key => $oneDomain) {
620 $domainName = $oneDomain['domain'];
621 if (!array_key_exists($domainName, $responseApi['data']) || !is_array($responseApi['data'][$domainName])) {
622 $errorDomains[] = acym_translation('ACYM_ERROR_ON_CALL_ACYBA_WEBSITE').': '.$responseApi['data'][$domainName].': '.$domainName;
623 continue;
624 }
625
626 if (empty($responseApi['data'][$domainName]['code'])) {
627 $domains[$key] = array_merge($domains[$key], $responseApi['data'][$domainName]);
628 continue;
629 }
630
631 if (!empty(self::TRANSLATIONS[$responseApi['data'][$domainName]['code']])) {
632 $message = self::TRANSLATIONS[$responseApi['data'][$domainName]['code']];
633 } else {
634 if (empty($responseApi['data'][$domainName]['message'])) {
635 $message = 'ACYM_DOMAIN_DEFAULT_ERROR';
636 } else {
637 $message = $this->displayMessage($responseApi['data'][$domainName]['message']);
638 }
639 }
640 acym_enqueueMessage(
641 acym_translation('ACYM_ERROR_ON_CALL_ACYBA_WEBSITE').': '.acym_translationSprintf(
642 $message,
643 $domainName
644 ),
645 'error'
646 );
647
648 if (!empty($responseApi['data'][$domainName]['logs'])) {
649 acym_logError($responseApi['data'][$domainName]['logs'], self::SENDING_METHOD_ID);
650 }
651 }
652
653 $this->config->save([self::SENDING_METHOD_ID.'_domains' => json_encode($domains)]);
654
655 if (!empty($errorDomains)) {
656 acym_sendAjaxResponse(implode(', ', $errorDomains), [], false);
657 }
658
659 acym_sendAjaxResponse('', ['domains' => $domains]);
660 }
661
662 public function onAcymDeleteDomain()
663 {
664 $oneDomain = acym_getVar('string', 'oneDomain', '');
665
666 if (empty($oneDomain)) {
667 return;
668 }
669
670 $apikey = $this->config->get(self::SENDING_METHOD_ID.'_apikey');
671 if (empty($apikey)) {
672 acym_sendAjaxResponse(acym_translation('ACYM_MISSING_API_KEY'), [], false);
673 }
674
675 $responseApi = $this->callApiSendingMethod(
676 'deleteDomainIdentity',
677 ['domain' => $oneDomain, 'siteUrl' => acym_baseURI()],
678 [],
679 'POST'
680 );
681
682 if (!empty($responseApi['error_curl'])) {
683 $message = acym_translationSprintf('ACYM_ERROR_OCCURRED_WHILE_CALLING_API', $responseApi['error_curl']);
684 acym_sendAjaxResponse($message, [], false);
685 } elseif (!empty($responseApi['message']) && $responseApi['message'] === 'Invalid private key') {
686 acym_sendAjaxResponse(acym_translation('ACYM_AUTHENTICATION_FAILS_WITH_API_KEY'), [], false);
687 } elseif (!$this->checkSuccessCode($this->responseCode) && (empty($responseApi['code']) || !in_array($responseApi['code'], [5, 4, 3]))) {
688
689 $message = acym_translation('ACYM_ERROR_ON_CALL_ACYBA_WEBSITE').': '.$this->translate($responseApi);
690 if (!empty($responseApi['logs'])) {
691 acym_logError($responseApi['logs'], self::SENDING_METHOD_ID);
692 }
693
694 acym_sendAjaxResponse($message, [], false);
695 } else {
696 $field = self::SENDING_METHOD_ID.'_domains';
697 $domains = json_decode($this->config->get($field, '[]'), true);
698 $domains = array_filter($domains, function ($domain) use ($oneDomain) {
699 return $domain['domain'] != $oneDomain;
700 });
701
702 $newConfig = new \stdClass();
703 $newConfig->$field = json_encode($domains);
704 $this->config->save($newConfig);
705
706 acym_sendAjaxResponse();
707 }
708 }
709
710 public function ajaxAddDomain(): void
711 {
712 $oneDomain = acym_getVar('string', 'oneDomain', '');
713
714 $this->config->save(['mailer_method' => self::SENDING_METHOD_ID]);
715
716 if (empty($oneDomain)) {
717 acym_sendAjaxResponse(acym_translation('ACYM_MISSING_DOMAIN'), [], false);
718 }
719
720 $oneDomain = acym_strtolower($oneDomain);
721
722 $apikey = $this->config->get(self::SENDING_METHOD_ID.'_apikey');
723 if (empty($apikey)) {
724 acym_sendAjaxResponse(acym_translation('ACYM_MISSING_API_KEY'), [], false);
725 }
726
727 $domainValidation = preg_match('/^(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z0-9][a-z0-9-]{0,61}[a-z0-9]$/u', $oneDomain);
728 if (!$domainValidation) {
729 $message = acym_translationSprintf('ACYM_THE_DOMAIN_X_IS_NOT_VALID', $oneDomain);
730 acym_sendAjaxResponse($message, ['type' => 'DOMAIN_VALIDATION'], false);
731 }
732
733 $field = self::SENDING_METHOD_ID.'_domains';
734 $domains = $this->config->get($field, []);
735
736 if (!empty($domains)) {
737 $domains = @json_decode($domains, true);
738 }
739
740 if (!empty($domains[$oneDomain])) {
741 acym_sendAjaxResponse(acym_translation('ACYM_DOMAIN_ALREADY_SENT'), [], false);
742 }
743
744 $responseApi = $this->callApiSendingMethod(
745 'createDomainIdentity',
746 ['domain' => $oneDomain, 'siteUrl' => acym_baseURI()],
747 [],
748 'POST'
749 );
750
751 if (!empty($responseApi['error_curl'])) {
752 $message = acym_translationSprintf('ACYM_ERROR_OCCURRED_WHILE_CALLING_API', $responseApi['error_curl']);
753 acym_sendAjaxResponse($message, [], false);
754 } elseif (!empty($responseApi['message']) && $responseApi['message'] === 'Invalid API-KEY') {
755 acym_sendAjaxResponse(acym_translation('ACYM_AUTHENTICATION_FAILS_WITH_API_KEY'), [], false);
756 } elseif (!$this->checkSuccessCode($this->responseCode)) {
757 if (empty($responseApi['code']) || empty(self::TRANSLATIONS[$responseApi['code']])) {
758 $errorCodeTranslationKey = empty($responseApi['message']) ? 'ACYM_DOMAIN_DEFAULT_ERROR' : $this->displayMessage($responseApi['message']);
759 } else {
760 $errorCodeTranslationKey = self::TRANSLATIONS[$responseApi['code']];
761 }
762 $message = acym_translationSprintf($errorCodeTranslationKey, $oneDomain);
763 acym_sendAjaxResponse($message, [], false);
764 } elseif ($this->responseCode === 201) {
765 $domains[$oneDomain] = [
766 'domain' => $oneDomain,
767 'CnameRecords' => $responseApi['cnameRecords'],
768 'status' => 'PENDING',
769 ];
770 $this->config->save([$field => json_encode($domains)]);
771 acym_sendAjaxResponse($this->translate($responseApi), ['cnameRecords' => $responseApi['cnameRecords']]);
772 } else {
773 $cnameRecords = $responseApi['data'][$oneDomain]['cnameRecords'];
774 $status = $responseApi['data'][$oneDomain]['status'];
775 $domains[$oneDomain] = [
776 'domain' => $oneDomain,
777 'CnameRecords' => $cnameRecords,
778 'status' => $status,
779 ];
780 $this->config->save([$field => json_encode($domains)]);
781
782 acym_sendAjaxResponse(
783 $this->translate($responseApi),
784 ['cnameRecords' => $cnameRecords, 'alreadyVerified' => $status === 'SUCCESS']
785 );
786 }
787 }
788
789 public function onAcymDisplayPage()
790 {
791 if (intval($this->config->get('walk_through', 0)) === 1) {
792 return;
793 }
794
795 $unverifiedDomains = $this->getDomainsUnVerified();
796
797 if (!empty($unverifiedDomains)) {
798 $message = acym_translationSprintf('ACYM_UNVERIFIED_DOMAINS_PREVENTING_EMAILS_FROM_BEING_SENT_X', implode(', ', $unverifiedDomains));
799 $notification = [
800 'name' => 'unverified_domains',
801 'removable' => 0,
802 ];
803
804 if (acym_getVar('string', 'page') === 'acymailing_dashboard' || acym_getVar('string', 'ctrl') === 'dashboard') {
805 acym_enqueueMessage($message, 'warning', false, [$notification], false);
806 } else {
807 acym_enqueueMessage($message, 'warning', true, [$notification]);
808 }
809 } else {
810 acym_removeDashboardNotification('unverified_domains');
811 }
812 }
813
814 public function onAcymGetCreditRemainingSendingMethod(&$html, $reloading = false)
815 {
816 $sendingMethod = $this->config->get('mailer_method', '');
817 if (empty($sendingMethod) || $sendingMethod != self::SENDING_METHOD_ID) return;
818
819 $apiKey = $this->config->get(self::SENDING_METHOD_ID.'_apikey', '');
820 if (empty($apiKey)) return;
821
822 $response = $this->getRemainingCredits($reloading);
823
824 if (!isset($response['remaining_credits'])) {
825 if (empty($this->translate($response))) {
826 $html = acym_translation('ACYM_ERROR_CONTACT_ACYMAILING');
827 } else {
828 $html = acym_translationSprintf(
829 'ACYM_SENDING_METHOD_ERROR_WHILE_ACTION',
830 self::SENDING_METHOD_NAME,
831 acym_translation('ACYM_GETTING_REMAINING_CREDITS'),
832 $this->translate($response)
833 );
834 }
835
836 return;
837 }
838
839 $unityTranslation = 'ACYM_CREDITS_REMAINING';
840 $creditsShowed = $response['remaining_credits'];
841
842 if (!empty($response['is_multisite'])) {
843 $fromEmail = $this->config->get('from_email', '');
844 $domain = explode('@', $fromEmail)[1];
845
846 if (empty($domain) || empty($response['domains'][$domain])) {
847 $html = acym_translation('ACYM_DOMAIN_FROM_EMAIL_NOT_VALID_ASS');
848 } else {
849 $domainData = $response['domains'][$domain];
850 if ($domainData['is_limited']) {
851 $creditsShowed = $domainData['remaining_credits'];
852 } else {
853 $creditsShowed = $domainData['credits_used'];
854 $unityTranslation = 'ACYM_CREDITS_USED';
855 }
856 }
857 }
858
859 if (empty($creditsShowed)) {
860 $creditsShowed = '0';
861 }
862 $html = acym_translationSprintf(
863 'ACYM_SENDING_METHOD_X_UNITY',
864 self::SENDING_METHOD_NAME,
865 acym_tooltip(
866 [
867 'hoveredText' => $creditsShowed,
868 'textShownInTooltip' => acym_translation('ACYM_GET_MORE_CREDITS'),
869 'classContainer' => 'credits_remaining',
870 'link' => ACYM_ACYMAILING_WEBSITE,
871 ]
872 ),
873 '<span class="acym_not_bold">'.acym_translation($unityTranslation).'</span>'
874 );
875 }
876
877 public function onAcymCreditsLeft(&$creditsLeft)
878 {
879 $sendingMethod = $this->config->get('mailer_method', '');
880 if (empty($sendingMethod) || $sendingMethod != self::SENDING_METHOD_ID) return;
881
882 $apiKey = $this->config->get(self::SENDING_METHOD_ID.'_apikey', '');
883 if (empty($apiKey)) {
884 $creditsLeft = 0;
885
886 return;
887 }
888
889 $credits = $this->getRemainingCredits(true);
890 if (empty($credits['remaining_credits'])) {
891 $creditsLeft = 0;
892 } else {
893 $creditsLeft = (int)$credits['remaining_credits'];
894 }
895 }
896
897 public function onAcymAttachLicense($licenseKey)
898 {
899 if (empty($licenseKey)) {
900 return;
901 }
902
903 $response = $this->callApiSendingMethod(self::SENDING_METHOD_API_URL.'public/licenses/'.$licenseKey);
904
905 if (!empty($response['id'])) {
906 $this->config->save([self::SENDING_METHOD_ID.'_apikey' => $response['id']]);
907 }
908 }
909
910 public function onAcymDetachLicense()
911 {
912 $this->config->save([self::SENDING_METHOD_ID.'_apikey' => '']);
913 }
914
915 public function onAcymCampaignSummary(&$data)
916 {
917 if ($this->config->get('mailer_method') !== self::SENDING_METHOD_ID) {
918 return;
919 }
920
921 $mail = $data['mailClass']->getOneById($data['mailId']);
922 if (empty($mail->body) || !$this->isContainingUnsubscribeLink($mail->body)) {
923 $data['notAllowedSendingError'] = acym_translation('ACYM_UNSUB_LINK');
924 }
925
926 $unverifiedDomains = $this->getDomainsUnVerified();
927 if (!empty($unverifiedDomains)) {
928 $data['notAllowedSendingError'] = acym_translationSprintf(
929 'ACYM_UNVERIFIED_DOMAINS_PREVENTING_EMAILS_FROM_BEING_SENT_X',
930 implode(', ', $unverifiedDomains)
931 );
932 }
933 }
934
935 private function getDomainsUnVerified(): array
936 {
937 if ($this->config->get('mailer_method') !== self::SENDING_METHOD_ID) {
938 return [];
939 }
940
941 $allDomains = [];
942
943 $allDomains[] = acym_getDomain($this->config->get('from_email'));
944 if ($this->config->get('from_as_replyto') === '0') {
945 $allDomains[] = acym_getDomain($this->config->get('replyto_email'));
946 }
947
948 if ($this->config->get('multilingual') === '1') {
949 $senderInfoTranslation = $this->config->get('sender_info_translation');
950 if (!empty($senderInfoTranslation)) {
951 $senderInfoTranslation = json_decode($senderInfoTranslation, true);
952 foreach ($senderInfoTranslation as $oneSenderInfo) {
953 $allDomains[] = acym_getDomain($oneSenderInfo['from_email']);
954 $allDomains[] = acym_getDomain($oneSenderInfo['replyto_email']);
955 }
956 }
957 }
958
959 $allDomains[] = acym_getDomain($this->config->get('bounce_email'));
960 $allDomains = array_filter(array_unique($allDomains));
961
962 $verifiedDomains = $this->getVerifiedDomains();
963
964 return array_diff($allDomains, $verifiedDomains);
965 }
966
967 private function getRateColor($rate, $allowedRate, $warningRate): array
968 {
969 if (empty($rate) || empty($allowedRate) || empty($warningRate)) {
970 return ['color' => '', 'icon' => ''];
971 }
972
973 if ($rate > $allowedRate) {
974 return [
975 'color' => 'acym__color__red',
976 'icon' => acym_tooltip(
977 [
978 'hoveredText' => '<i class="acym__config__acymailer__rate-status__icon acymicon-close acym__color__red"></i>',
979 'textShownInTooltip' => acym_translation('ACYM_RATE_BLOCKED'),
980 ]
981 ),
982 ];
983 } elseif ($rate >= $warningRate) {
984 return [
985 'color' => 'acym__color__orange',
986 'icon' => acym_tooltip(
987 [
988 'hoveredText' => '<i class="acym__config__acymailer__rate-status__icon acymicon-exclamation-triangle acym__color__orange"></i>',
989 'textShownInTooltip' => acym_translation('ACYM_RATE_WARNING'),
990 ]
991 ),
992 ];
993 }
994
995 return ['color' => '', 'icon' => ''];
996 }
997
998 private function updateDomainRates($domainsRates)
999 {
1000 $domains = $this->config->get(self::SENDING_METHOD_ID.'_domains', []);
1001
1002 if (empty($domains)) {
1003 return;
1004 }
1005
1006 $domains = @json_decode($domains, true);
1007
1008 foreach ($domainsRates as $oneDomain => $oneRate) {
1009 if (empty($domains[$oneDomain])) continue;
1010 foreach ($oneRate as $rateKey => $rateValue) {
1011 $domains[$oneDomain][$rateKey] = $rateValue;
1012 }
1013 }
1014
1015 $this->config->save([self::SENDING_METHOD_ID.'_domains' => json_encode($domains)]);
1016 }
1017
1018 private function getVerifiedDomains(): array
1019 {
1020 $verifiedDomains = [];
1021 $domainStatuses = json_decode($this->config->get(self::SENDING_METHOD_ID.'_domains', '[]'), true);
1022 if (!empty($domainStatuses)) {
1023 foreach ($domainStatuses as $domain => $info) {
1024 if ($info['status'] === 'SUCCESS') {
1025 $verifiedDomains[] = $domain;
1026 }
1027 }
1028 }
1029
1030 return $verifiedDomains;
1031 }
1032
1033 private function displayMessage($message): string
1034 {
1035 $correspondances = [
1036 'AlreadyExistsException' => 'ACYM_DOMAIN_X_ALREADY_EXIST',
1037 'TooManyRequestsException' => 'ACYM_DOMAIN_TO_MANY_REQUEST',
1038 'NotFoundException' => 'ACYM_DOMAIN_NOT_FOUND',
1039 'NotExistException' => 'ACYM_CANT_DELETE_DOMAIN',
1040 ];
1041
1042 if (empty($message) || empty($correspondances[$message])) {
1043 return 'ACYM_DOMAIN_DEFAULT_ERROR';
1044 }
1045
1046 return $correspondances[$message];
1047 }
1048
1049 private function getRemainingCredits($forceReload = false)
1050 {
1051 $time = time();
1052 $lastCheck = $this->config->get(self::SENDING_METHOD_ID.'_last_credits_check', 0);
1053 $lastDetails = $this->config->get(self::SENDING_METHOD_ID.'_credits_details', []);
1054
1055 if (!$forceReload && !empty($lastDetails) && $lastCheck > $time - self::CREDITS_RELOAD_DELAY) {
1056 return json_decode($lastDetails, true);
1057 }
1058
1059 $response = $this->callApiSendingMethod('get_credits');
1060
1061 $this->config->save([
1062 self::SENDING_METHOD_ID.'_credits_details' => json_encode($response),
1063 self::SENDING_METHOD_ID.'_last_credits_check' => $time,
1064 ]);
1065
1066 if (!empty($response['domains'])) {
1067 $this->updateDomainRates($response['domains']);
1068 }
1069
1070 return $response;
1071 }
1072
1073 private function checkSuccessCode($responseCode): bool
1074 {
1075 $successCodes = [200, 201, 204];
1076
1077 return in_array($responseCode, $successCodes);
1078 }
1079
1080 private function translate($response)
1081 {
1082 if (!isset($response['code']) && empty($response['message'])) {
1083 return '';
1084 }
1085
1086 $correspondence = '';
1087 $messageData = '';
1088
1089
1090 if (isset($response['code']) && !empty(self::TRANSLATIONS[$response['code']])) {
1091 $correspondence = self::TRANSLATIONS[$response['code']];
1092 }
1093
1094 if (!empty($response['messageData'])) {
1095 $messageData = $response['messageData'];
1096 }
1097
1098 if (empty($correspondence)) {
1099 if (empty($messageData)) {
1100 return $response['message'];
1101 }
1102
1103 return acym_translationVsprintf($response['message'], $messageData, false);
1104 }
1105
1106 if (empty($messageData)) {
1107 $finalMessage = acym_translation($correspondence);
1108 } else {
1109 $finalMessage = acym_translationVsprintf($correspondence, $messageData);
1110 }
1111
1112 if (in_array($response['code'], $this->errorCodes)) {
1113 $this->errors[] = $finalMessage;
1114 $this->errorCallback();
1115 }
1116
1117 return $finalMessage;
1118 }
1119
1120 private function isUnsubscribeLinkMissing($mailerHelper): bool
1121 {
1122 if ($mailerHelper->isTest || $mailerHelper->isForward || $mailerHelper->isSpamTest || empty($mailerHelper->mail)) {
1123 return false;
1124 }
1125
1126 if (in_array($mailerHelper->mail->type, MailClass::TYPES_TRANSACTIONAL) || $mailerHelper->mail->type === MailClass::TYPE_AUTOMATION) {
1127 return false;
1128 }
1129
1130 return !$this->isContainingUnsubscribeLink($mailerHelper->mail->body);
1131 }
1132
1133 private function isContainingUnsubscribeLink(string $text): bool
1134 {
1135 return strpos($text, '{unsubscribe}') !== false
1136 || strpos($text, '{unsubscribeall}') !== false
1137 || strpos($text, 'task=unsubscribe') !== false
1138 || strpos($text, 'frontusers/unsubscribe') !== false;
1139 }
1140
1141 private function checkDomainsDNS($domains): array
1142 {
1143 $remainingDomains = [];
1144 foreach ($domains as $oneDomain) {
1145 if (empty($oneDomain['CnameRecords'])) {
1146 $remainingDomains[] = $oneDomain;
1147 continue;
1148 }
1149
1150 if ($oneDomain['status'] == 'SUCCESS') {
1151 continue;
1152 }
1153
1154 foreach ($oneDomain['CnameRecords'] as $oneRecord) {
1155 if (!$this->checkCnameEntry($oneRecord['name'], $oneRecord['value'])) {
1156 $domainPosition = strpos($oneRecord['name'], '_domainkey') + 11;
1157 $domainName = substr($oneRecord['name'], $domainPosition);
1158 acym_sendAjaxResponse(acym_translation('ACYM_A_CNAME_MISSING'), ['domain' => $domainName], false);
1159 }
1160 }
1161
1162 $remainingDomains[] = $oneDomain;
1163 }
1164
1165 return $remainingDomains;
1166 }
1167
1168 private function checkCnameEntry(string $entryName, string $entryValue): bool
1169 {
1170 $domainPosition = strpos($entryName, '_domainkey') + 11;
1171 $domainName = substr($entryName, $domainPosition);
1172
1173 $dnsEntries = @dns_get_record($entryName, DNS_CNAME);
1174
1175 if (empty($dnsEntries)) {
1176 $entryName = substr($entryName, 0, $domainPosition);
1177 $doubleDomainEntry = $entryName.'.'.$domainName;
1178
1179 $dnsEntries = @dns_get_record($doubleDomainEntry, DNS_CNAME);
1180 if (!empty($dnsEntries)) {
1181 $this->cnameErrors[] = acym_translationSprintf('ACYM_ACYMAILER_MALFORMED_CNAME', $doubleDomainEntry);
1182 $this->cnameErrors[] = acym_translationSprintf('ACYM_ACYMAILER_CNAME_TRY_WITHOUT_DOMAIN', $entryName, $entryValue);
1183 } else {
1184 $this->cnameErrors[] = acym_translation('ACYM_WALK_ACYMAILER_STATUS_WAIT');
1185 }
1186
1187 return false;
1188 }
1189
1190 if (!is_array($dnsEntries)) {
1191 $dnsEntries = [$dnsEntries];
1192 }
1193
1194 foreach ($dnsEntries as $oneEntry) {
1195 if ($oneEntry['type'] !== 'CNAME' || $oneEntry['host'] !== $entryName) {
1196 continue;
1197 }
1198
1199 if (rtrim($oneEntry['target'], '.') === rtrim($entryValue, '.')) {
1200 return true;
1201 }
1202
1203 $this->cnameErrors[] = acym_translationSprintf('ACYM_DOMAIN_CHECK_INCORRECT_VALUE', $entryName, $domainName);
1204
1205 return false;
1206 }
1207
1208 $this->cnameErrors[] = acym_translation('ACYM_DNS_NOT_CNAME');
1209
1210 return false;
1211 }
1212 }
1213