PluginProbe
AcyMailing – An Ultimate Newsletter Plugin and Marketing Automation Solution for WordPress / 10.0.1
AcyMailing – An Ultimate Newsletter Plugin and Marketing Automation Solution for WordPress v10.0.1
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.0.1, at back/dynamics/acymailer/plugin.php

1,201 lines 51.6 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->config->get('bounce_email');
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->config->get('bounce_email');
572 if (!empty($bounceAddress) && method_exists($email, 'addCustomHeader')) {
573 $email->addCustomHeader('Return-Path', $bounceAddress);
574 }
575 }
576
577 public function ajaxCheckDomain()
578 {
579 $sendingMethod = acym_getVar('string', 'sendingMethod', '');
580 if ($sendingMethod != self::SENDING_METHOD_ID) {
581 acym_sendAjaxResponse();
582 }
583
584 $domains = json_decode($this->config->get(self::SENDING_METHOD_ID.'_domains', '[]'), true);
585 if (empty($domains)) {
586 acym_sendAjaxResponse();
587 }
588
589 $remainingDomains = $this->checkDomainsDNS($domains);
590
591 if (empty($remainingDomains)) {
592 acym_sendAjaxResponse('', ['domains' => $domains]);
593 }
594
595 $prepareDomains = array_map(
596 function ($domain) {
597 return $domain['domain'];
598 },
599 $remainingDomains
600 );
601
602 $responseApi = $this->callApiSendingMethod(
603 'getDomainStatus',
604 ['domains' => $prepareDomains],
605 [],
606 'POST'
607 );
608
609 if (empty($responseApi)) {
610 acym_sendAjaxResponse('', ['domains' => $domains]);
611 }
612
613 if (!$this->checkSuccessCode($this->responseCode)) {
614 acym_sendAjaxResponse(acym_translation('ACYM_ERROR_ON_CALL_ACYBA_WEBSITE').': '.$responseApi['message'], ['domains' => $domains], false);
615 }
616
617 $errorDomains = [];
618 foreach ($domains as $key => $oneDomain) {
619 $domainName = $oneDomain['domain'];
620 if (!array_key_exists($domainName, $responseApi['data']) || !is_array($responseApi['data'][$domainName])) {
621 $errorDomains[] = acym_translation('ACYM_ERROR_ON_CALL_ACYBA_WEBSITE').': '.$responseApi['data'][$domainName].': '.$domainName;
622 continue;
623 }
624
625 if (empty($responseApi['data'][$domainName]['code'])) {
626 $domains[$key] = array_merge($domains[$key], $responseApi['data'][$domainName]);
627 continue;
628 }
629
630 if (!empty(self::TRANSLATIONS[$responseApi['data'][$domainName]['code']])) {
631 $message = self::TRANSLATIONS[$responseApi['data'][$domainName]['code']];
632 } else {
633 if (empty($responseApi['data'][$domainName]['message'])) {
634 $message = 'ACYM_DOMAIN_DEFAULT_ERROR';
635 } else {
636 $message = $this->displayMessage($responseApi['data'][$domainName]['message']);
637 }
638 }
639 acym_enqueueMessage(
640 acym_translation('ACYM_ERROR_ON_CALL_ACYBA_WEBSITE').': '.acym_translationSprintf(
641 $message,
642 $domainName
643 ),
644 'error'
645 );
646
647 if (!empty($responseApi['data'][$domainName]['logs'])) {
648 acym_logError($responseApi['data'][$domainName]['logs'], self::SENDING_METHOD_ID);
649 }
650 }
651
652 $this->config->save([self::SENDING_METHOD_ID.'_domains' => json_encode($domains)]);
653
654 if (!empty($errorDomains)) {
655 acym_sendAjaxResponse(implode(', ', $errorDomains), [], false);
656 }
657
658 acym_sendAjaxResponse('', ['domains' => $domains]);
659 }
660
661 public function onAcymDeleteDomain()
662 {
663 $oneDomain = acym_getVar('string', 'oneDomain', '');
664
665 if (empty($oneDomain)) {
666 return;
667 }
668
669 $apikey = $this->config->get(self::SENDING_METHOD_ID.'_apikey');
670 if (empty($apikey)) {
671 acym_sendAjaxResponse(acym_translation('ACYM_MISSING_API_KEY'), [], false);
672 }
673
674 $responseApi = $this->callApiSendingMethod(
675 'deleteDomainIdentity',
676 ['domain' => $oneDomain, 'siteUrl' => acym_baseURI()],
677 [],
678 'POST'
679 );
680
681 if (!empty($responseApi['error_curl'])) {
682 $message = acym_translationSprintf('ACYM_ERROR_OCCURRED_WHILE_CALLING_API', $responseApi['error_curl']);
683 acym_sendAjaxResponse($message, [], false);
684 } elseif (!empty($responseApi['message']) && $responseApi['message'] === 'Invalid private key') {
685 acym_sendAjaxResponse(acym_translation('ACYM_AUTHENTICATION_FAILS_WITH_API_KEY'), [], false);
686 } elseif (!$this->checkSuccessCode($this->responseCode) && (empty($responseApi['code']) || !in_array($responseApi['code'], [5, 4, 3]))) {
687
688 $message = acym_translation('ACYM_ERROR_ON_CALL_ACYBA_WEBSITE').': '.$this->translate($responseApi);
689 if (!empty($responseApi['logs'])) {
690 acym_logError($responseApi['logs'], self::SENDING_METHOD_ID);
691 }
692
693 acym_sendAjaxResponse($message, [], false);
694 } else {
695 $field = self::SENDING_METHOD_ID.'_domains';
696 $domains = json_decode($this->config->get($field, '[]'), true);
697 $domains = array_filter($domains, function ($domain) use ($oneDomain) {
698 return $domain['domain'] != $oneDomain;
699 });
700
701 $newConfig = new \stdClass();
702 $newConfig->$field = json_encode($domains);
703 $this->config->save($newConfig);
704
705 acym_sendAjaxResponse();
706 }
707 }
708
709 public function ajaxAddDomain(): void
710 {
711 $oneDomain = acym_getVar('string', 'oneDomain', '');
712
713 $this->config->save(['mailer_method' => self::SENDING_METHOD_ID]);
714
715 if (empty($oneDomain)) {
716 acym_sendAjaxResponse(acym_translation('ACYM_MISSING_DOMAIN'), [], false);
717 }
718
719 $oneDomain = acym_strtolower($oneDomain);
720
721 $apikey = $this->config->get(self::SENDING_METHOD_ID.'_apikey');
722 if (empty($apikey)) {
723 acym_sendAjaxResponse(acym_translation('ACYM_MISSING_API_KEY'), [], false);
724 }
725
726 $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);
727 if (!$domainValidation) {
728 $message = acym_translationSprintf('ACYM_THE_DOMAIN_X_IS_NOT_VALID', $oneDomain);
729 acym_sendAjaxResponse($message, ['type' => 'DOMAIN_VALIDATION'], false);
730 }
731
732 $field = self::SENDING_METHOD_ID.'_domains';
733 $domains = $this->config->get($field, []);
734
735 if (!empty($domains)) {
736 $domains = @json_decode($domains, true);
737 }
738
739 if (!empty($domains[$oneDomain])) {
740 acym_sendAjaxResponse(acym_translation('ACYM_DOMAIN_ALREADY_SENT'), [], false);
741 }
742
743 $responseApi = $this->callApiSendingMethod(
744 'createDomainIdentity',
745 ['domain' => $oneDomain, 'siteUrl' => acym_baseURI()],
746 [],
747 'POST'
748 );
749
750 if (!empty($responseApi['error_curl'])) {
751 $message = acym_translationSprintf('ACYM_ERROR_OCCURRED_WHILE_CALLING_API', $responseApi['error_curl']);
752 acym_sendAjaxResponse($message, [], false);
753 } elseif (!empty($responseApi['message']) && $responseApi['message'] === 'Invalid API-KEY') {
754 acym_sendAjaxResponse(acym_translation('ACYM_AUTHENTICATION_FAILS_WITH_API_KEY'), [], false);
755 } elseif (!$this->checkSuccessCode($this->responseCode)) {
756 if (empty($responseApi['code']) || empty(self::TRANSLATIONS[$responseApi['code']])) {
757 $errorCodeTranslationKey = empty($responseApi['message']) ? 'ACYM_DOMAIN_DEFAULT_ERROR' : $this->displayMessage($responseApi['message']);
758 } else {
759 $errorCodeTranslationKey = self::TRANSLATIONS[$responseApi['code']];
760 }
761 $message = acym_translationSprintf($errorCodeTranslationKey, $oneDomain);
762 acym_sendAjaxResponse($message, [], false);
763 } elseif ($this->responseCode === 201) {
764 $domains[$oneDomain] = [
765 'domain' => $oneDomain,
766 'CnameRecords' => $responseApi['cnameRecords'],
767 'status' => 'PENDING',
768 ];
769 $this->config->save([$field => json_encode($domains)]);
770 acym_sendAjaxResponse($this->translate($responseApi), ['cnameRecords' => $responseApi['cnameRecords']]);
771 } else {
772 $cnameRecords = $responseApi['data'][$oneDomain]['cnameRecords'];
773 $status = $responseApi['data'][$oneDomain]['status'];
774 $domains[$oneDomain] = [
775 'domain' => $oneDomain,
776 'CnameRecords' => $cnameRecords,
777 'status' => $status,
778 ];
779 $this->config->save([$field => json_encode($domains)]);
780
781 acym_sendAjaxResponse(
782 $this->translate($responseApi),
783 ['cnameRecords' => $cnameRecords, 'alreadyVerified' => $status === 'SUCCESS']
784 );
785 }
786 }
787
788 public function onAcymDisplayPage()
789 {
790 if (intval($this->config->get('walk_through', 0)) === 1) {
791 return;
792 }
793
794 $unverifiedDomains = $this->getDomainsUnVerified();
795
796 if (!empty($unverifiedDomains)) {
797 $message = acym_translationSprintf('ACYM_UNVERIFIED_DOMAINS_PREVENTING_EMAILS_FROM_BEING_SENT_X', implode(', ', $unverifiedDomains));
798 acym_enqueueMessage($message, 'warning');
799 }
800 }
801
802 public function onAcymGetCreditRemainingSendingMethod(&$html, $reloading = false)
803 {
804 $sendingMethod = $this->config->get('mailer_method', '');
805 if (empty($sendingMethod) || $sendingMethod != self::SENDING_METHOD_ID) return;
806
807 $apiKey = $this->config->get(self::SENDING_METHOD_ID.'_apikey', '');
808 if (empty($apiKey)) return;
809
810 $response = $this->getRemainingCredits($reloading);
811
812 if (!isset($response['remaining_credits'])) {
813 if (empty($this->translate($response))) {
814 $html = acym_translation('ACYM_ERROR_CONTACT_ACYMAILING');
815 } else {
816 $html = acym_translationSprintf(
817 'ACYM_SENDING_METHOD_ERROR_WHILE_ACTION',
818 self::SENDING_METHOD_NAME,
819 acym_translation('ACYM_GETTING_REMAINING_CREDITS'),
820 $this->translate($response)
821 );
822 }
823
824 return;
825 }
826
827 $unityTranslation = 'ACYM_CREDITS_REMAINING';
828 $creditsShowed = $response['remaining_credits'];
829
830 if (!empty($response['is_multisite'])) {
831 $fromEmail = $this->config->get('from_email', '');
832 $domain = explode('@', $fromEmail)[1];
833
834 if (empty($domain) || empty($response['domains'][$domain])) {
835 $html = acym_translation('ACYM_DOMAIN_FROM_EMAIL_NOT_VALID_ASS');
836 } else {
837 $domainData = $response['domains'][$domain];
838 if ($domainData['is_limited']) {
839 $creditsShowed = $domainData['remaining_credits'];
840 } else {
841 $creditsShowed = $domainData['credits_used'];
842 $unityTranslation = 'ACYM_CREDITS_USED';
843 }
844 }
845 }
846
847 if (empty($creditsShowed)) {
848 $creditsShowed = '0';
849 }
850 $html = acym_translationSprintf(
851 'ACYM_SENDING_METHOD_X_UNITY',
852 self::SENDING_METHOD_NAME,
853 acym_tooltip(
854 [
855 'hoveredText' => $creditsShowed,
856 'textShownInTooltip' => acym_translation('ACYM_GET_MORE_CREDITS'),
857 'classContainer' => 'credits_remaining',
858 'link' => ACYM_ACYMAILING_WEBSITE,
859 ]
860 ),
861 '<span class="acym_not_bold">'.acym_translation($unityTranslation).'</span>'
862 );
863 }
864
865 public function onAcymCreditsLeft(&$creditsLeft)
866 {
867 $sendingMethod = $this->config->get('mailer_method', '');
868 if (empty($sendingMethod) || $sendingMethod != self::SENDING_METHOD_ID) return;
869
870 $apiKey = $this->config->get(self::SENDING_METHOD_ID.'_apikey', '');
871 if (empty($apiKey)) {
872 $creditsLeft = 0;
873
874 return;
875 }
876
877 $credits = $this->getRemainingCredits(true);
878 if (empty($credits['remaining_credits'])) {
879 $creditsLeft = 0;
880 } else {
881 $creditsLeft = $credits['remaining_credits'];
882 }
883 }
884
885 public function onAcymAttachLicense($licenseKey)
886 {
887 if (empty($licenseKey)) {
888 return;
889 }
890
891 $response = $this->callApiSendingMethod(self::SENDING_METHOD_API_URL.'public/licenses/'.$licenseKey);
892
893 if (!empty($response['id'])) {
894 $this->config->save([self::SENDING_METHOD_ID.'_apikey' => $response['id']]);
895 }
896 }
897
898 public function onAcymDetachLicense()
899 {
900 $this->config->save([self::SENDING_METHOD_ID.'_apikey' => '']);
901 }
902
903 public function onAcymCampaignSummary(&$data)
904 {
905 if ($this->config->get('mailer_method') !== self::SENDING_METHOD_ID) {
906 return;
907 }
908
909 $mail = $data['mailClass']->getOneById($data['mailId']);
910 if (empty($mail->body) || !$this->isContainingUnsubscribeLink($mail->body)) {
911 $data['notAllowedSendingError'] = acym_translation('ACYM_UNSUB_LINK');
912 }
913
914 $unverifiedDomains = $this->getDomainsUnVerified();
915 if (!empty($unverifiedDomains)) {
916 $data['notAllowedSendingError'] = acym_translationSprintf(
917 'ACYM_UNVERIFIED_DOMAINS_PREVENTING_EMAILS_FROM_BEING_SENT_X',
918 implode(', ', $unverifiedDomains)
919 );
920 }
921 }
922
923 private function getDomainsUnVerified(): array
924 {
925 if ($this->config->get('mailer_method') !== self::SENDING_METHOD_ID) {
926 return [];
927 }
928
929 $allDomains = [];
930
931 $allDomains[] = acym_getDomain($this->config->get('from_email'));
932 if ($this->config->get('from_as_replyto') === '0') {
933 $allDomains[] = acym_getDomain($this->config->get('replyto_email'));
934 }
935
936 if ($this->config->get('multilingual') === '1') {
937 $senderInfoTranslation = $this->config->get('sender_info_translation');
938 if (!empty($senderInfoTranslation)) {
939 $senderInfoTranslation = json_decode($senderInfoTranslation, true);
940 foreach ($senderInfoTranslation as $oneSenderInfo) {
941 $allDomains[] = acym_getDomain($oneSenderInfo['from_email']);
942 $allDomains[] = acym_getDomain($oneSenderInfo['replyto_email']);
943 }
944 }
945 }
946
947 $allDomains[] = acym_getDomain($this->config->get('bounce_email'));
948 $allDomains = array_filter(array_unique($allDomains));
949
950 $verifiedDomains = $this->getVerifiedDomains();
951
952 return array_diff($allDomains, $verifiedDomains);
953 }
954
955 private function getRateColor($rate, $allowedRate, $warningRate): array
956 {
957 if (empty($rate) || empty($allowedRate) || empty($warningRate)) {
958 return ['color' => '', 'icon' => ''];
959 }
960
961 if ($rate > $allowedRate) {
962 return [
963 'color' => 'acym__color__red',
964 'icon' => acym_tooltip(
965 [
966 'hoveredText' => '<i class="acym__config__acymailer__rate-status__icon acymicon-close acym__color__red"></i>',
967 'textShownInTooltip' => acym_translation('ACYM_RATE_BLOCKED'),
968 ]
969 ),
970 ];
971 } elseif ($rate >= $warningRate) {
972 return [
973 'color' => 'acym__color__orange',
974 'icon' => acym_tooltip(
975 [
976 'hoveredText' => '<i class="acym__config__acymailer__rate-status__icon acymicon-exclamation-triangle acym__color__orange"></i>',
977 'textShownInTooltip' => acym_translation('ACYM_RATE_WARNING'),
978 ]
979 ),
980 ];
981 }
982
983 return ['color' => '', 'icon' => ''];
984 }
985
986 private function updateDomainRates($domainsRates)
987 {
988 $domains = $this->config->get(self::SENDING_METHOD_ID.'_domains', []);
989
990 if (empty($domains)) {
991 return;
992 }
993
994 $domains = @json_decode($domains, true);
995
996 foreach ($domainsRates as $oneDomain => $oneRate) {
997 if (empty($domains[$oneDomain])) continue;
998 foreach ($oneRate as $rateKey => $rateValue) {
999 $domains[$oneDomain][$rateKey] = $rateValue;
1000 }
1001 }
1002
1003 $this->config->save([self::SENDING_METHOD_ID.'_domains' => json_encode($domains)]);
1004 }
1005
1006 private function getVerifiedDomains(): array
1007 {
1008 $verifiedDomains = [];
1009 $domainStatuses = json_decode($this->config->get(self::SENDING_METHOD_ID.'_domains', '[]'), true);
1010 if (!empty($domainStatuses)) {
1011 foreach ($domainStatuses as $domain => $info) {
1012 if ($info['status'] === 'SUCCESS') {
1013 $verifiedDomains[] = $domain;
1014 }
1015 }
1016 }
1017
1018 return $verifiedDomains;
1019 }
1020
1021 private function displayMessage($message): string
1022 {
1023 $correspondances = [
1024 'AlreadyExistsException' => 'ACYM_DOMAIN_X_ALREADY_EXIST',
1025 'TooManyRequestsException' => 'ACYM_DOMAIN_TO_MANY_REQUEST',
1026 'NotFoundException' => 'ACYM_DOMAIN_NOT_FOUND',
1027 'NotExistException' => 'ACYM_CANT_DELETE_DOMAIN',
1028 ];
1029
1030 if (empty($message) || empty($correspondances[$message])) {
1031 return 'ACYM_DOMAIN_DEFAULT_ERROR';
1032 }
1033
1034 return $correspondances[$message];
1035 }
1036
1037 private function getRemainingCredits($forceReload = false)
1038 {
1039 $time = time();
1040 $lastCheck = $this->config->get(self::SENDING_METHOD_ID.'_last_credits_check', 0);
1041 $lastDetails = $this->config->get(self::SENDING_METHOD_ID.'_credits_details', []);
1042
1043 if (!$forceReload && !empty($lastDetails) && $lastCheck > $time - self::CREDITS_RELOAD_DELAY) {
1044 return json_decode($lastDetails, true);
1045 }
1046
1047 $response = $this->callApiSendingMethod('get_credits');
1048
1049 $this->config->save([
1050 self::SENDING_METHOD_ID.'_credits_details' => json_encode($response),
1051 self::SENDING_METHOD_ID.'_last_credits_check' => $time,
1052 ]);
1053
1054 if (!empty($response['domains'])) {
1055 $this->updateDomainRates($response['domains']);
1056 }
1057
1058 return $response;
1059 }
1060
1061 private function checkSuccessCode($responseCode): bool
1062 {
1063 $successCodes = [200, 201, 204];
1064
1065 return in_array($responseCode, $successCodes);
1066 }
1067
1068 private function translate($response)
1069 {
1070 if (!isset($response['code']) && empty($response['message'])) {
1071 return '';
1072 }
1073
1074 $correspondence = '';
1075 $messageData = '';
1076
1077
1078 if (isset($response['code']) && !empty(self::TRANSLATIONS[$response['code']])) {
1079 $correspondence = self::TRANSLATIONS[$response['code']];
1080 }
1081
1082 if (!empty($response['messageData'])) {
1083 $messageData = $response['messageData'];
1084 }
1085
1086 if (empty($correspondence)) {
1087 if (empty($messageData)) {
1088 return $response['message'];
1089 }
1090
1091 return acym_translationVsprintf($response['message'], $messageData, false);
1092 }
1093
1094 if (empty($messageData)) {
1095 $finalMessage = acym_translation($correspondence);
1096 } else {
1097 $finalMessage = acym_translationVsprintf($correspondence, $messageData);
1098 }
1099
1100 if (in_array($response['code'], $this->errorCodes)) {
1101 $this->errors[] = $finalMessage;
1102 $this->errorCallback();
1103 }
1104
1105 return $finalMessage;
1106 }
1107
1108 private function isUnsubscribeLinkMissing($mailerHelper): bool
1109 {
1110 if ($mailerHelper->isTest || $mailerHelper->isForward || $mailerHelper->isSpamTest || empty($mailerHelper->mail)) {
1111 return false;
1112 }
1113
1114 if (in_array($mailerHelper->mail->type, MailClass::TYPES_TRANSACTIONAL) || $mailerHelper->mail->type === MailClass::TYPE_AUTOMATION) {
1115 return false;
1116 }
1117
1118 return !$this->isContainingUnsubscribeLink($mailerHelper->mail->body);
1119 }
1120
1121 private function isContainingUnsubscribeLink(string $text): bool
1122 {
1123 return strpos($text, '{unsubscribe}') !== false
1124 || strpos($text, '{unsubscribeall}') !== false
1125 || strpos($text, 'task=unsubscribe') !== false
1126 || strpos($text, 'frontusers/unsubscribe') !== false;
1127 }
1128
1129 private function checkDomainsDNS($domains): array
1130 {
1131 $remainingDomains = [];
1132 foreach ($domains as $oneDomain) {
1133 if (empty($oneDomain['CnameRecords'])) {
1134 $remainingDomains[] = $oneDomain;
1135 continue;
1136 }
1137
1138 if ($oneDomain['status'] == 'SUCCESS') {
1139 continue;
1140 }
1141
1142 foreach ($oneDomain['CnameRecords'] as $oneRecord) {
1143 if (!$this->checkCnameEntry($oneRecord['name'], $oneRecord['value'])) {
1144 $domainPosition = strpos($oneRecord['name'], '_domainkey') + 11;
1145 $domainName = substr($oneRecord['name'], $domainPosition);
1146 acym_sendAjaxResponse(acym_translation('ACYM_A_CNAME_MISSING'), ['domain' => $domainName], false);
1147 }
1148 }
1149
1150 $remainingDomains[] = $oneDomain;
1151 }
1152
1153 return $remainingDomains;
1154 }
1155
1156 private function checkCnameEntry(string $entryName, string $entryValue): bool
1157 {
1158 $domainPosition = strpos($entryName, '_domainkey') + 11;
1159 $domainName = substr($entryName, $domainPosition);
1160
1161 $dnsEntries = @dns_get_record($entryName, DNS_CNAME);
1162
1163 if (empty($dnsEntries)) {
1164 $entryName = substr($entryName, 0, $domainPosition);
1165 $doubleDomainEntry = $entryName.'.'.$domainName;
1166
1167 $dnsEntries = @dns_get_record($doubleDomainEntry, DNS_CNAME);
1168 if (!empty($dnsEntries)) {
1169 $this->cnameErrors[] = acym_translationSprintf('ACYM_ACYMAILER_MALFORMED_CNAME', $doubleDomainEntry);
1170 $this->cnameErrors[] = acym_translationSprintf('ACYM_ACYMAILER_CNAME_TRY_WITHOUT_DOMAIN', $entryName, $entryValue);
1171 } else {
1172 $this->cnameErrors[] = acym_translation('ACYM_WALK_ACYMAILER_STATUS_WAIT');
1173 }
1174
1175 return false;
1176 }
1177
1178 if (!is_array($dnsEntries)) {
1179 $dnsEntries = [$dnsEntries];
1180 }
1181
1182 foreach ($dnsEntries as $oneEntry) {
1183 if ($oneEntry['type'] !== 'CNAME' || $oneEntry['host'] !== $entryName) {
1184 continue;
1185 }
1186
1187 if (rtrim($oneEntry['target'], '.') === rtrim($entryValue, '.')) {
1188 return true;
1189 }
1190
1191 $this->cnameErrors[] = acym_translationSprintf('ACYM_DOMAIN_CHECK_INCORRECT_VALUE', $entryName, $domainName);
1192
1193 return false;
1194 }
1195
1196 $this->cnameErrors[] = acym_translation('ACYM_DNS_NOT_CNAME');
1197
1198 return false;
1199 }
1200 }
1201