1: <?php
2: namespace Opencart\Catalog\Controller\Mail;
3: /**
4: * Class Order
5: *
6: * @package Opencart\Catalog\Controller\Mail
7: */
8: class Order extends \Opencart\System\Engine\Controller {
9: /**
10: * Mail class for orders
11: *
12: * Trigger catalog/model/checkout/order/addHistory/before
13: *
14: * @param string $route
15: * @param array<int, mixed> $args
16: *
17: * @return void
18: */
19: public function index(string &$route, array &$args): void {
20: if (isset($args[0])) {
21: $order_id = $args[0];
22: } else {
23: $order_id = 0;
24: }
25:
26: if (isset($args[1])) {
27: $order_status_id = $args[1];
28: } else {
29: $order_status_id = 0;
30: }
31:
32: if (isset($args[2])) {
33: $comment = $args[2];
34: } else {
35: $comment = '';
36: }
37:
38: if (isset($args[3])) {
39: $notify = $args[3];
40: } else {
41: $notify = '';
42: }
43:
44: // We need to grab the old order status ID
45: $order_info = $this->model_checkout_order->getOrder($order_id);
46:
47: if ($order_info) {
48: // If the order status returns 0, then it becomes greater than 0. Therefore, we send the default html email
49: if (!$order_info['order_status_id'] && $order_status_id) {
50: $this->add($order_info, $order_status_id, $comment, $notify);
51: }
52:
53: // If the order status does not return 0, we send the update as a text email
54: if ($order_info['order_status_id'] && $order_status_id && $notify) {
55: $this->history($order_info, $order_status_id, $comment, $notify);
56: }
57: }
58: }
59:
60: /**
61: * @param array<string, mixed> $order_info
62: * @param int $order_status_id
63: * @param string $comment
64: * @param bool $notify
65: *
66: * @throws \Exception
67: *
68: * @return void
69: */
70: public function add(array $order_info, int $order_status_id, string $comment, bool $notify): void {
71: // Check for any downloadable products
72: $download_status = false;
73:
74: $order_products = $this->model_checkout_order->getProducts($order_info['order_id']);
75:
76: foreach ($order_products as $order_product) {
77: // Check if there are any linked downloads
78: $product_download_query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "product_to_download` WHERE `product_id` = '" . (int)$order_product['product_id'] . "'");
79:
80: if ($product_download_query->row['total']) {
81: $download_status = true;
82: }
83: }
84:
85: $store_logo = html_entity_decode($this->config->get('config_logo'), ENT_QUOTES, 'UTF-8');
86: $store_name = html_entity_decode($this->config->get('config_name'), ENT_QUOTES, 'UTF-8');
87:
88: if (!defined('HTTP_CATALOG')) {
89: $store_url = HTTP_SERVER;
90: } else {
91: $store_url = HTTP_CATALOG;
92: }
93:
94: $this->load->model('setting/store');
95:
96: $store_info = $this->model_setting_store->getStore($order_info['store_id']);
97:
98: if ($store_info) {
99: $this->load->model('setting/setting');
100:
101: $store_logo = html_entity_decode($this->model_setting_setting->getValue('config_logo', $store_info['store_id']), ENT_QUOTES, 'UTF-8');
102: $store_name = html_entity_decode($store_info['name'], ENT_QUOTES, 'UTF-8');
103: $store_url = $store_info['url'];
104: }
105:
106: $this->load->model('localisation/language');
107:
108: $language_info = $this->model_localisation_language->getLanguage($order_info['language_id']);
109:
110: if ($language_info) {
111: $language_code = $language_info['code'];
112: } else {
113: $language_code = $this->config->get('config_language');
114: }
115:
116: // Load the language for any mails using a different country code and prefixing it so it does not pollute the main data pool.
117: $this->load->language('default', 'mail', $language_code);
118: $this->load->language('mail/order_add', 'mail', $language_code);
119:
120: // Add language vars to the template folder
121: $results = $this->language->all('mail');
122:
123: foreach ($results as $key => $value) {
124: $data[$key] = $value;
125: }
126:
127: $subject = sprintf($this->language->get('mail_text_subject'), $store_name, $order_info['order_id']);
128:
129: $this->load->model('tool/image');
130:
131: if (is_file(DIR_IMAGE . $store_logo)) {
132: $data['logo'] = $store_url . 'image/' . $store_logo;
133: } else {
134: $data['logo'] = '';
135: }
136:
137: $data['title'] = sprintf($this->language->get('mail_text_subject'), $store_name, $order_info['order_id']);
138:
139: $data['text_greeting'] = sprintf($this->language->get('mail_text_greeting'), $order_info['store_name']);
140:
141: $data['store'] = $store_name;
142: $data['store_url'] = $order_info['store_url'];
143:
144: $data['customer_id'] = $order_info['customer_id'];
145: $data['link'] = $order_info['store_url'] . 'index.php?route=account/order.info&order_id=' . $order_info['order_id'];
146:
147: if ($download_status) {
148: $data['download'] = $order_info['store_url'] . 'index.php?route=account/download';
149: } else {
150: $data['download'] = '';
151: }
152:
153: $data['order_id'] = $order_info['order_id'];
154: $data['date_added'] = date($this->language->get('date_format_short'), strtotime($order_info['date_added']));
155: $data['payment_method'] = $order_info['payment_method']['name'] ?? '';
156: $data['shipping_method'] = $order_info['shipping_method']['name'] ?? '';
157: $data['email'] = $order_info['email'];
158: $data['telephone'] = $order_info['telephone'];
159: $data['ip'] = $order_info['ip'];
160:
161: $order_status_query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "order_status` WHERE `order_status_id` = '" . (int)$order_status_id . "' AND `language_id` = '" . (int)$order_info['language_id'] . "'");
162:
163: if ($order_status_query->num_rows) {
164: $data['order_status'] = $order_status_query->row['name'];
165: } else {
166: $data['order_status'] = '';
167: }
168:
169: $data['comment'] = nl2br($order_info['comment']);
170:
171: // Payment Address
172: if ($order_info['payment_address_format']) {
173: $format = $order_info['payment_address_format'];
174: } else {
175: $format = '{firstname} {lastname}' . "\n" . '{company}' . "\n" . '{address_1}' . "\n" . '{address_2}' . "\n" . '{city} {postcode}' . "\n" . '{zone}' . "\n" . '{country}';
176: }
177:
178: $find = [
179: '{firstname}',
180: '{lastname}',
181: '{company}',
182: '{address_1}',
183: '{address_2}',
184: '{city}',
185: '{postcode}',
186: '{zone}',
187: '{zone_code}',
188: '{country}'
189: ];
190:
191: $replace = [
192: 'firstname' => $order_info['payment_firstname'],
193: 'lastname' => $order_info['payment_lastname'],
194: 'company' => $order_info['payment_company'],
195: 'address_1' => $order_info['payment_address_1'],
196: 'address_2' => $order_info['payment_address_2'],
197: 'city' => $order_info['payment_city'],
198: 'postcode' => $order_info['payment_postcode'],
199: 'zone' => $order_info['payment_zone'],
200: 'zone_code' => $order_info['payment_zone_code'],
201: 'country' => $order_info['payment_country']
202: ];
203:
204: $pattern_1 = [
205: "\r\n",
206: "\r",
207: "\n"
208: ];
209:
210: $pattern_2 = [
211: "/\\s\\s+/",
212: "/\r\r+/",
213: "/\n\n+/"
214: ];
215:
216: $data['payment_address'] = str_replace($pattern_1, '<br/>', preg_replace($pattern_2, '<br/>', trim(str_replace($find, $replace, $format))));
217:
218: // Shipping Address
219: if ($order_info['shipping_address_format']) {
220: $format = $order_info['shipping_address_format'];
221: } else {
222: $format = '{firstname} {lastname}' . "\n" . '{company}' . "\n" . '{address_1}' . "\n" . '{address_2}' . "\n" . '{city} {postcode}' . "\n" . '{zone}' . "\n" . '{country}';
223: }
224:
225: $find = [
226: '{firstname}',
227: '{lastname}',
228: '{company}',
229: '{address_1}',
230: '{address_2}',
231: '{city}',
232: '{postcode}',
233: '{zone}',
234: '{zone_code}',
235: '{country}'
236: ];
237:
238: $replace = [
239: 'firstname' => $order_info['shipping_firstname'],
240: 'lastname' => $order_info['shipping_lastname'],
241: 'company' => $order_info['shipping_company'],
242: 'address_1' => $order_info['shipping_address_1'],
243: 'address_2' => $order_info['shipping_address_2'],
244: 'city' => $order_info['shipping_city'],
245: 'postcode' => $order_info['shipping_postcode'],
246: 'zone' => $order_info['shipping_zone'],
247: 'zone_code' => $order_info['shipping_zone_code'],
248: 'country' => $order_info['shipping_country']
249: ];
250:
251: $data['shipping_address'] = str_replace($pattern_1, '<br/>', preg_replace($pattern_2, '<br/>', trim(str_replace($find, $replace, $format))));
252:
253: $this->load->model('tool/upload');
254:
255: // Products
256: $data['products'] = [];
257:
258: foreach ($order_products as $order_product) {
259: $option_data = [];
260:
261: $order_options = $this->model_checkout_order->getOptions($order_info['order_id'], $order_product['order_product_id']);
262:
263: foreach ($order_options as $order_option) {
264: if ($order_option['type'] != 'file') {
265: $value = $order_option['value'];
266: } else {
267: $upload_info = $this->model_tool_upload->getUploadByCode($order_option['value']);
268:
269: if ($upload_info) {
270: $value = $upload_info['name'];
271: } else {
272: $value = '';
273: }
274: }
275:
276: $option_data[] = [
277: 'name' => $order_option['name'],
278: 'value' => (oc_strlen($value) > 20 ? oc_substr($value, 0, 20) . '..' : $value)
279: ];
280: }
281:
282: $description = '';
283:
284: $this->load->model('checkout/order');
285:
286: $subscription_info = $this->model_checkout_order->getSubscription($order_info['order_id'], $order_product['order_product_id']);
287:
288: if ($subscription_info) {
289: if ($subscription_info['trial_status']) {
290: $trial_price = $this->currency->format($subscription_info['trial_price'] + ($this->config->get('config_tax') ? $subscription_info['trial_tax'] : 0), $order_info['currency_code'], $order_info['currency_value']);
291: $trial_cycle = $subscription_info['trial_cycle'];
292: $trial_frequency = $this->language->get('text_' . $subscription_info['trial_frequency']);
293: $trial_duration = $subscription_info['trial_duration'];
294:
295: $description .= sprintf($this->language->get('text_subscription_trial'), $trial_price, $trial_cycle, $trial_frequency, $trial_duration);
296: }
297:
298: $price = $this->currency->format($subscription_info['price'] + ($this->config->get('config_tax') ? $subscription_info['tax'] : 0), $order_info['currency_code'], $order_info['currency_value']);
299: $cycle = $subscription_info['cycle'];
300: $frequency = $this->language->get('text_' . $subscription_info['frequency']);
301: $duration = $subscription_info['duration'];
302:
303: if ($duration) {
304: $description .= sprintf($this->language->get('text_subscription_duration'), $price, $cycle, $frequency, $duration);
305: } else {
306: $description .= sprintf($this->language->get('text_subscription_cancel'), $price, $cycle, $frequency);
307: }
308: }
309:
310: $data['products'][] = [
311: 'name' => $order_product['name'],
312: 'model' => $order_product['model'],
313: 'option' => $option_data,
314: 'subscription' => $description,
315: 'quantity' => $order_product['quantity'],
316: 'price' => $this->currency->format($order_product['price'] + ($this->config->get('config_tax') ? $order_product['tax'] : 0), $order_info['currency_code'], $order_info['currency_value']),
317: 'total' => $this->currency->format($order_product['total'] + ($this->config->get('config_tax') ? ($order_product['tax'] * $order_product['quantity']) : 0), $order_info['currency_code'], $order_info['currency_value']),
318: 'reward' => $order_product['reward']
319: ];
320: }
321:
322: // Vouchers
323: $data['vouchers'] = [];
324:
325: $order_vouchers = $this->model_checkout_order->getVouchers($order_info['order_id']);
326:
327: foreach ($order_vouchers as $order_voucher) {
328: $data['vouchers'][] = [
329: 'description' => $order_voucher['description'],
330: 'amount' => $this->currency->format($order_voucher['amount'], $order_info['currency_code'], $order_info['currency_value']),
331: ];
332: }
333:
334: // Order Totals
335: $data['totals'] = [];
336:
337: $order_totals = $this->model_checkout_order->getTotals($order_info['order_id']);
338:
339: foreach ($order_totals as $order_total) {
340: $data['totals'][] = [
341: 'title' => $order_total['title'],
342: 'text' => $this->currency->format($order_total['value'], $order_info['currency_code'], $order_info['currency_value']),
343: ];
344: }
345:
346: $this->load->model('setting/setting');
347:
348: $from = $this->model_setting_setting->getValue('config_email', $order_info['store_id']);
349:
350: if (!$from) {
351: $from = $this->config->get('config_email');
352: }
353:
354: if ($this->config->get('config_mail_engine')) {
355: $mail_option = [
356: 'parameter' => $this->config->get('config_mail_parameter'),
357: 'smtp_hostname' => $this->config->get('config_mail_smtp_hostname'),
358: 'smtp_username' => $this->config->get('config_mail_smtp_username'),
359: 'smtp_password' => html_entity_decode($this->config->get('config_mail_smtp_password'), ENT_QUOTES, 'UTF-8'),
360: 'smtp_port' => $this->config->get('config_mail_smtp_port'),
361: 'smtp_timeout' => $this->config->get('config_mail_smtp_timeout')
362: ];
363:
364: $mail = new \Opencart\System\Library\Mail($this->config->get('config_mail_engine'), $mail_option);
365: $mail->setTo($order_info['email']);
366: $mail->setFrom($from);
367: $mail->setSender($store_name);
368: $mail->setSubject($subject);
369: $mail->setHtml($this->load->view('mail/order_add', $data));
370: $mail->send();
371: }
372: }
373:
374: /**
375: * catalog/model/checkout/order/addHistory/before
376: *
377: * @param array<string, mixed> $order_info
378: * @param int $order_status_id
379: * @param string $comment
380: * @param bool $notify
381: *
382: * @throws \Exception
383: *
384: * @return void
385: */
386: public function history(array $order_info, int $order_status_id, string $comment, bool $notify): void {
387: $store_name = html_entity_decode($this->config->get('config_name'), ENT_QUOTES, 'UTF-8');
388:
389: if (!defined('HTTP_CATALOG')) {
390: $store_url = HTTP_SERVER;
391: } else {
392: $store_url = HTTP_CATALOG;
393: }
394:
395: $this->load->model('setting/store');
396:
397: $store_info = $this->model_setting_store->getStore($order_info['store_id']);
398:
399: if ($store_info) {
400: $store_name = html_entity_decode($store_info['name'], ENT_QUOTES, 'UTF-8');
401: $store_url = $store_info['url'];
402: }
403:
404: $this->load->model('localisation/language');
405:
406: $language_info = $this->model_localisation_language->getLanguage($order_info['language_id']);
407:
408: if ($language_info) {
409: $language_code = $language_info['code'];
410: } else {
411: $language_code = $this->config->get('config_language');
412: }
413:
414: // Load the language for any mails using a different country code and prefixing it so it does not pollute the main data pool.
415: $this->load->language('default', 'mail', $language_code);
416: $this->load->language('mail/order_edit', 'mail', $language_code);
417:
418: // Add language vars to the template folder
419: $results = $this->language->all('mail');
420:
421: foreach ($results as $key => $value) {
422: $data[$key] = $value;
423: }
424:
425: $subject = sprintf($this->language->get('mail_text_subject'), $store_name, $order_info['order_id']);
426:
427: $data['order_id'] = $order_info['order_id'];
428: $data['date_added'] = date($this->language->get('date_format_short'), strtotime($order_info['date_added']));
429:
430: $order_status_query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "order_status` WHERE `order_status_id` = '" . (int)$order_status_id . "' AND `language_id` = '" . (int)$order_info['language_id'] . "'");
431:
432: if ($order_status_query->num_rows) {
433: $data['order_status'] = $order_status_query->row['name'];
434: } else {
435: $data['order_status'] = '';
436: }
437:
438: if ($order_info['customer_id']) {
439: $data['link'] = $order_info['store_url'] . 'index.php?route=account/order.info&order_id=' . $order_info['order_id'];
440: } else {
441: $data['link'] = '';
442: }
443:
444: $data['comment'] = strip_tags($comment);
445:
446: $data['store'] = $store_name;
447: $data['store_url'] = $store_url;
448:
449: $this->load->model('setting/setting');
450:
451: $from = $this->model_setting_setting->getValue('config_email', $order_info['store_id']);
452:
453: if (!$from) {
454: $from = $this->config->get('config_email');
455: }
456:
457: if ($this->config->get('config_mail_engine')) {
458: $mail_option = [
459: 'parameter' => $this->config->get('config_mail_parameter'),
460: 'smtp_hostname' => $this->config->get('config_mail_smtp_hostname'),
461: 'smtp_username' => $this->config->get('config_mail_smtp_username'),
462: 'smtp_password' => html_entity_decode($this->config->get('config_mail_smtp_password'), ENT_QUOTES, 'UTF-8'),
463: 'smtp_port' => $this->config->get('config_mail_smtp_port'),
464: 'smtp_timeout' => $this->config->get('config_mail_smtp_timeout')
465: ];
466:
467: $mail = new \Opencart\System\Library\Mail($this->config->get('config_mail_engine'), $mail_option);
468: $mail->setTo($order_info['email']);
469: $mail->setFrom($from);
470: $mail->setSender($store_name);
471: $mail->setSubject($subject);
472: $mail->setHtml($this->load->view('mail/order_history', $data));
473: $mail->send();
474: }
475: }
476:
477: /**
478: * @param string $route
479: * @param array<int, mixed> $args
480: *
481: * Event called catalog/model/checkout/order/addHistory/before
482: *
483: * @throws \Exception
484: *
485: * @return void
486: */
487: public function alert(string &$route, array &$args): void {
488: if (isset($args[0])) {
489: $order_id = $args[0];
490: } else {
491: $order_id = 0;
492: }
493:
494: if (isset($args[1])) {
495: $order_status_id = $args[1];
496: } else {
497: $order_status_id = 0;
498: }
499:
500: if (isset($args[2])) {
501: $comment = $args[2];
502: } else {
503: $comment = '';
504: }
505:
506: if (isset($args[3])) {
507: $notify = $args[3];
508: } else {
509: $notify = '';
510: }
511:
512: $order_info = $this->model_checkout_order->getOrder($order_id);
513:
514: if ($order_info && !$order_info['order_status_id'] && $order_status_id && in_array('order', (array)$this->config->get('config_mail_alert'))) {
515: $this->load->language('mail/order_alert');
516:
517: $subject = html_entity_decode(sprintf($this->language->get('text_subject'), $this->config->get('config_name'), $order_info['order_id']), ENT_QUOTES, 'UTF-8');
518:
519: $data['order_id'] = $order_info['order_id'];
520: $data['date_added'] = date($this->language->get('date_format_short'), strtotime($order_info['date_added']));
521:
522: $order_status_query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "order_status` WHERE `order_status_id` = '" . (int)$order_status_id . "' AND `language_id` = '" . (int)$this->config->get('config_language_id') . "'");
523:
524: if ($order_status_query->num_rows) {
525: $data['order_status'] = $order_status_query->row['name'];
526: } else {
527: $data['order_status'] = '';
528: }
529:
530: $this->load->model('tool/upload');
531:
532: $data['products'] = [];
533:
534: $order_products = $this->model_checkout_order->getProducts($order_id);
535:
536: foreach ($order_products as $order_product) {
537: $option_data = [];
538:
539: $order_options = $this->model_checkout_order->getOptions($order_info['order_id'], $order_product['order_product_id']);
540:
541: foreach ($order_options as $order_option) {
542: if ($order_option['type'] != 'file') {
543: $value = $order_option['value'];
544: } else {
545: $upload_info = $this->model_tool_upload->getUploadByCode($order_option['value']);
546:
547: if ($upload_info) {
548: $value = $upload_info['name'];
549: } else {
550: $value = '';
551: }
552: }
553:
554: $option_data[] = [
555: 'name' => $order_option['name'],
556: 'value' => (oc_strlen($value) > 20 ? oc_substr($value, 0, 20) . '..' : $value)
557: ];
558: }
559:
560: $description = '';
561:
562: $subscription_info = $this->model_checkout_order->getSubscription($order_info['order_id'], $order_product['order_product_id']);
563:
564: if ($subscription_info) {
565: if ($subscription_info['trial_status']) {
566: $trial_price = $this->currency->format($subscription_info['trial_price'] + ($this->config->get('config_tax') ? $subscription_info['trial_tax'] : 0), $this->session->data['currency']);
567: $trial_cycle = $subscription_info['trial_cycle'];
568: $trial_frequency = $this->language->get('text_' . $subscription_info['trial_frequency']);
569: $trial_duration = $subscription_info['trial_duration'];
570:
571: $description .= sprintf($this->language->get('text_subscription_trial'), $trial_price, $trial_cycle, $trial_frequency, $trial_duration);
572: }
573:
574: $price = $this->currency->format($subscription_info['price'] + ($this->config->get('config_tax') ? $subscription_info['tax'] : 0), $this->session->data['currency']);
575: $cycle = $subscription_info['cycle'];
576: $frequency = $this->language->get('text_' . $subscription_info['frequency']);
577: $duration = $subscription_info['duration'];
578:
579: if ($duration) {
580: $description .= sprintf($this->language->get('text_subscription_duration'), $price, $cycle, $frequency, $duration);
581: } else {
582: $description .= sprintf($this->language->get('text_subscription_cancel'), $price, $cycle, $frequency);
583: }
584: }
585:
586: $data['products'][] = [
587: 'name' => $order_product['name'],
588: 'model' => $order_product['model'],
589: 'quantity' => $order_product['quantity'],
590: 'option' => $option_data,
591: 'subscription' => $description,
592: 'total' => html_entity_decode($this->currency->format($order_product['total'] + ($this->config->get('config_tax') ? $order_product['tax'] * $order_product['quantity'] : 0), $order_info['currency_code'], $order_info['currency_value']), ENT_NOQUOTES, 'UTF-8')
593: ];
594: }
595:
596: $data['vouchers'] = [];
597:
598: $order_vouchers = $this->model_checkout_order->getVouchers($order_id);
599:
600: foreach ($order_vouchers as $order_voucher) {
601: $data['vouchers'][] = [
602: 'description' => $order_voucher['description'],
603: 'amount' => html_entity_decode($this->currency->format($order_voucher['amount'], $order_info['currency_code'], $order_info['currency_value']), ENT_NOQUOTES, 'UTF-8')
604: ];
605: }
606:
607: $data['totals'] = [];
608:
609: $order_totals = $this->model_checkout_order->getTotals($order_id);
610:
611: foreach ($order_totals as $order_total) {
612: $data['totals'][] = [
613: 'title' => $order_total['title'],
614: 'value' => html_entity_decode($this->currency->format($order_total['value'], $order_info['currency_code'], $order_info['currency_value']), ENT_NOQUOTES, 'UTF-8')
615: ];
616: }
617:
618: $data['comment'] = nl2br($order_info['comment']);
619:
620: $data['store'] = html_entity_decode($order_info['store_name'], ENT_QUOTES, 'UTF-8');
621: $data['store_url'] = $order_info['store_url'];
622:
623: if ($this->config->get('config_mail_engine')) {
624: $mail_option = [
625: 'parameter' => $this->config->get('config_mail_parameter'),
626: 'smtp_hostname' => $this->config->get('config_mail_smtp_hostname'),
627: 'smtp_username' => $this->config->get('config_mail_smtp_username'),
628: 'smtp_password' => html_entity_decode($this->config->get('config_mail_smtp_password'), ENT_QUOTES, 'UTF-8'),
629: 'smtp_port' => $this->config->get('config_mail_smtp_port'),
630: 'smtp_timeout' => $this->config->get('config_mail_smtp_timeout')
631: ];
632:
633: $mail = new \Opencart\System\Library\Mail($this->config->get('config_mail_engine'), $mail_option);
634: $mail->setTo($this->config->get('config_email'));
635: $mail->setFrom($this->config->get('config_email'));
636: $mail->setSender(html_entity_decode($order_info['store_name'], ENT_QUOTES, 'UTF-8'));
637: $mail->setSubject($subject);
638: $mail->setHtml($this->load->view('mail/order_alert', $data));
639: $mail->send();
640:
641: // Send to additional alert emails
642: $emails = explode(',', $this->config->get('config_mail_alert_email'));
643:
644: foreach ($emails as $email) {
645: if ($email && filter_var($email, FILTER_VALIDATE_EMAIL)) {
646: $mail->setTo(trim($email));
647: $mail->send();
648: }
649: }
650: }
651: }
652: }
653: }
654: