1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace App; |
4
|
|
|
|
5
|
|
|
/** |
6
|
|
|
* Mailer basic class. |
7
|
|
|
* |
8
|
|
|
* @package App |
9
|
|
|
* |
10
|
|
|
* @copyright YetiForce S.A. |
11
|
|
|
* @license YetiForce Public License 6.5 (licenses/LicenseEN.txt or yetiforce.com) |
12
|
|
|
* @author Mariusz Krzaczkowski <[email protected]> |
13
|
|
|
* @author Radosław Skrzypczak <[email protected]> |
14
|
|
|
*/ |
15
|
|
|
class Mailer |
16
|
|
|
{ |
17
|
|
|
/** @var string[] Queue status */ |
18
|
|
|
public static $statuses = [ |
19
|
|
|
0 => 'LBL_PENDING_ACCEPTANCE', |
20
|
|
|
1 => 'LBL_WAITING_TO_BE_SENT', |
21
|
|
|
2 => 'LBL_ERROR_DURING_SENDING', |
22
|
|
|
]; |
23
|
|
|
|
24
|
|
|
/** @var string[] Columns list that require JSON formatting */ |
25
|
|
|
public static $quoteJsonColumn = ['from', 'to', 'cc', 'bcc', 'attachments', 'params']; |
26
|
|
|
|
27
|
|
|
/** @var string[] Columns list available in the database */ |
28
|
|
|
public static $quoteColumn = ['smtp_id', 'date', 'owner', 'status', 'from', 'subject', 'content', 'to', 'cc', 'bcc', 'attachments', 'priority']; |
29
|
|
|
|
30
|
|
|
/** @var \PHPMailer\PHPMailer\PHPMailer PHPMailer instance */ |
31
|
|
|
protected $mailer; |
32
|
|
|
|
33
|
|
|
/** @var array SMTP configuration */ |
34
|
|
|
protected $smtp; |
35
|
|
|
|
36
|
|
|
/** @var array Parameters for sending messages */ |
37
|
|
|
protected $params = []; |
38
|
|
|
|
39
|
|
|
/** @var array Error logs */ |
40
|
|
|
public static $error; |
41
|
|
|
|
42
|
|
|
/** |
43
|
|
|
* Construct. |
44
|
|
|
*/ |
45
|
|
|
public function __construct() |
46
|
|
|
{ |
47
|
|
|
static::$error = []; |
48
|
|
|
$this->mailer = new \PHPMailer\PHPMailer\PHPMailer(false); |
49
|
|
|
if (\App\Config::debug('MAILER_DEBUG')) { |
50
|
|
|
$this->mailer->SMTPDebug = 2; |
51
|
|
|
$this->mailer->Debugoutput = function ($str, $level) { |
52
|
|
|
if (false !== stripos($str, 'error') || false !== stripos($str, 'failed')) { |
53
|
|
|
static::$error[] = $str; |
54
|
|
|
Log::error(trim($str), 'Mailer'); |
55
|
|
|
} else { |
56
|
|
|
Log::trace(trim($str), 'Mailer'); |
57
|
|
|
} |
58
|
|
|
}; |
59
|
|
|
} |
60
|
|
|
$this->mailer->XMailer = 'YetiForceCRM Mailer'; |
61
|
|
|
$this->mailer->Hostname = 'YetiForceCRM'; |
62
|
|
|
$this->mailer->FromName = 'YetiForce Mailer'; |
63
|
|
|
$this->mailer->CharSet = \App\Config::main('default_charset'); |
64
|
|
|
} |
65
|
|
|
|
66
|
|
|
/** |
67
|
|
|
* Load configuration smtp by id. |
68
|
|
|
* |
69
|
|
|
* @param int $smtpId Smtp ID |
70
|
|
|
* |
71
|
|
|
* @return $this mailer object itself |
72
|
|
|
*/ |
73
|
|
|
public function loadSmtpByID($smtpId) |
74
|
|
|
{ |
75
|
|
|
$this->smtp = Mail::getSmtpById($smtpId); |
76
|
|
|
$this->setSmtp(); |
77
|
|
|
return $this; |
78
|
|
|
} |
79
|
|
|
|
80
|
|
|
/** |
81
|
|
|
* Load configuration smtp. |
82
|
|
|
* |
83
|
|
|
* @param array $smtpInfo |
84
|
|
|
* |
85
|
|
|
* @return $this mailer object itself |
86
|
|
|
*/ |
87
|
|
|
public function loadSmtp($smtpInfo) |
88
|
1 |
|
{ |
89
|
|
|
$this->smtp = $smtpInfo; |
90
|
1 |
|
$this->setSmtp(); |
91
|
1 |
|
return $this; |
92
|
|
|
} |
93
|
|
|
|
94
|
|
|
/** |
95
|
1 |
|
* @param array $params |
96
|
1 |
|
* |
97
|
1 |
|
* @return bool |
98
|
1 |
|
*/ |
99
|
|
|
public static function sendFromTemplate(array $params): bool |
100
|
|
|
{ |
101
|
|
|
Log::trace('Send mail from template', 'Mailer'); |
102
|
|
|
if (empty($params['template'])) { |
103
|
|
|
Log::warning('No template', 'Mailer'); |
104
|
1 |
|
return false; |
105
|
1 |
|
} |
106
|
|
|
$recordModel = false; |
107
|
|
|
if (empty($params['recordModel'])) { |
108
|
|
|
$moduleName = $params['moduleName'] ?? null; |
109
|
1 |
|
if (isset($params['recordId'])) { |
110
|
1 |
|
$recordModel = \Vtiger_Record_Model::getInstanceById($params['recordId'], $moduleName); |
111
|
|
|
} |
112
|
|
|
} else { |
113
|
1 |
|
$recordModel = $params['recordModel']; |
114
|
|
|
unset($params['recordModel']); |
115
|
|
|
} |
116
|
1 |
|
$template = Mail::getTemplate($params['template']); |
117
|
1 |
|
if (!$template) { |
118
|
1 |
|
Log::warning('No mail template', 'Mailer'); |
119
|
1 |
|
return false; |
120
|
1 |
|
} |
121
|
|
|
$textParser = $recordModel ? TextParser::getInstanceByModel($recordModel) : TextParser::getInstance($params['moduleName'] ?? ''); |
122
|
|
|
if (!empty($params['language'])) { |
123
|
1 |
|
$textParser->setLanguage($params['language']); |
124
|
|
|
} |
125
|
|
|
if (!empty($params['sourceRecord'])) { |
126
|
1 |
|
$textParser->setSourceRecord($params['sourceRecord'], $params['sourceModule']); |
127
|
1 |
|
} |
128
|
|
|
$textParser->setParams(array_diff_key($params, array_flip(['subject', 'content', 'attachments', 'recordModel']))); |
129
|
1 |
|
$params['subject'] = $textParser->setContent($template['subject'])->parse()->getContent(); |
130
|
|
|
$params['content'] = $textParser->setContent(\App\Utils\Completions::decode(\App\Purifier::purifyHtml($template['content'])))->parse()->getContent(); |
131
|
|
|
unset($textParser); |
132
|
|
|
if (empty($params['smtp_id']) && !empty($template['smtp_id'])) { |
133
|
|
|
$params['smtp_id'] = $template['smtp_id']; |
134
|
|
|
} |
135
|
|
|
if (isset($template['attachments'])) { |
136
|
|
|
$params['attachments'] = array_merge(empty($params['attachments']) ? [] : $params['attachments'], $template['attachments']); |
137
|
1 |
|
} |
138
|
|
|
if (!empty($template['email_template_priority'])) { |
139
|
1 |
|
$params['priority'] = $template['email_template_priority']; |
140
|
1 |
|
} |
141
|
1 |
|
$row = array_intersect_key($params, array_flip(self::$quoteColumn)); |
142
|
1 |
|
$row['params'] = array_diff_key($params, $row); |
143
|
1 |
|
return static::addMail($row); |
144
|
|
|
} |
145
|
1 |
|
|
146
|
1 |
|
/** |
147
|
|
|
* Add mail to quote for send. |
148
|
1 |
|
* |
149
|
1 |
|
* @param array $params |
150
|
1 |
|
* |
151
|
1 |
|
* @return bool |
152
|
1 |
|
*/ |
153
|
1 |
|
public static function addMail(array $params): bool |
154
|
|
|
{ |
155
|
|
|
$params['status'] = Config::component('Mail', 'MAILER_REQUIRED_ACCEPTATION_BEFORE_SENDING') ? 0 : 1; |
156
|
|
|
$params['date'] = date('Y-m-d H:i:s'); |
157
|
|
|
if (empty($params['owner'])) { |
158
|
|
|
$owner = User::getCurrentUserRealId(); |
159
|
|
|
$params['owner'] = $owner ?: 0; |
160
|
|
|
} |
161
|
|
|
if (empty($params['smtp_id'])) { |
162
|
|
|
$params['smtp_id'] = Mail::getDefaultSmtp(); |
163
|
|
|
} |
164
|
|
|
if (empty($params['smtp_id'])) { |
165
|
|
|
unset($params['priority'], $params['status']); |
166
|
|
|
$params['error_code'] = 1; |
167
|
|
|
static::insertMail($params, 'log'); |
168
|
|
|
Log::warning('No SMTP configuration', 'Mailer'); |
169
|
|
|
return false; |
170
|
|
|
} |
171
|
|
|
if (!\App\Mail::getSmtpById($params['smtp_id'])) { |
172
|
|
|
unset($params['priority'], $params['status']); |
173
|
|
|
$params['error_code'] = 2; |
174
|
|
|
static::insertMail($params, 'log'); |
175
|
|
|
Log::warning('SMTP configuration with provided id not exists', 'Mailer'); |
176
|
|
|
return false; |
177
|
|
|
} |
178
|
|
|
if (empty($params['to'])) { |
179
|
|
|
unset($params['priority'], $params['status']); |
180
|
|
|
$params['error_code'] = 3; |
181
|
1 |
|
static::insertMail($params, 'log'); |
182
|
|
|
Log::warning('No target email address provided', 'Mailer'); |
183
|
1 |
|
return false; |
184
|
1 |
|
} |
185
|
1 |
|
static::insertMail($params, 'admin'); |
186
|
|
|
return true; |
187
|
|
|
} |
188
|
1 |
|
|
189
|
|
|
/** |
190
|
|
|
* Save mail data in provided table. |
191
|
1 |
|
* |
192
|
1 |
|
* @param array $params |
193
|
|
|
* @param string $type 'admin' | 'log' |
194
|
|
|
* |
195
|
|
|
* @return void |
196
|
|
|
*/ |
197
|
|
|
public static function insertMail(array $params, string $type): void |
198
|
|
|
{ |
199
|
|
|
$eventHandler = new EventHandler(); |
200
|
|
|
$eventHandler->setParams($params); |
201
|
|
|
$eventHandler->trigger('admin' === $type ? 'MailerAddToQueue' : 'MailerAddToLogs'); |
202
|
|
|
$params = $eventHandler->getParams(); |
203
|
|
|
|
204
|
|
|
foreach (static::$quoteJsonColumn as $key) { |
205
|
|
|
if (isset($params[$key])) { |
206
|
|
|
if (!\is_array($params[$key])) { |
207
|
|
|
$params[$key] = [$params[$key]]; |
208
|
|
|
} |
209
|
|
|
$params[$key] = Json::encode($params[$key]); |
210
|
|
|
} |
211
|
|
|
} |
212
|
|
|
\App\Db::getInstance($type)->createCommand()->insert('admin' === $type ? 's_#__mail_queue' : 'l_#__mail', $params)->execute(); |
213
|
|
|
} |
214
|
|
|
|
215
|
|
|
/** |
216
|
|
|
* Get configuration smtp. |
217
|
|
|
* |
218
|
|
|
* @param string|null $key |
219
|
|
|
* |
220
|
|
|
* @return mixed |
221
|
|
|
*/ |
222
|
|
|
public function getSmtp(?string $key = null) |
223
|
|
|
{ |
224
|
|
|
if ($key && isset($this->smtp[$key])) { |
225
|
|
|
return $this->smtp[$key]; |
226
|
|
|
} |
227
|
|
|
return $this->smtp; |
228
|
|
|
} |
229
|
|
|
|
230
|
|
|
/** |
231
|
|
|
* Set configuration smtp in mailer. |
232
|
|
|
*/ |
233
|
|
|
public function setSmtp(): void |
234
|
|
|
{ |
235
|
|
|
if (!$this->smtp) { |
|
|
|
|
236
|
|
|
throw new \App\Exceptions\AppException('ERR_NO_SMTP_CONFIGURATION'); |
237
|
|
|
} |
238
|
|
|
switch ($this->smtp['mailer_type']) { |
239
|
|
|
case 'smtp': |
240
|
|
|
$this->mailer->isSMTP(); |
241
|
|
|
break; |
242
|
|
|
case 'sendmail': |
243
|
|
|
$this->mailer->isSendmail(); |
244
|
|
|
break; |
245
|
|
|
case 'mail': |
246
|
|
|
$this->mailer->isMail(); |
247
|
|
|
break; |
248
|
|
|
case 'qmail': |
249
|
|
|
$this->mailer->isQmail(); |
250
|
|
|
break; |
251
|
|
|
default: |
252
|
|
|
break; |
253
|
|
|
} |
254
|
|
|
$this->mailer->Host = $this->smtp['host']; |
255
|
|
|
if (!empty($this->smtp['port'])) { |
256
|
|
|
$this->mailer->Port = $this->smtp['port']; |
257
|
|
|
} |
258
|
|
|
$this->mailer->SMTPSecure = $this->smtp['secure']; |
259
|
|
|
$this->mailer->SMTPAuth = isset($this->smtp['authentication']) && (bool) $this->smtp['authentication']; |
260
|
|
|
$this->mailer->Username = trim($this->smtp['username']); |
261
|
|
|
$this->mailer->Password = trim(Encryption::getInstance()->decrypt($this->smtp['password'])); |
262
|
|
|
if ($this->smtp['options']) { |
263
|
|
|
$this->mailer->SMTPOptions = Json::decode($this->smtp['options'], true); |
|
|
|
|
264
|
|
|
} |
265
|
|
|
$this->mailer->From = $this->smtp['from_email'] ?: $this->smtp['username']; |
266
|
|
|
if ($this->smtp['from_name']) { |
267
|
|
|
$this->mailer->FromName = $this->smtp['from_name']; |
268
|
|
|
} |
269
|
|
|
if ($this->smtp['reply_to']) { |
270
|
|
|
$this->mailer->addReplyTo($this->smtp['reply_to']); |
271
|
|
|
} |
272
|
|
|
if ($this->smtp['unsubscribe']) { |
273
|
|
|
$unsubscribe = ''; |
274
|
|
|
foreach (\App\Json::decode($this->smtp['unsubscribe']) as $row) { |
275
|
|
|
$unsubscribe .= "<$row>,"; |
276
|
|
|
} |
277
|
|
|
$unsubscribe = rtrim($unsubscribe, ','); |
278
|
|
|
$this->mailer->AddCustomHeader('List-Unsubscribe', $unsubscribe); |
279
|
|
|
} |
280
|
|
|
if ($this->smtp['priority']) { |
281
|
|
|
$priorityName = $priority = $priorityX = null; |
282
|
|
|
switch ($this->smtp['priority']) { |
283
|
|
|
case 'normal': |
284
|
|
|
case 'Normal': |
285
|
|
|
$priorityX = 3; |
286
|
|
|
$priority = $priorityName = 'Normal'; |
287
|
|
|
break; |
288
|
|
|
case 'non-urgent': |
289
|
|
|
case 'Low': |
290
|
|
|
$priorityX = 5; |
291
|
|
|
$priority = 'Non-Urgent'; |
292
|
|
|
$priorityName = 'Low'; |
293
|
|
|
break; |
294
|
|
|
case 'urgent': |
295
|
|
|
case 'High': |
296
|
|
|
$priorityX = 1; |
297
|
|
|
$priority = 'Urgent'; |
298
|
|
|
$priorityName = 'High'; |
299
|
|
|
break; |
300
|
|
|
} |
301
|
|
|
if ($priority) { |
302
|
|
|
$this->mailer->Priority = $priorityX; |
303
|
|
|
$this->mailer->AddCustomHeader('Priority', $priority); |
304
|
|
|
$this->mailer->AddCustomHeader('X-MSMail-Priority', $priorityName); |
305
|
|
|
$this->mailer->AddCustomHeader('Importance', $priorityName); |
306
|
|
|
} |
307
|
|
|
} |
308
|
|
|
if ($this->smtp['confirm_reading_to']) { |
309
|
|
|
$this->mailer->ConfirmReadingTo = $this->smtp['confirm_reading_to']; |
310
|
|
|
} |
311
|
|
|
if ($this->smtp['organization']) { |
312
|
|
|
$this->mailer->AddCustomHeader('Organization', $this->smtp['organization']); |
313
|
|
|
} |
314
|
|
|
} |
315
|
|
|
|
316
|
|
|
/** |
317
|
|
|
* Set subject. |
318
|
|
|
* |
319
|
|
|
* @param string $subject |
320
|
|
|
* |
321
|
|
|
* @return $this mailer object itself |
322
|
|
|
*/ |
323
|
|
|
public function subject($subject) |
324
|
|
|
{ |
325
|
|
|
$this->params['subject'] = $this->mailer->Subject = $subject; |
326
|
|
|
return $this; |
327
|
|
|
} |
328
|
|
|
|
329
|
|
|
/** |
330
|
|
|
* Creates a message from an HTML string, making modifications for inline images and backgrounds and creates a plain-text version by converting the HTML. |
331
|
|
|
* |
332
|
|
|
* @param text $message |
333
|
|
|
* |
334
|
|
|
* @see \PHPMailer::MsgHTML() |
335
|
|
|
* |
336
|
|
|
* @return $this mailer object itself |
337
|
|
|
*/ |
338
|
|
|
public function content($message) |
339
|
|
|
{ |
340
|
|
|
$this->params['body'] = $message; |
341
|
|
|
// Modification of the following condition will violate the license! |
342
|
|
|
if (!\App\YetiForce\Shop::check('YetiForceDisableBranding')) { |
343
|
|
|
$message .= '<table style="font-size:9px;width:100%; margin: 0;"><tbody><tr><td style="width:50%;text-align: center;">Powered by YetiForce</td></tr></tbody></table>'; |
344
|
|
|
} |
345
|
|
|
$this->mailer->isHTML(true); |
346
|
|
|
$this->mailer->msgHTML($message); |
347
|
|
|
return $this; |
348
|
|
|
} |
349
|
|
|
|
350
|
|
|
/** |
351
|
|
|
* Set the From and FromName properties. |
352
|
|
|
* |
353
|
|
|
* @param string $address |
354
|
|
|
* @param string $name |
355
|
|
|
* |
356
|
|
|
* @return $this mailer object itself |
357
|
|
|
*/ |
358
|
|
|
public function from($address, $name = '') |
359
|
|
|
{ |
360
|
|
|
$this->params['from'][$address] = $name; |
361
|
|
|
$this->mailer->From = $address; |
362
|
|
|
$this->mailer->FromName = $name; |
363
|
|
|
return $this; |
364
|
|
|
} |
365
|
|
|
|
366
|
|
|
/** |
367
|
|
|
* Add a "To" address. |
368
|
|
|
* |
369
|
|
|
* @param string $address The email address to send to |
370
|
|
|
* @param string $name |
371
|
|
|
* |
372
|
|
|
* @return $this mailer object itself |
373
|
|
|
*/ |
374
|
|
|
public function to($address, $name = '') |
375
|
|
|
{ |
376
|
|
|
$this->params['to'][$address] = $name; |
377
|
|
|
$this->mailer->addAddress($address, $name); |
378
|
|
|
return $this; |
379
|
|
|
} |
380
|
|
|
|
381
|
|
|
/** |
382
|
|
|
* Add a "CC" address. |
383
|
|
|
* |
384
|
|
|
* @note: This function works with the SMTP mailer on win32, not with the "mail" mailer. |
385
|
|
|
* |
386
|
|
|
* @param string $address The email address to send to |
387
|
|
|
* @param string $name |
388
|
|
|
* |
389
|
|
|
* @return $this mailer object itself |
390
|
|
|
*/ |
391
|
|
|
public function cc($address, $name = '') |
392
|
|
|
{ |
393
|
|
|
$this->params['cc'][$address] = $name; |
394
|
|
|
$this->mailer->addCC($address, $name); |
395
|
|
|
return $this; |
396
|
|
|
} |
397
|
|
|
|
398
|
|
|
/** |
399
|
|
|
* Add a "BCC" address. |
400
|
|
|
* |
401
|
|
|
* @note: This function works with the SMTP mailer on win32, not with the "mail" mailer. |
402
|
|
|
* |
403
|
|
|
* @param string $address The email address to send to |
404
|
|
|
* @param string $name |
405
|
|
|
* |
406
|
|
|
* @return $this mailer object itself |
407
|
|
|
*/ |
408
|
|
|
public function bcc($address, $name = '') |
409
|
|
|
{ |
410
|
|
|
$this->params['bcc'][$address] = $name; |
411
|
|
|
$this->mailer->addBCC($address, $name); |
412
|
|
|
return $this; |
413
|
|
|
} |
414
|
|
|
|
415
|
|
|
/** |
416
|
|
|
* Add a "Reply-To" address. |
417
|
|
|
* |
418
|
|
|
* @param string $address The email address to reply to |
419
|
|
|
* @param string $name |
420
|
|
|
* |
421
|
|
|
* @return $this mailer object itself |
422
|
|
|
*/ |
423
|
|
|
public function replyTo($address, $name = '') |
424
|
|
|
{ |
425
|
|
|
$this->params['replyTo'][$address] = $name; |
426
|
|
|
$this->mailer->addReplyTo($address, $name); |
427
|
|
|
return $this; |
428
|
|
|
} |
429
|
|
|
|
430
|
|
|
/** |
431
|
|
|
* Add an attachment from a path on the filesystem. |
432
|
|
|
* |
433
|
|
|
* @param string $path Path to the attachment |
434
|
|
|
* @param string $name Overrides the attachment name |
435
|
|
|
* |
436
|
|
|
* @return $this mailer object itself |
437
|
|
|
*/ |
438
|
|
|
public function attachment($path, $name = '') |
439
|
|
|
{ |
440
|
|
|
$this->params['attachment'][$path] = $name; |
441
|
|
|
$this->mailer->addAttachment($path, $name); |
442
|
|
|
return $this; |
443
|
|
|
} |
444
|
|
|
|
445
|
|
|
/** |
446
|
|
|
* Create a message and send it. |
447
|
|
|
* |
448
|
|
|
* @return bool |
449
|
|
|
*/ |
450
|
|
|
public function send(): bool |
451
|
|
|
{ |
452
|
|
|
$eventHandler = new EventHandler(); |
453
|
|
|
$eventHandler->setParams(['mailer' => $this]); |
454
|
|
|
$eventHandler->trigger('MailerBeforeSend'); |
455
|
|
|
$toAddresses = $this->mailer->From . ' >> ' . \print_r($this->mailer->getToAddresses(), true); |
|
|
|
|
456
|
|
|
\App\Log::beginProfile("Mailer::send|{$toAddresses}", 'Mail|SMTP'); |
457
|
|
|
if ($this->mailer->send()) { |
458
|
|
|
\App\Log::endProfile("Mailer::send|{$toAddresses}", 'Mail|SMTP'); |
459
|
|
|
if (!empty($this->smtp['save_send_mail'])) { |
460
|
|
|
$this->saveMail(); |
461
|
|
|
} |
462
|
|
|
Log::trace('Mailer sent mail', 'Mailer'); |
463
|
|
|
$eventHandler->trigger('MailerAfterSend'); |
464
|
|
|
return true; |
465
|
|
|
} |
466
|
|
|
\App\Log::endProfile("Mailer::send|{$toAddresses}", 'Mail|SMTP'); |
467
|
|
|
Log::error('Mailer Error: ' . \print_r($this->mailer->ErrorInfo, true), 'Mailer'); |
|
|
|
|
468
|
|
|
if (!empty(static::$error)) { |
469
|
|
|
static::$error[] = '########################################'; |
470
|
|
|
} |
471
|
|
|
if (\is_array($this->mailer->ErrorInfo)) { |
|
|
|
|
472
|
|
|
foreach ($this->mailer->ErrorInfo as $error) { |
473
|
|
|
static::$error[] = $error; |
474
|
|
|
} |
475
|
|
|
} else { |
476
|
|
|
static::$error[] = $this->mailer->ErrorInfo; |
477
|
|
|
} |
478
|
|
|
$eventHandler->trigger('MailerAfterSendError'); |
479
|
|
|
return false; |
480
|
|
|
} |
481
|
|
|
|
482
|
|
|
/** |
483
|
|
|
* Check connection. |
484
|
|
|
* |
485
|
|
|
* @return array |
486
|
|
|
*/ |
487
|
|
|
public function test() |
488
|
|
|
{ |
489
|
|
|
$this->mailer->SMTPDebug = 2; |
490
|
|
|
static::$error = []; |
491
|
|
|
$this->mailer->Debugoutput = function ($str, $level) { |
492
|
|
|
if (false !== strpos(strtolower($str), 'error') || false !== strpos(strtolower($str), 'failed')) { |
493
|
|
|
static::$error[] = trim($str); |
494
|
|
|
Log::error(trim($str), 'Mailer'); |
495
|
|
|
} else { |
496
|
|
|
Log::trace(trim($str), 'Mailer'); |
497
|
|
|
} |
498
|
|
|
}; |
499
|
|
|
$currentUser = \Users_Record_Model::getCurrentUserModel(); |
500
|
|
|
$this->to($currentUser->get('email1')); |
501
|
|
|
$templateId = Mail::getTemplateIdFromSysName('TestMailAboutTheMailServerConfiguration'); |
502
|
|
|
if (!$templateId) { |
|
|
|
|
503
|
|
|
return ['result' => false, 'error' => Language::translate('LBL_NO_EMAIL_TEMPLATE')]; |
504
|
|
|
} |
505
|
|
|
$template = Mail::getTemplate($templateId); |
506
|
|
|
$textParser = TextParser::getInstanceById($currentUser->getId(), 'Users'); |
507
|
|
|
$this->subject($textParser->setContent($template['subject'])->parse()->getContent()); |
508
|
|
|
$this->content($textParser->setContent($template['content'])->parse()->getContent()); |
|
|
|
|
509
|
|
|
return ['result' => $this->send(), 'error' => implode(PHP_EOL, static::$error)]; |
510
|
|
|
} |
511
|
|
|
|
512
|
|
|
/** |
513
|
|
|
* Send mail by row queue. |
514
|
|
|
* |
515
|
|
|
* @param array $rowQueue |
516
|
|
|
* |
517
|
|
|
* @return bool |
518
|
|
|
*/ |
519
|
|
|
public static function sendByRowQueue($rowQueue) |
520
|
|
|
{ |
521
|
|
|
if ('demo' === \App\Config::main('systemMode')) { |
522
|
|
|
return true; |
523
|
|
|
} |
524
|
|
|
$mailer = (new self())->loadSmtpByID($rowQueue['smtp_id'])->subject($rowQueue['subject'])->content($rowQueue['content']); |
525
|
|
|
if ($rowQueue['from']) { |
526
|
|
|
$from = Json::decode($rowQueue['from']); |
527
|
|
|
$mailer->from($from['email'], $from['name']); |
528
|
|
|
} |
529
|
|
|
foreach (['cc', 'bcc'] as $key) { |
530
|
|
|
if ($rowQueue[$key]) { |
531
|
|
|
foreach (Json::decode($rowQueue[$key]) as $email => $name) { |
532
|
|
|
if (is_numeric($email)) { |
533
|
|
|
$email = $name; |
534
|
|
|
$name = ''; |
535
|
|
|
} |
536
|
|
|
$mailer->{$key}($email, $name); |
537
|
|
|
} |
538
|
|
|
} |
539
|
|
|
} |
540
|
|
|
$status = false; |
541
|
|
|
$attachmentsToRemove = $update = []; |
542
|
|
|
if ($rowQueue['attachments']) { |
543
|
|
|
$attachments = Json::decode($rowQueue['attachments']); |
544
|
|
|
if (isset($attachments['ids'])) { |
545
|
|
|
$attachments = array_merge($attachments, Mail::getAttachmentsFromDocument($attachments['ids'])); |
546
|
|
|
unset($attachments['ids']); |
547
|
|
|
} |
548
|
|
|
foreach ($attachments as $path => $name) { |
549
|
|
|
if (is_numeric($path)) { |
550
|
|
|
$path = $name; |
551
|
|
|
$name = ''; |
552
|
|
|
} |
553
|
|
|
$mailer->attachment($path, $name); |
554
|
|
|
if (strpos(realpath($path), 'cache' . \DIRECTORY_SEPARATOR)) { |
555
|
|
|
$attachmentsToRemove[] = $path; |
556
|
|
|
} |
557
|
|
|
} |
558
|
|
|
} |
559
|
|
|
if (!empty($rowQueue['params'])) { |
560
|
|
|
$mailer->setCustomParams(Json::decode($rowQueue['params'])); |
561
|
|
|
} |
562
|
|
|
if ($mailer->getSmtp('individual_delivery')) { |
563
|
|
|
$emails = []; |
564
|
|
|
foreach (Json::decode($rowQueue['to']) as $email => $name) { |
565
|
|
|
if (is_numeric($email)) { |
566
|
|
|
$email = $name; |
567
|
|
|
$name = ''; |
568
|
|
|
} |
569
|
|
|
$emails[$email] = $name; |
570
|
|
|
} |
571
|
|
|
foreach ($emails as $email => $name) { |
572
|
|
|
$separateMailer = $mailer->cloneMailer(); |
573
|
|
|
$separateMailer->to($email, $name); |
574
|
|
|
$status = $separateMailer->send(); |
575
|
|
|
if (!$status) { |
576
|
|
|
$update['to'] = Json::encode($emails); |
577
|
|
|
break; |
578
|
|
|
} |
579
|
|
|
unset($separateMailer, $emails[$email]); |
580
|
|
|
} |
581
|
|
|
} else { |
582
|
|
|
foreach (Json::decode($rowQueue['to']) as $email => $name) { |
583
|
|
|
if (is_numeric($email)) { |
584
|
|
|
$email = $name; |
585
|
|
|
$name = ''; |
586
|
|
|
} |
587
|
|
|
$mailer->to($email, $name); |
588
|
|
|
} |
589
|
|
|
$status = $mailer->send(); |
590
|
|
|
unset($mailer); |
591
|
|
|
} |
592
|
|
|
$db = Db::getInstance('admin'); |
593
|
|
|
if ($status) { |
594
|
|
|
$db->createCommand()->delete('s_#__mail_queue', ['id' => $rowQueue['id']])->execute(); |
595
|
|
|
foreach ($attachmentsToRemove as $file) { |
596
|
|
|
unlink($file); |
597
|
|
|
} |
598
|
|
|
} else { |
599
|
|
|
$update['status'] = 2; |
600
|
|
|
$update['error'] = implode(PHP_EOL, static::$error); |
601
|
|
|
$db->createCommand()->update('s_#__mail_queue', $update, ['id' => $rowQueue['id']])->execute(); |
602
|
|
|
} |
603
|
|
|
return $status; |
604
|
|
|
} |
605
|
|
|
|
606
|
|
|
/** |
607
|
|
|
* Adding additional parameters. |
608
|
|
|
* |
609
|
|
|
* @param array $params |
610
|
|
|
* |
611
|
|
|
* @return void |
612
|
|
|
*/ |
613
|
|
|
public function setCustomParams(array $params): void |
614
|
|
|
{ |
615
|
|
|
$this->params['params'] = $params; |
616
|
|
|
if (isset($this->params['ics'])) { |
617
|
|
|
$this->mailer->Ical = $this->params['ics']; |
618
|
|
|
} |
619
|
|
|
} |
620
|
|
|
|
621
|
|
|
/** |
622
|
|
|
* Get additional parameters. |
623
|
|
|
* |
624
|
|
|
* @return array |
625
|
|
|
*/ |
626
|
|
|
public function getCustomParams(): array |
627
|
|
|
{ |
628
|
|
|
return $this->params; |
629
|
|
|
} |
630
|
|
|
|
631
|
|
|
/** |
632
|
|
|
* Save sent email. |
633
|
|
|
* |
634
|
|
|
* @throws \App\Exceptions\AppException |
635
|
|
|
* |
636
|
|
|
* @return bool |
637
|
|
|
*/ |
638
|
|
|
public function saveMail() |
639
|
|
|
{ |
640
|
|
|
if (empty($this->smtp['smtp_username']) && empty($this->smtp['smtp_password']) && empty($this->smtp['smtp_host'])) { |
641
|
|
|
Log::error('Mailer Error: No smtp data entered', 'Mailer'); |
642
|
|
|
return false; |
643
|
|
|
} |
644
|
|
|
$folder = Utils::convertCharacterEncoding($this->smtp['smtp_folder'], 'UTF-8', 'UTF7-IMAP'); |
645
|
|
|
$mbox = \OSSMail_Record_Model::imapConnect( |
646
|
|
|
$this->smtp['smtp_username'], |
647
|
|
|
Encryption::getInstance()->decrypt($this->smtp['smtp_password']), |
648
|
|
|
$this->smtp['smtp_host'] . ':' . $this->smtp['smtp_port'], $folder, false, |
649
|
|
|
[ |
650
|
|
|
'validate_cert' => !empty($this->smtp['smtp_validate_cert']), |
651
|
|
|
'imap_max_retries' => 0, |
652
|
|
|
'imap_params' => [], |
653
|
|
|
'imap_open_add_connection_type' => true, |
654
|
|
|
] |
655
|
|
|
); |
656
|
|
|
if (false === $mbox && !imap_last_error()) { |
657
|
|
|
static::$error[] = 'IMAP error - ' . imap_last_error(); |
658
|
|
|
Log::error('Mailer Error: IMAP error - ' . imap_last_error(), 'Mailer'); |
659
|
|
|
return false; |
660
|
|
|
} |
661
|
|
|
\App\Log::beginProfile(__METHOD__ . '|imap_append', 'Mail|IMAP'); |
662
|
|
|
imap_append($mbox, \OSSMail_Record_Model::$imapConnectMailbox, $this->mailer->getSentMIMEMessage(), '\\Seen'); |
|
|
|
|
663
|
|
|
\App\Log::endProfile(__METHOD__ . '|imap_append', 'Mail|IMAP'); |
664
|
|
|
|
665
|
|
|
return true; |
666
|
|
|
} |
667
|
|
|
|
668
|
|
|
/** |
669
|
|
|
* Clone the mailer object for individual shipment. |
670
|
|
|
* |
671
|
|
|
* @return \App\Mailer |
672
|
|
|
*/ |
673
|
|
|
public function cloneMailer() |
674
|
|
|
{ |
675
|
|
|
$clonedThis = clone $this; |
676
|
|
|
$clonedThis->mailer = clone $this->mailer; |
677
|
|
|
return $clonedThis; |
678
|
|
|
} |
679
|
|
|
} |
680
|
|
|
|
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.
Consider making the comparison explicit by using
empty(..)
or! empty(...)
instead.