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