| @@ -52,28 +52,36 @@ | ||
| 52 | 52 | parent::__construct(); |
| 53 | 53 | $this->pluginDescription->name = self::SENDING_METHOD_NAME; |
| 54 | 54 | } |
| 55 | 55 | |
| 56 | - protected function callApiSendingMethod(string $url, array $data = [], array $headers = [], string $type = 'GET', array $authentication = [], bool $dataDecoded = false): array | |
| 57 | - { | |
| 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 { | |
| 58 | 65 | if (strpos($url, self::SENDING_METHOD_API_URL) === false) { |
| 59 | 66 | $url = self::SENDING_METHOD_API_URL.'api/'.$url; |
| 60 | 67 | } |
| 61 | 68 | |
| 62 | 69 | $defaultHeaders = [ |
| 63 | - 'accept' => 'application/json', | |
| 64 | - 'content-type' => 'application/json', | |
| 70 | + 'Accept' => 'application/json', | |
| 71 | + 'Content-Type' => 'application/json', | |
| 65 | 72 | 'API-KEY' => $this->config->get(self::SENDING_METHOD_ID.'_apikey', ''), |
| 66 | 73 | 'Version' => $this->config->get('version'), |
| 67 | 74 | ]; |
| 68 | 75 | |
| 76 | + $usedHeaders = array_map('strtolower', array_keys($headers)); | |
| 69 | 77 | foreach ($defaultHeaders as $key => $value) { |
| 70 | - if (!isset($headers[$key])) { | |
| 78 | + if (!in_array(strtolower($key), $usedHeaders, true)) { | |
| 71 | 79 | $headers[$key] = $value; |
| 72 | 80 | } |
| 73 | 81 | } |
| 74 | 82 | |
| 75 | - $result = parent::callApiSendingMethod($url, $data, $headers, $type, $authentication, $dataDecoded); | |
| 83 | + $result = parent::callApiSendingMethod($url, $data, $headers, $type, $authentication, $dataDecoded, $files); | |
| 76 | 84 | if (!empty($result['error_curl'])) { |
| 77 | 85 | $result['message'] = $result['error_curl']; |
| 78 | 86 | $this->errors[] = $result['error_curl']; |
| 79 | 87 | $this->errorCallback(); |
| @@ -106,14 +114,14 @@ | ||
| 106 | 114 | ?> |
| 107 | 115 | <div class="grid-x grid-margin-x margin-top-1" id="activate_ass_method_notice"> |
| 108 | 116 | <label class="cell medium-7 acym_vcenter"> |
| 109 | 117 | <i class="acymicon-info-circle" id="acymailer_info_icon"></i> |
| 110 | - <?php echo acym_translation('ACYM_ACTIVATE_ACYMAILER'); ?> | |
| 118 | + <?php echo esc_html(acym_translation('ACYM_ACTIVATE_ACYMAILER')); ?> | |
| 111 | 119 | </label> |
| 112 | 120 | <button type="button" |
| 113 | - id="acym__configuration__activate__acymailer" | |
| 114 | - class="cell shrink button margin-bottom-0"> | |
| 115 | - <?php echo acym_translation('ACYM_SEE_THE_SENDING_METHOD'); ?> | |
| 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')); ?> | |
| 116 | 124 | </button> |
| 117 | 125 | </div> |
| 118 | 126 | <?php |
| 119 | 127 | } |
| @@ -131,24 +139,22 @@ | ||
| 131 | 139 | }); |
| 132 | 140 | } |
| 133 | 141 | |
| 134 | 142 | $unverifiedDomains = $this->getDomainsUnVerified(); |
| 135 | - | |
| 136 | - ob_start(); | |
| 137 | 143 | ?> |
| 138 | - <div class="send_settings cell grid-x acym_vcenter" id="<?php echo self::SENDING_METHOD_ID; ?>_settings"> | |
| 144 | + <div class="send_settings cell grid-x acym_vcenter" id="<?php echo esc_attr(self::SENDING_METHOD_ID); ?>_settings"> | |
| 139 | 145 | <div class="cell grid-x acym__sending__methods__one__settings <?php echo empty($data['step']) ? 'xlarge-10 xxlarge-8' : ''; ?>"> |
| 140 | 146 | <?php if (!acym_level(ACYM_ESSENTIAL) && empty($data['step'])) { ?> |
| 141 | 147 | <div class="acym_vcenter acym__config__acymailer__warning margin-top-1 cell grid-x large-8 xlarge-6 xxlarge-5"> |
| 142 | 148 | <label for="acym__configuration__license-key" class="cell"> |
| 143 | - <?php echo acym_translation('ACYM_YOUR_LICENSE_KEY'); ?> | |
| 149 | + <?php echo esc_html(acym_translation('ACYM_YOUR_LICENSE_KEY')); ?> | |
| 144 | 150 | </label> |
| 145 | - <input type="text" name="config[license_key]" id="acym__configuration__license-key" class="cell auto" value="<?php echo acym_escape($licenseKey); ?>"> | |
| 151 | + <input type="text" name="config[license_key]" id="acym__configuration__license-key" class="cell auto" value="<?php echo esc_attr($licenseKey); ?>"> | |
| 146 | 152 | <button type="button" |
| 147 | - id="acym__configuration__button__license" | |
| 148 | - class="cell shrink medium-3 button margin-top-1 medium-margin-top-0 medium-margin-left-1" | |
| 149 | - data-acym-linked="<?php echo empty($licenseKey) ? 0 : 1; ?>"> | |
| 150 | - <?php echo acym_translation(empty($licenseKey) ? 'ACYM_ATTACH_MY_LICENSE' : 'ACYM_UNLINK_MY_LICENSE'); ?> | |
| 153 | + id="acym__configuration__button__license" | |
| 154 | + class="cell shrink medium-3 button margin-top-1 medium-margin-top-0 medium-margin-left-1" | |
| 155 | + data-acym-linked="<?php echo empty($licenseKey) ? 0 : 1; ?>"> | |
| 156 | + <?php echo esc_html(acym_translation(empty($licenseKey) ? 'ACYM_ATTACH_MY_LICENSE' : 'ACYM_UNLINK_MY_LICENSE')); ?> | |
| 151 | 157 | </button> |
| 152 | 158 | </div> |
| 153 | 159 | <?php } |
| 154 | 160 | if (empty($licenseKey)) { ?> |
| @@ -156,11 +162,11 @@ | ||
| 156 | 162 | <i class="acymicon-exclamation-triangle acym__color__orange"></i> |
| 157 | 163 | <span class="margin-right-1"> |
| 158 | 164 | <?php |
| 159 | 165 | $pricingPage = ACYM_ACYMAILING_WEBSITE.'pricing?utm_source=acymailing_plugin&utm_medium=sendingmethod&utm_campaign=purchase'; |
| 160 | - echo acym_translation(acym_level(ACYM_ESSENTIAL) ? 'ACYM_NO_LICENSE' : 'ACYM_NO_LICENSE_STARTER'); | |
| 166 | + echo esc_html(acym_translation(acym_level(ACYM_ESSENTIAL) ? 'ACYM_NO_LICENSE' : 'ACYM_NO_LICENSE_STARTER')); | |
| 161 | 167 | ?> |
| 162 | - <a target="_blank" href="<?php echo $pricingPage; ?>"><?php echo acym_translation('ACYM_GET_A_LICENSE'); ?></a> | |
| 168 | + <a target="_blank" href="<?php echo esc_url($pricingPage); ?>"><?php echo esc_html(acym_translation('ACYM_GET_A_LICENSE')); ?></a> | |
| 163 | 169 | </span> |
| 164 | 170 | </div> |
| 165 | 171 | <?php } elseif (empty($acyMailerKey)) { ?> |
| 166 | 172 | <div class="cell acym_vcenter acym__config__acymailer__warning margin-top-1"> |
| @@ -167,21 +173,23 @@ | ||
| 167 | 173 | <i class="acymicon-exclamation-triangle acym__color__orange"></i> |
| 168 | 174 | <span> |
| 169 | 175 | <?php |
| 170 | 176 | $subscriptionsPage = ACYM_ACYMAILING_WEBSITE.'account/license?utm_source=acymailing_plugin&utm_medium=sendingmethod&utm_campaign=purchase'; |
| 171 | - echo acym_translation('ACYM_API_KEY_NOT_ALLOWING_METHOD'); | |
| 177 | + echo esc_html(acym_translation('ACYM_API_KEY_NOT_ALLOWING_METHOD')); | |
| 172 | 178 | ?> |
| 173 | - <a target="_blank" href="<?php echo $subscriptionsPage; ?>"><?php echo acym_translation('ACYM_SWITCH_MY_LICENSE'); ?></a> | |
| 179 | + <a target="_blank" href="<?php echo esc_url($subscriptionsPage); ?>"><?php echo esc_html( | |
| 180 | + acym_translation('ACYM_SWITCH_MY_LICENSE') | |
| 181 | + ); ?></a> | |
| 174 | 182 | </span> |
| 175 | 183 | </div> |
| 176 | 184 | |
| 177 | 185 | <div class="acym__configuration__acymailer__check-license cell grid-x"> |
| 178 | - <div class="cell"><?php echo acym_translation('ACYM_CHECK_SENDING_SERVICE_LICENSE'); ?></div> | |
| 186 | + <div class="cell"><?php echo esc_html(acym_translation('ACYM_CHECK_SENDING_SERVICE_LICENSE')); ?></div> | |
| 179 | 187 | <button |
| 180 | 188 | data-task="attachLicenseAcymailer" |
| 181 | 189 | id="acym__configuration__acymailer__verify-license" |
| 182 | 190 | class="cell medium-shrink button margin-left-0 margin-top-1 acy_button_submit"> |
| 183 | - <?php echo acym_translation('ACYM_CHECK_LICENSE'); ?> | |
| 191 | + <?php echo esc_html(acym_translation('ACYM_CHECK_LICENSE')); ?> | |
| 184 | 192 | </button> |
| 185 | 193 | </div> |
| 186 | 194 | <?php } else { ?> |
| 187 | 195 | <div class="cell grid-x"> |
| @@ -188,22 +196,24 @@ | ||
| 188 | 196 | <?php if (!empty($domainsWaiting)) { ?> |
| 189 | 197 | <div class="cell <?php echo empty($data['step']) ? 'large-8' : ''; ?> grid-x acym_vcenter acym__config__acymailer__warning"> |
| 190 | 198 | <i class="cell small-2 margin-right-0 acymicon-access-time acym__color__orange"></i> |
| 191 | 199 | <div class="cell small-10 grid-x"> |
| 192 | - <span class="cell"><?php echo acym_translation('ACYM_DOMAINS_WAITING_VALIDATION_ADD_CNAME'); ?></span> | |
| 193 | - <a href="<?php echo ACYM_DOCUMENTATION; ?>external-sending-method/acymailing-sending-service#how-to-add-the-dns-entries-on-my-server" | |
| 200 | + <span class="cell"><?php echo esc_html(acym_translation('ACYM_DOMAINS_WAITING_VALIDATION_ADD_CNAME')); ?></span> | |
| 201 | + <a href="<?php echo esc_url( | |
| 202 | + ACYM_DOCUMENTATION | |
| 203 | + ); ?>external-sending-method/acymailing-sending-service#how-to-add-the-dns-entries-on-my-server" | |
| 194 | 204 | target="_blank" |
| 195 | 205 | class="cell"> |
| 196 | - <?php echo acym_translation('ACYM_CHECK_THIS_TUTORIAL'); ?> | |
| 206 | + <?php echo esc_html(acym_translation('ACYM_CHECK_THIS_TUTORIAL')); ?> | |
| 197 | 207 | </a> |
| 198 | 208 | </div> |
| 199 | 209 | </div> |
| 200 | 210 | <div class="cell <?php echo empty($data['step']) ? 'large-4' : ''; ?> margin-top-1 margin-bottom-1"> |
| 201 | 211 | <button id="acym__config__acymailer__update-domain-status" |
| 202 | - type="button" | |
| 203 | - class="button button-secondary float-right" | |
| 204 | - sending-method-id="<?php echo self::SENDING_METHOD_ID; ?>"> | |
| 205 | - <i class="acymicon-autorenew"></i><?php echo acym_translation('ACYM_UPDATE_DOMAIN_STATUS'); ?> | |
| 212 | + type="button" | |
| 213 | + class="button button-secondary float-right" | |
| 214 | + sending-method-id="<?php echo esc_attr(self::SENDING_METHOD_ID); ?>"> | |
| 215 | + <i class="acymicon-autorenew"></i><?php echo esc_html(acym_translation('ACYM_UPDATE_DOMAIN_STATUS')); ?> | |
| 206 | 216 | </button> |
| 207 | 217 | </div> |
| 208 | 218 | <?php } ?> |
| 209 | 219 | </div> |
| @@ -210,27 +220,29 @@ | ||
| 210 | 220 | <div class="grid-x acym__listing cell"> |
| 211 | 221 | <div class="grid-x cell acym__listing__header"> |
| 212 | 222 | <div class="grid-x medium-auto small-11 cell acym__listing__header__title__container"> |
| 213 | 223 | <div class="cell small-8 medium-auto acym__listing__header__title"> |
| 214 | - <?php echo acym_translation('ACYM_DOMAIN_NAME'); ?> | |
| 224 | + <?php echo esc_html(acym_translation('ACYM_DOMAIN_NAME')); ?> | |
| 215 | 225 | </div> |
| 216 | 226 | <div class="cell hide-for-small-only medium-2 acym__listing__header__title text-center"> |
| 217 | - <?php echo acym_translation('ACYM_STATUS'); ?> | |
| 227 | + <?php echo esc_html(acym_translation('ACYM_STATUS')); ?> | |
| 218 | 228 | </div> |
| 219 | 229 | <div class="cell hide-for-small-only medium-2 acym__listing__header__title text-center"> |
| 220 | - <?php echo acym_translation('ACYM_BOUNCE_RATE').acym_info(['textShownInTooltip' => 'ACYM_BOUNCE_RATE_DESC']); ?> | |
| 230 | + <?php echo esc_html(acym_translation('ACYM_BOUNCE_RATE')); | |
| 231 | + acym_info(['textShownInTooltip' => 'ACYM_BOUNCE_RATE_DESC']); ?> | |
| 221 | 232 | </div> |
| 222 | 233 | <div class="cell hide-for-small-only medium-2 acym__listing__header__title text-center"> |
| 223 | - <?php echo acym_translation('ACYM_COMPLAINT_RATE').acym_info(['textShownInTooltip' => 'ACYM_COMPLAINT_RATE_DESC']); ?> | |
| 234 | + <?php echo esc_html(acym_translation('ACYM_COMPLAINT_RATE')); | |
| 235 | + acym_info(['textShownInTooltip' => 'ACYM_COMPLAINT_RATE_DESC']); ?> | |
| 224 | 236 | </div> |
| 225 | 237 | <div class="cell small-4 medium-2 acym__listing__header__title text-center"> |
| 226 | - <?php echo acym_translation('ACYM_ACTIONS'); ?> | |
| 238 | + <?php echo esc_html(acym_translation('ACYM_ACTIONS')); ?> | |
| 227 | 239 | </div> |
| 228 | 240 | </div> |
| 229 | 241 | </div> |
| 230 | 242 | <?php if (empty($domains)) { ?> |
| 231 | 243 | <div class="grid-x cell margin-top-1 align-center"> |
| 232 | - <?php echo acym_translation('ACYM_NO_DOMAINS_YET'); ?> | |
| 244 | + <?php echo esc_html(acym_translation('ACYM_NO_DOMAINS_YET')); ?> | |
| 233 | 245 | </div> |
| 234 | 246 | <?php } else { |
| 235 | 247 | foreach ($domains as &$domain) { |
| 236 | 248 | $isValid = true; |
| @@ -237,9 +249,9 @@ | ||
| 237 | 249 | foreach ($domain['CnameRecords'] as $i => $cnameRecord) { |
| 238 | 250 | $domain['CnameRecords'][$i]['isValid'] = $this->checkCnameEntry($cnameRecord['name'], $cnameRecord['value']); |
| 239 | 251 | $isValid = $isValid && $domain['CnameRecords'][$i]['isValid']; |
| 240 | 252 | $domain['CnameRecords'][$i]['tooltipMessages'] = $this->cnameErrors; |
| 241 | - $this->cnameErrors = []; | |
| 253 | + $this->cnameErrors = []; | |
| 242 | 254 | } |
| 243 | 255 | |
| 244 | 256 | if (!$isValid && $domain['status'] === 'SUCCESS') { |
| 245 | 257 | $domain['status'] = 'PENDING'; |
| @@ -245,22 +257,22 @@ | ||
| 245 | 257 | $domain['status'] = 'PENDING'; |
| 246 | 258 | $this->config->saveConfig([self::SENDING_METHOD_ID.'_domains' => json_encode($domains)]); |
| 247 | 259 | } |
| 248 | 260 | |
| 249 | - $bounceRateParams = $this->getRateColor( | |
| 261 | + $bounceRateColorClass = $this->getRateColor( | |
| 250 | 262 | empty($domain['bounce_rate']) ? 0 : $domain['bounce_rate'], |
| 251 | 263 | empty($domain['allowed_bounce_rate']) ? 0 : $domain['allowed_bounce_rate'], |
| 252 | 264 | empty($domain['warning_bounce_rate']) ? 0 : $domain['warning_bounce_rate'] |
| 253 | 265 | ); |
| 254 | - $complaintRateParams = $this->getRateColor( | |
| 266 | + $complaintRateColorClass = $this->getRateColor( | |
| 255 | 267 | empty($domain['complaint_rate']) ? 0 : $domain['complaint_rate'], |
| 256 | 268 | empty($domain['allowed_complaint_rate']) ? 0 : $domain['allowed_complaint_rate'], |
| 257 | 269 | empty($domain['warning_complaint_rate']) ? 0 : $domain['warning_complaint_rate'] |
| 258 | 270 | ); |
| 259 | 271 | ?> |
| 260 | - <div acym-data-domain="<?php echo $domain['domain']; ?>" class="grid-x cell align-middle acym__listing__row"> | |
| 272 | + <div acym-data-domain="<?php echo esc_attr($domain['domain']); ?>" class="grid-x cell align-middle acym__listing__row"> | |
| 261 | 273 | <div class="cell small-6 medium-auto grid-x acym__listing__title__container"> |
| 262 | - <?php echo acym_escape($domain['domain']); ?> | |
| 274 | + <?php echo esc_html($domain['domain']); ?> | |
| 263 | 275 | </div> |
| 264 | 276 | <div class="cell small-1 medium-2 grid-x acym__listing__title__container align-center"> |
| 265 | 277 | <?php |
| 266 | 278 | switch ($domain['status']) { |
| @@ -276,9 +288,9 @@ | ||
| 276 | 288 | $iconClass = 'acymicon-access-time acym__color__orange notValidated'; |
| 277 | 289 | $tooltipText = acym_translation('ACYM_A_CNAME_MISSING'); |
| 278 | 290 | } |
| 279 | 291 | |
| 280 | - echo acym_tooltip( | |
| 292 | + acym_tooltip( | |
| 281 | 293 | [ |
| 282 | 294 | 'hoveredText' => '<i class="acym__config__acymailer__status__icon '.$iconClass.'"></i>', |
| 283 | 295 | 'textShownInTooltip' => $tooltipText, |
| 284 | 296 | ] |
| @@ -284,28 +296,42 @@ | ||
| 284 | 296 | ] |
| 285 | 297 | ); |
| 286 | 298 | ?> |
| 287 | 299 | </div> |
| 288 | - <div class="cell hide-for-small-only medium-2 grid-x acym__listing__title__container align-center <?php echo $bounceRateParams['color']; ?>"> | |
| 289 | - <?php echo empty($domain['bounce_rate']) ? '-' : round($domain['bounce_rate'], 2).'%'; | |
| 290 | - echo $bounceRateParams['icon']; | |
| 300 | + <div class="cell hide-for-small-only medium-2 grid-x acym__listing__title__container align-center <?php echo esc_attr( | |
| 301 | + $bounceRateColorClass | |
| 302 | + ); ?>"> | |
| 303 | + <?php echo empty($domain['bounce_rate']) ? '-' : esc_html(round($domain['bounce_rate'], 2)).'%'; | |
| 304 | + $this->displayRateIcon( | |
| 305 | + empty($domain['bounce_rate']) ? 0 : $domain['bounce_rate'], | |
| 306 | + empty($domain['allowed_bounce_rate']) ? 0 : $domain['allowed_bounce_rate'], | |
| 307 | + empty($domain['warning_bounce_rate']) ? 0 : $domain['warning_bounce_rate'] | |
| 308 | + ); | |
| 291 | 309 | ?> |
| 292 | 310 | </div> |
| 293 | - <div class="cell hide-for-small-only medium-2 grid-x acym__listing__title__container align-center <?php echo $complaintRateParams['color']; ?>"> | |
| 294 | - <?php echo empty($domain['complaint_rate']) ? '-' : round($domain['complaint_rate'], 2).'%'; | |
| 295 | - echo $complaintRateParams['icon']; | |
| 311 | + <div class="cell hide-for-small-only medium-2 grid-x acym__listing__title__container align-center <?php echo esc_attr( | |
| 312 | + $complaintRateColorClass | |
| 313 | + ); ?>"> | |
| 314 | + <?php echo empty($domain['complaint_rate']) ? '-' : esc_html(round($domain['complaint_rate'], 2)).'%'; | |
| 315 | + $this->displayRateIcon( | |
| 316 | + empty($domain['complaint_rate']) ? 0 : $domain['complaint_rate'], | |
| 317 | + empty($domain['allowed_complaint_rate']) ? 0 : $domain['allowed_complaint_rate'], | |
| 318 | + empty($domain['warning_complaint_rate']) ? 0 : $domain['warning_complaint_rate'] | |
| 319 | + ); | |
| 296 | 320 | ?> |
| 297 | 321 | </div> |
| 298 | 322 | <div class="cell small-4 medium-2 grid-x margin-left-1 medium-margin-left-0 acym__listing__title__container align-center"> |
| 299 | 323 | <?php ob_start(); ?> |
| 300 | 324 | <div class="cell grid-x acym__config__acymailer__cname__modal"> |
| 301 | - <h6 class="cell text-center margin-top-2 margin-bottom-1"><?php echo acym_translation('ACYM_DNS_ENTRIES'); ?></h6> | |
| 325 | + <h6 class="cell text-center margin-top-2 margin-bottom-1"><?php echo esc_html(acym_translation('ACYM_DNS_ENTRIES')); ?></h6> | |
| 302 | 326 | <div class="grid-x cell align-center margin-top-1 margin-bottom-2 acym_vcenter"> |
| 303 | - <p class="cell shrink"><?php echo acym_translation('ACYM_DO_NOT_KNOW_HOW_DO_IT'); ?> </p> | |
| 304 | - <a href="<?php echo ACYM_DOCUMENTATION; ?>external-sending-method/acymailing-sending-service#how-to-add-the-dns-entries-on-my-server" | |
| 327 | + <p class="cell shrink"><?php echo esc_html(acym_translation('ACYM_DO_NOT_KNOW_HOW_DO_IT')); ?> </p> | |
| 328 | + <a href="<?php echo esc_url( | |
| 329 | + ACYM_DOCUMENTATION | |
| 330 | + ); ?>external-sending-method/acymailing-sending-service#how-to-add-the-dns-entries-on-my-server" | |
| 305 | 331 | class="cell shrink acym__config__acymailer__cname__modal__link" |
| 306 | 332 | target="_blank"> |
| 307 | - <?php echo acym_translation('ACYM_STEP_BY_STEP_GUIDE'); ?> | |
| 333 | + <?php echo esc_html(acym_translation('ACYM_STEP_BY_STEP_GUIDE')); ?> | |
| 308 | 334 | </a> |
| 309 | 335 | </div> |
| 310 | 336 | <div class="grid-x acym__listing cell"> |
| 311 | 337 | <div class="grid-x acym__listing cell"> |
| @@ -310,45 +336,33 @@ | ||
| 310 | 336 | <div class="grid-x acym__listing cell"> |
| 311 | 337 | <div class="grid-x acym__listing cell"> |
| 312 | 338 | <div class="cell grid-x grid-margin-x margin-left-0 padding-bottom-1 acym__listing__header"> |
| 313 | 339 | <div class="cell small-10 hide-for-medium acym__listing__header__title"> |
| 314 | - <?php echo acym_translation('ACYM_NAME').' / '.acym_translation('ACYM_VALUE'); ?> | |
| 340 | + <?php echo esc_html(acym_translation('ACYM_NAME').' / '.acym_translation('ACYM_VALUE')); ?> | |
| 315 | 341 | </div> |
| 316 | 342 | <div class="cell small-5 show-for-medium acym__listing__header__title"> |
| 317 | - <?php echo acym_translation('ACYM_NAME'); ?> | |
| 343 | + <?php echo esc_html(acym_translation('ACYM_NAME')); ?> | |
| 318 | 344 | </div> |
| 319 | 345 | <div class="cell small-5 show-for-medium acym__listing__header__title"> |
| 320 | - <?php echo acym_translation('ACYM_VALUE'); ?> | |
| 346 | + <?php echo esc_html(acym_translation('ACYM_VALUE')); ?> | |
| 321 | 347 | </div> |
| 322 | 348 | <div class="cell small-2 acym__listing__header__title text-center"> |
| 323 | - <?php echo acym_translation('ACYM_STATUS'); ?> | |
| 349 | + <?php echo esc_html(acym_translation('ACYM_STATUS')); ?> | |
| 324 | 350 | </div> |
| 325 | 351 | </div> |
| 326 | - <?php | |
| 327 | - foreach ($domain['CnameRecords'] as $cnameRecord) { | |
| 328 | - if ($cnameRecord['isValid']) { | |
| 329 | - $cnameStatus = '<i class="acym__config__acymailer__status__icon acymicon-check-circle acym__color__green"></i>'; | |
| 330 | - } else { | |
| 331 | - $cnameStatus = acym_tooltip( | |
| 332 | - [ | |
| 333 | - 'hoveredText' => '<i class="acym__config__acymailer__status__icon acymicon-close acym__color__red"></i>', | |
| 334 | - 'textShownInTooltip' => implode('<br/>', $cnameRecord['tooltipMessages']), | |
| 335 | - ] | |
| 336 | - ); | |
| 337 | - } | |
| 338 | - ?> | |
| 352 | + <?php foreach ($domain['CnameRecords'] as $cnameRecord) { ?> | |
| 339 | 353 | <div class="cell grid-x grid-margin-x margin-left-0 align-middle acym__listing__row"> |
| 340 | 354 | <div class="cell small-11 medium-5 cname-name"> |
| 341 | - <?php echo $cnameRecord['name']; ?> | |
| 355 | + <?php echo esc_html($cnameRecord['name']); ?> | |
| 342 | 356 | </div> |
| 343 | 357 | <div class="cell small-1 hide-for-medium cname-value"> |
| 344 | - <?php echo $cnameStatus; ?> | |
| 358 | + <?php $this->displayCnameStatus($cnameRecord); ?> | |
| 345 | 359 | </div> |
| 346 | 360 | <div class="cell small-11 medium-5 cname-value"> |
| 347 | - <?php echo $cnameRecord['value']; ?> | |
| 361 | + <?php echo esc_html($cnameRecord['value']); ?> | |
| 348 | 362 | </div> |
| 349 | 363 | <div class="cell medium-2 show-for-medium text-center"> |
| 350 | - <?php echo $cnameStatus; ?> | |
| 364 | + <?php $this->displayCnameStatus($cnameRecord); ?> | |
| 351 | 365 | </div> |
| 352 | 366 | </div> |
| 353 | 367 | <?php } ?> |
| 354 | 368 | </div> |
| @@ -355,15 +369,19 @@ | ||
| 355 | 369 | </div> |
| 356 | 370 | </div> |
| 357 | 371 | <?php |
| 358 | 372 | $modalContent = ob_get_clean(); |
| 359 | - $buttonModal = acym_tooltip( | |
| 373 | + ob_start(); | |
| 374 | + acym_tooltip( | |
| 360 | 375 | [ |
| 361 | - 'hoveredText' => '<i class="acymicon-cogs acym__config__acymailer__domain--settings cursor-pointer acym__color__blue" acym-data-domain="'.$domain['domain'].'"></i>', | |
| 376 | + 'hoveredText' => '<i class="acymicon-cogs acym__config__acymailer__domain--settings cursor-pointer acym__color__blue" acym-data-domain="'.esc_attr( | |
| 377 | + $domain['domain'] | |
| 378 | + ).'"></i>', | |
| 362 | 379 | 'textShownInTooltip' => acym_translation('ACYM_SHOW_DNS_SETTINGS'), |
| 363 | 380 | ] |
| 364 | 381 | ); |
| 365 | - echo acym_modal( | |
| 382 | + $buttonModal = ob_get_clean(); | |
| 383 | + acym_modal( | |
| 366 | 384 | $buttonModal, |
| 367 | 385 | $modalContent, |
| 368 | 386 | null, |
| 369 | 387 | [], |
| @@ -372,11 +390,11 @@ | ||
| 372 | 390 | true, |
| 373 | 391 | 'acym__config__acymailer__cname__modal__container' |
| 374 | 392 | ); |
| 375 | 393 | |
| 376 | - echo acym_tooltip( | |
| 394 | + acym_tooltip( | |
| 377 | 395 | [ |
| 378 | - 'hoveredText' => '<i class="acymicon-delete acym__config__acymailer__domain--delete cursor-pointer" acym-data-domain="'.acym_escape( | |
| 396 | + 'hoveredText' => '<i class="acymicon-delete acym__config__acymailer__domain--delete cursor-pointer" acym-data-domain="'.esc_attr( | |
| 379 | 397 | $domain['domain'] |
| 380 | 398 | ).'"></i>', |
| 381 | 399 | 'textShownInTooltip' => acym_translation('ACYM_DELETE'), |
| 382 | 400 | ] |
| @@ -391,19 +409,19 @@ | ||
| 391 | 409 | </div> |
| 392 | 410 | <div class="cell grid-x acym_vcenter acym__sending__methods__one__settings padding-top-1"> |
| 393 | 411 | <div class="cell grid-x"> |
| 394 | 412 | <div class="cell small-7 medium-4 large-3 margin-next-1"> |
| 395 | - <input id="<?php echo self::SENDING_METHOD_ID; ?>_domain" | |
| 396 | - class="cell medium-6 large-4 xlarge-3" | |
| 397 | - type="text" | |
| 398 | - autocomplete="off" | |
| 399 | - value=""> | |
| 400 | - <span id="<?php echo self::SENDING_METHOD_ID; ?>_domain_error" class="medium-6 large-4 xlarge-3"></span> | |
| 413 | + <input id="<?php echo esc_attr(self::SENDING_METHOD_ID); ?>_domain" | |
| 414 | + class="cell medium-6 large-4 xlarge-3" | |
| 415 | + type="text" | |
| 416 | + autocomplete="off" | |
| 417 | + value=""> | |
| 418 | + <span id="<?php echo esc_attr(self::SENDING_METHOD_ID); ?>_domain_error" class="medium-6 large-4 xlarge-3"></span> | |
| 401 | 419 | <?php |
| 402 | 420 | if (!empty($unverifiedDomains)) { ?> |
| 403 | 421 | <span id="acym__acymailer__unverifiedDomains"> |
| 404 | 422 | <?php foreach ($unverifiedDomains as $oneDomain) { ?> |
| 405 | - <span class="acym__acymailer__oneSuggestion"><?php echo $oneDomain; ?></span> | |
| 423 | + <span class="acym__acymailer__oneSuggestion"><?php echo esc_html($oneDomain); ?></span> | |
| 406 | 424 | <?php } ?> |
| 407 | 425 | </span> |
| 408 | 426 | <?php } ?> |
| 409 | 427 | </div> |
| @@ -408,11 +426,11 @@ | ||
| 408 | 426 | <?php } ?> |
| 409 | 427 | </div> |
| 410 | 428 | <div id="acym__configuration__sending__method_addDomain_submit" class="cell grid-x small-4 medium-6 large-8 acym_vcenter"> |
| 411 | 429 | <button type="button" |
| 412 | - id="acym__configuration__sending__method-addDomain" | |
| 413 | - class="cell shrink button button-secondary"> | |
| 414 | - <?php echo acym_translation('ACYM_ADD_A_DOMAIN'); ?> | |
| 430 | + id="acym__configuration__sending__method-addDomain" | |
| 431 | + class="cell shrink button button-secondary"> | |
| 432 | + <?php echo esc_html(acym_translation('ACYM_ADD_A_DOMAIN')); ?> | |
| 415 | 433 | </button> |
| 416 | 434 | <i class="margin-left-1 acym_vcenter acymicon-circle-o-notch acymicon-spin is-hidden" |
| 417 | 435 | id="acym__configuration__sending__method_add_domain-wait"></i> |
| 418 | 436 | <div class="cell shrink grid-x acym_vcenter" id="acym__configuration__acymailer__add__error"> |
| @@ -424,9 +442,9 @@ | ||
| 424 | 442 | </div> |
| 425 | 443 | <?php if (!$this->isLogFileEmpty()) { ?> |
| 426 | 444 | <div class="cell grid-x acym__sending__methods__log"> |
| 427 | 445 | <?php |
| 428 | - echo acym_modal( | |
| 446 | + acym_modal( | |
| 429 | 447 | acym_translation('ACYM_REPORT_SEE'), |
| 430 | 448 | '', |
| 431 | 449 | null, |
| 432 | 450 | [], |
| @@ -442,9 +460,8 @@ | ||
| 442 | 460 | <?php } ?> |
| 443 | 461 | </div> |
| 444 | 462 | </div> |
| 445 | 463 | <?php |
| 446 | - $data['sendingMethodsHtmlSettings'][self::SENDING_METHOD_ID] = ob_get_clean(); | |
| 447 | 464 | } |
| 448 | 465 | |
| 449 | 466 | public function onAcymTestCredentialSendingMethod($sendingMethod, $credentials) |
| 450 | 467 | { |
| @@ -510,8 +527,9 @@ | ||
| 510 | 527 | |
| 511 | 528 | return; |
| 512 | 529 | } |
| 513 | 530 | |
| 531 | + // In Amazon SES, you must verify each identity used as a "From", "Source", "Sender", or "Return-Path" address. | |
| 514 | 532 | $domainsUsed = [ |
| 515 | 533 | acym_getDomain($from['email']), |
| 516 | 534 | acym_getDomain($replyTo['email']), |
| 517 | 535 | ]; |
| @@ -521,8 +539,9 @@ | ||
| 521 | 539 | } |
| 522 | 540 | |
| 523 | 541 | $domainsUsed = array_unique($domainsUsed); |
| 524 | 542 | |
| 543 | + // Maybe don't try to send if one of these domains is not validated? | |
| 525 | 544 | $verifiedDomains = $this->getVerifiedDomains(); |
| 526 | 545 | |
| 527 | 546 | $unverifiedDomains = array_diff($domainsUsed, $verifiedDomains); |
| 528 | 547 | if (!empty($unverifiedDomains)) { |
| @@ -572,8 +591,9 @@ | ||
| 572 | 591 | $response['message'] .= acym_translation('ACYM_GET_MORE_CREDITS'); |
| 573 | 592 | $response['message'] .= '</a>'; |
| 574 | 593 | } |
| 575 | 594 | |
| 595 | + // Don't unsubscribe/remove recipients if the error isn't related to them | |
| 576 | 596 | if (!empty($responseMailer['code']) && in_array($responseMailer['code'], [18, 26, 28])) { |
| 577 | 597 | $mailerHelper->failedCounting = false; |
| 578 | 598 | } |
| 579 | 599 | |
| @@ -701,9 +721,17 @@ | ||
| 701 | 721 | acym_sendAjaxResponse($message, [], false); |
| 702 | 722 | } elseif (!empty($responseApi['message']) && $responseApi['message'] === 'Invalid private key') { |
| 703 | 723 | acym_sendAjaxResponse(acym_translation('ACYM_AUTHENTICATION_FAILS_WITH_API_KEY'), [], false); |
| 704 | 724 | } elseif (!$this->checkSuccessCode($this->responseCode) && (empty($responseApi['code']) || !in_array($responseApi['code'], [5, 4, 3]))) { |
| 725 | + /* | |
| 726 | + We may ask the API for the deletion of a domain while: | |
| 727 | + - it already doesn't exist (error code 5) | |
| 728 | + - it doesn't belong to the current API key (error code 4) | |
| 729 | + - it isn't linked to this website (error code 3) | |
| 705 | 730 | |
| 731 | + 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 | |
| 732 | + */ | |
| 733 | + | |
| 706 | 734 | $message = acym_translation('ACYM_ERROR_ON_CALL_ACYBA_WEBSITE').': '.$this->translate($responseApi); |
| 707 | 735 | if (!empty($responseApi['logs'])) { |
| 708 | 736 | acym_logError($responseApi['logs'], self::SENDING_METHOD_ID); |
| 709 | 737 | } |
| @@ -855,8 +883,9 @@ | ||
| 855 | 883 | $creditsShowed = $response['remaining_credits']; |
| 856 | 884 | |
| 857 | 885 | if (!empty($response['is_multisite'])) { |
| 858 | 886 | $fromEmail = $this->config->get('from_email', ''); |
| 887 | + // If the license is multisite we check and increment credits on the domain of the from email | |
| 859 | 888 | $domain = explode('@', $fromEmail)[1]; |
| 860 | 889 | |
| 861 | 890 | if (empty($domain) || empty($response['domains'][$domain])) { |
| 862 | 891 | $html = acym_translation('ACYM_DOMAIN_FROM_EMAIL_NOT_VALID_ASS'); |
| @@ -870,26 +899,38 @@ | ||
| 870 | 899 | } |
| 871 | 900 | } |
| 872 | 901 | } |
| 873 | 902 | |
| 903 | + // Add security empty text message | |
| 874 | 904 | if (empty($creditsShowed)) { |
| 875 | 905 | $creditsShowed = '0'; |
| 876 | 906 | } |
| 907 | + | |
| 908 | + ob_start(); | |
| 909 | + acym_tooltip( | |
| 910 | + [ | |
| 911 | + 'hoveredText' => $creditsShowed, | |
| 912 | + 'textShownInTooltip' => acym_translation('ACYM_GET_MORE_CREDITS'), | |
| 913 | + 'classContainer' => 'credits_remaining', | |
| 914 | + 'link' => ACYM_ACYMAILING_WEBSITE, | |
| 915 | + ] | |
| 916 | + ); | |
| 917 | + $tooltip = ob_get_clean(); | |
| 877 | 918 | $html = acym_translationSprintf( |
| 878 | 919 | 'ACYM_SENDING_METHOD_X_UNITY', |
| 879 | 920 | self::SENDING_METHOD_NAME, |
| 880 | - acym_tooltip( | |
| 881 | - [ | |
| 882 | - 'hoveredText' => $creditsShowed, | |
| 883 | - 'textShownInTooltip' => acym_translation('ACYM_GET_MORE_CREDITS'), | |
| 884 | - 'classContainer' => 'credits_remaining', | |
| 885 | - 'link' => ACYM_ACYMAILING_WEBSITE, | |
| 886 | - ] | |
| 887 | - ), | |
| 888 | - '<span class="acym_not_bold">'.acym_translation($unityTranslation).'</span>' | |
| 921 | + $tooltip, | |
| 922 | + '<span class="acym_not_bold">'.esc_html(acym_translation($unityTranslation)).'</span>' | |
| 889 | 923 | ); |
| 890 | 924 | } |
| 891 | 925 | |
| 926 | + /** | |
| 927 | + * Called before loading the emails of a batch to get the credits left | |
| 928 | + * | |
| 929 | + * @param int $creditsLeft | |
| 930 | + * | |
| 931 | + * @return void | |
| 932 | + */ | |
| 892 | 933 | public function onAcymCreditsLeft(&$creditsLeft) |
| 893 | 934 | { |
| 894 | 935 | $sendingMethod = $this->config->get('mailer_method', ''); |
| 895 | 936 | if (empty($sendingMethod) || $sendingMethod != self::SENDING_METHOD_ID) return; |
| @@ -952,8 +993,9 @@ | ||
| 952 | 993 | if ($this->config->get('mailer_method') !== self::SENDING_METHOD_ID) { |
| 953 | 994 | return []; |
| 954 | 995 | } |
| 955 | 996 | |
| 997 | + // In Amazon SES, you must verify each identity used as a "From", "Source", "Sender", or "Return-Path" address. | |
| 956 | 998 | $allDomains = []; |
| 957 | 999 | |
| 958 | 1000 | $allDomains[] = acym_getDomain($this->config->get('from_email')); |
| 959 | 1001 | if ($this->config->get('from_as_replyto') === '0') { |
| @@ -978,39 +1020,46 @@ | ||
| 978 | 1020 | |
| 979 | 1021 | return array_diff($allDomains, $verifiedDomains); |
| 980 | 1022 | } |
| 981 | 1023 | |
| 982 | - private function getRateColor($rate, $allowedRate, $warningRate): array | |
| 1024 | + private function getRateColor(float $rate, float $allowedRate, float $warningRate): string | |
| 983 | 1025 | { |
| 984 | 1026 | if (empty($rate) || empty($allowedRate) || empty($warningRate)) { |
| 985 | - return ['color' => '', 'icon' => '']; | |
| 1027 | + return ''; | |
| 986 | 1028 | } |
| 987 | 1029 | |
| 988 | 1030 | if ($rate > $allowedRate) { |
| 989 | - return [ | |
| 990 | - 'color' => 'acym__color__red', | |
| 991 | - 'icon' => acym_tooltip( | |
| 992 | - [ | |
| 993 | - 'hoveredText' => '<i class="acym__config__acymailer__rate-status__icon acymicon-close acym__color__red"></i>', | |
| 994 | - 'textShownInTooltip' => acym_translation('ACYM_RATE_BLOCKED'), | |
| 995 | - ] | |
| 996 | - ), | |
| 997 | - ]; | |
| 1031 | + return 'acym__color__red'; | |
| 998 | 1032 | } elseif ($rate >= $warningRate) { |
| 999 | - return [ | |
| 1000 | - 'color' => 'acym__color__orange', | |
| 1001 | - 'icon' => acym_tooltip( | |
| 1002 | - [ | |
| 1003 | - 'hoveredText' => '<i class="acym__config__acymailer__rate-status__icon acymicon-exclamation-triangle acym__color__orange"></i>', | |
| 1004 | - 'textShownInTooltip' => acym_translation('ACYM_RATE_WARNING'), | |
| 1005 | - ] | |
| 1006 | - ), | |
| 1007 | - ]; | |
| 1033 | + return 'acym__color__orange'; | |
| 1008 | 1034 | } |
| 1009 | 1035 | |
| 1010 | - return ['color' => '', 'icon' => '']; | |
| 1036 | + return ''; | |
| 1011 | 1037 | } |
| 1012 | 1038 | |
| 1039 | + private function displayRateIcon(float $rate, float $allowedRate, float $warningRate): void | |
| 1040 | + { | |
| 1041 | + if (empty($rate) || empty($allowedRate) || empty($warningRate)) { | |
| 1042 | + return; | |
| 1043 | + } | |
| 1044 | + | |
| 1045 | + if ($rate > $allowedRate) { | |
| 1046 | + acym_tooltip( | |
| 1047 | + [ | |
| 1048 | + 'hoveredText' => '<i class="acym__config__acymailer__rate-status__icon acymicon-close acym__color__red"></i>', | |
| 1049 | + 'textShownInTooltip' => acym_translation('ACYM_RATE_BLOCKED'), | |
| 1050 | + ] | |
| 1051 | + ); | |
| 1052 | + } elseif ($rate >= $warningRate) { | |
| 1053 | + acym_tooltip( | |
| 1054 | + [ | |
| 1055 | + 'hoveredText' => '<i class="acym__config__acymailer__rate-status__icon acymicon-exclamation-triangle acym__color__orange"></i>', | |
| 1056 | + 'textShownInTooltip' => acym_translation('ACYM_RATE_WARNING'), | |
| 1057 | + ] | |
| 1058 | + ); | |
| 1059 | + } | |
| 1060 | + } | |
| 1061 | + | |
| 1013 | 1062 | private function updateDomainRates($domainsRates) |
| 1014 | 1063 | { |
| 1015 | 1064 | $domains = $this->config->get(self::SENDING_METHOD_ID.'_domains', []); |
| 1016 | 1065 | |
| @@ -1086,8 +1135,9 @@ | ||
| 1086 | 1135 | } |
| 1087 | 1136 | |
| 1088 | 1137 | private function checkSuccessCode($responseCode): bool |
| 1089 | 1138 | { |
| 1139 | + // we can add more success response codes if needed but for now, that's all the success response codes the API can send | |
| 1090 | 1140 | return in_array($responseCode, [200, 201]); |
| 1091 | 1141 | } |
| 1092 | 1142 | |
| 1093 | 1143 | private function translate($response) |
| @@ -1129,8 +1179,19 @@ | ||
| 1129 | 1179 | |
| 1130 | 1180 | return $finalMessage; |
| 1131 | 1181 | } |
| 1132 | 1182 | |
| 1183 | + /** | |
| 1184 | + * Emails not needing an unsubscribe link: | |
| 1185 | + * - Sending a test from config, from campaign tab or from editor | |
| 1186 | + * - Forwarding a bounce message | |
| 1187 | + * - Sending a spam-test | |
| 1188 | + * - Overriding website emails | |
| 1189 | + * - Sending notification messages | |
| 1190 | + * - Unsubscribe emails | |
| 1191 | + * - Sending the walkthrough email | |
| 1192 | + * - Forwarding an email to a specific address from mailbox actions | |
| 1193 | + */ | |
| 1133 | 1194 | private function isUnsubscribeLinkMissing($mailerHelper): bool |
| 1134 | 1195 | { |
| 1135 | 1196 | if ($mailerHelper->isTest || $mailerHelper->isForward || $mailerHelper->isSpamTest || empty($mailerHelper->mail)) { |
| 1136 | 1197 | return false; |
| @@ -1155,13 +1216,15 @@ | ||
| 1155 | 1216 | private function checkDomainsDNS($domains): array |
| 1156 | 1217 | { |
| 1157 | 1218 | $remainingDomains = []; |
| 1158 | 1219 | foreach ($domains as $oneDomain) { |
| 1220 | + // No DNS entries yet, we have to check the domain to get DNS entries | |
| 1159 | 1221 | if (empty($oneDomain['CnameRecords'])) { |
| 1160 | 1222 | $remainingDomains[] = $oneDomain; |
| 1161 | 1223 | continue; |
| 1162 | 1224 | } |
| 1163 | 1225 | |
| 1226 | + // Check if all DNS entries are valid before calling the API | |
| 1164 | 1227 | foreach ($oneDomain['CnameRecords'] as $oneRecord) { |
| 1165 | 1228 | if (!$this->checkCnameEntry($oneRecord['name'], $oneRecord['value'])) { |
| 1166 | 1229 | $domainPosition = strpos($oneRecord['name'], '_domainkey') + 11; |
| 1167 | 1230 | $domainName = substr($oneRecord['name'], $domainPosition); |
| @@ -1217,6 +1280,20 @@ | ||
| 1217 | 1280 | |
| 1218 | 1281 | $this->cnameErrors[] = acym_translation('ACYM_DNS_NOT_CNAME'); |
| 1219 | 1282 | |
| 1220 | 1283 | return false; |
| 1284 | + } | |
| 1285 | + | |
| 1286 | + private function displayCnameStatus(array $cnameRecord): void | |
| 1287 | + { | |
| 1288 | + if ($cnameRecord['isValid']) { | |
| 1289 | + echo '<i class="acym__config__acymailer__status__icon acymicon-check-circle acym__color__green"></i>'; | |
| 1290 | + } else { | |
| 1291 | + acym_tooltip( | |
| 1292 | + [ | |
| 1293 | + 'hoveredText' => '<i class="acym__config__acymailer__status__icon acymicon-close acym__color__red"></i>', | |
| 1294 | + 'textShownInTooltip' => implode('<br/>', $cnameRecord['tooltipMessages']), | |
| 1295 | + ] | |
| 1296 | + ); | |
| 1297 | + } | |
| 1221 | 1298 | } |
| 1222 | 1299 | } |