These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | /** |
||
3 | * CakePHP(tm) : Rapid Development Framework (https://cakephp.org) |
||
4 | * Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org) |
||
5 | * |
||
6 | * Licensed under The MIT License |
||
7 | * For full copyright and license information, please see the LICENSE.txt |
||
8 | * Redistributions of files must retain the above copyright notice. |
||
9 | * |
||
10 | * @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org) |
||
11 | * @link https://cakephp.org CakePHP(tm) Project |
||
12 | * @since 2.0.0 |
||
13 | * @license https://opensource.org/licenses/mit-license.php MIT License |
||
14 | */ |
||
15 | namespace Cake\Mailer; |
||
16 | |||
17 | use BadMethodCallException; |
||
18 | use Cake\Core\Configure; |
||
19 | use Cake\Core\StaticConfigTrait; |
||
20 | use Cake\Filesystem\File; |
||
21 | use Cake\Http\Client\FormDataPart; |
||
22 | use Cake\Log\Log; |
||
23 | use Cake\Utility\Hash; |
||
24 | use Cake\Utility\Security; |
||
25 | use Cake\Utility\Text; |
||
26 | use Cake\View\ViewVarsTrait; |
||
27 | use Closure; |
||
28 | use Exception; |
||
29 | use InvalidArgumentException; |
||
30 | use JsonSerializable; |
||
31 | use LogicException; |
||
32 | use PDO; |
||
33 | use RuntimeException; |
||
34 | use Serializable; |
||
35 | use SimpleXMLElement; |
||
36 | |||
37 | /** |
||
38 | * CakePHP Email class. |
||
39 | * |
||
40 | * This class is used for sending Internet Message Format based |
||
41 | * on the standard outlined in https://www.rfc-editor.org/rfc/rfc2822.txt |
||
42 | * |
||
43 | * ### Configuration |
||
44 | * |
||
45 | * Configuration for Email is managed by Email::config() and Email::configTransport(). |
||
46 | * Email::config() can be used to add or read a configuration profile for Email instances. |
||
47 | * Once made configuration profiles can be used to re-use across various email messages your |
||
48 | * application sends. |
||
49 | */ |
||
50 | class Email implements JsonSerializable, Serializable |
||
51 | { |
||
52 | use StaticConfigTrait; |
||
53 | use ViewVarsTrait; |
||
54 | |||
55 | /** |
||
56 | * Line length - no should more - RFC 2822 - 2.1.1 |
||
57 | * |
||
58 | * @var int |
||
59 | */ |
||
60 | const LINE_LENGTH_SHOULD = 78; |
||
61 | |||
62 | /** |
||
63 | * Line length - no must more - RFC 2822 - 2.1.1 |
||
64 | * |
||
65 | * @var int |
||
66 | */ |
||
67 | const LINE_LENGTH_MUST = 998; |
||
68 | |||
69 | /** |
||
70 | * Type of message - HTML |
||
71 | * |
||
72 | * @var string |
||
73 | */ |
||
74 | const MESSAGE_HTML = 'html'; |
||
75 | |||
76 | /** |
||
77 | * Type of message - TEXT |
||
78 | * |
||
79 | * @var string |
||
80 | */ |
||
81 | const MESSAGE_TEXT = 'text'; |
||
82 | |||
83 | /** |
||
84 | * Holds the regex pattern for email validation |
||
85 | * |
||
86 | * @var string |
||
87 | */ |
||
88 | const EMAIL_PATTERN = '/^((?:[\p{L}0-9.!#$%&\'*+\/=?^_`{|}~-]+)*@[\p{L}0-9-._]+)$/ui'; |
||
89 | |||
90 | /** |
||
91 | * Recipient of the email |
||
92 | * |
||
93 | * @var array |
||
94 | */ |
||
95 | protected $_to = []; |
||
96 | |||
97 | /** |
||
98 | * The mail which the email is sent from |
||
99 | * |
||
100 | * @var array |
||
101 | */ |
||
102 | protected $_from = []; |
||
103 | |||
104 | /** |
||
105 | * The sender email |
||
106 | * |
||
107 | * @var array |
||
108 | */ |
||
109 | protected $_sender = []; |
||
110 | |||
111 | /** |
||
112 | * The email the recipient will reply to |
||
113 | * |
||
114 | * @var array |
||
115 | */ |
||
116 | protected $_replyTo = []; |
||
117 | |||
118 | /** |
||
119 | * The read receipt email |
||
120 | * |
||
121 | * @var array |
||
122 | */ |
||
123 | protected $_readReceipt = []; |
||
124 | |||
125 | /** |
||
126 | * The mail that will be used in case of any errors like |
||
127 | * - Remote mailserver down |
||
128 | * - Remote user has exceeded his quota |
||
129 | * - Unknown user |
||
130 | * |
||
131 | * @var array |
||
132 | */ |
||
133 | protected $_returnPath = []; |
||
134 | |||
135 | /** |
||
136 | * Carbon Copy |
||
137 | * |
||
138 | * List of email's that should receive a copy of the email. |
||
139 | * The Recipient WILL be able to see this list |
||
140 | * |
||
141 | * @var array |
||
142 | */ |
||
143 | protected $_cc = []; |
||
144 | |||
145 | /** |
||
146 | * Blind Carbon Copy |
||
147 | * |
||
148 | * List of email's that should receive a copy of the email. |
||
149 | * The Recipient WILL NOT be able to see this list |
||
150 | * |
||
151 | * @var array |
||
152 | */ |
||
153 | protected $_bcc = []; |
||
154 | |||
155 | /** |
||
156 | * Message ID |
||
157 | * |
||
158 | * @var bool|string |
||
159 | */ |
||
160 | protected $_messageId = true; |
||
161 | |||
162 | /** |
||
163 | * Domain for messageId generation. |
||
164 | * Needs to be manually set for CLI mailing as env('HTTP_HOST') is empty |
||
165 | * |
||
166 | * @var string |
||
167 | */ |
||
168 | protected $_domain; |
||
169 | |||
170 | /** |
||
171 | * The subject of the email |
||
172 | * |
||
173 | * @var string |
||
174 | */ |
||
175 | protected $_subject = ''; |
||
176 | |||
177 | /** |
||
178 | * Associative array of a user defined headers |
||
179 | * Keys will be prefixed 'X-' as per RFC2822 Section 4.7.5 |
||
180 | * |
||
181 | * @var array |
||
182 | */ |
||
183 | protected $_headers = []; |
||
184 | |||
185 | /** |
||
186 | * Text message |
||
187 | * |
||
188 | * @var string |
||
189 | */ |
||
190 | protected $_textMessage = ''; |
||
191 | |||
192 | /** |
||
193 | * Html message |
||
194 | * |
||
195 | * @var string |
||
196 | */ |
||
197 | protected $_htmlMessage = ''; |
||
198 | |||
199 | /** |
||
200 | * Final message to send |
||
201 | * |
||
202 | * @var array |
||
203 | */ |
||
204 | protected $_message = []; |
||
205 | |||
206 | /** |
||
207 | * Available formats to be sent. |
||
208 | * |
||
209 | * @var array |
||
210 | */ |
||
211 | protected $_emailFormatAvailable = ['text', 'html', 'both']; |
||
212 | |||
213 | /** |
||
214 | * What format should the email be sent in |
||
215 | * |
||
216 | * @var string |
||
217 | */ |
||
218 | protected $_emailFormat = 'text'; |
||
219 | |||
220 | /** |
||
221 | * The transport instance to use for sending mail. |
||
222 | * |
||
223 | * @var \Cake\Mailer\AbstractTransport|null |
||
224 | */ |
||
225 | protected $_transport; |
||
226 | |||
227 | /** |
||
228 | * Charset the email body is sent in |
||
229 | * |
||
230 | * @var string |
||
231 | */ |
||
232 | public $charset = 'utf-8'; |
||
233 | |||
234 | /** |
||
235 | * Charset the email header is sent in |
||
236 | * If null, the $charset property will be used as default |
||
237 | * |
||
238 | * @var string|null |
||
239 | */ |
||
240 | public $headerCharset; |
||
241 | |||
242 | /** |
||
243 | * The email transfer encoding used. |
||
244 | * If null, the $charset property is used for determined the transfer encoding. |
||
245 | * |
||
246 | * @var string|null |
||
247 | */ |
||
248 | protected $transferEncoding; |
||
249 | |||
250 | /** |
||
251 | * Available encoding to be set for transfer. |
||
252 | * |
||
253 | * @var array |
||
254 | */ |
||
255 | protected $_transferEncodingAvailable = [ |
||
256 | '7bit', |
||
257 | '8bit', |
||
258 | 'base64', |
||
259 | 'binary', |
||
260 | 'quoted-printable' |
||
261 | ]; |
||
262 | |||
263 | /** |
||
264 | * The application wide charset, used to encode headers and body |
||
265 | * |
||
266 | * @var string|null |
||
267 | */ |
||
268 | protected $_appCharset; |
||
269 | |||
270 | /** |
||
271 | * List of files that should be attached to the email. |
||
272 | * |
||
273 | * Only absolute paths |
||
274 | * |
||
275 | * @var array |
||
276 | */ |
||
277 | protected $_attachments = []; |
||
278 | |||
279 | /** |
||
280 | * If set, boundary to use for multipart mime messages |
||
281 | * |
||
282 | * @var string|null |
||
283 | */ |
||
284 | protected $_boundary; |
||
285 | |||
286 | /** |
||
287 | * Contains the optional priority of the email. |
||
288 | * |
||
289 | * @var int|null |
||
290 | */ |
||
291 | protected $_priority; |
||
292 | |||
293 | /** |
||
294 | * An array mapping url schemes to fully qualified Transport class names. |
||
295 | * Unused. |
||
296 | * |
||
297 | * @var array |
||
298 | * @deprecated 3.7.0 This property is unused and will be removed in 4.0.0. |
||
299 | */ |
||
300 | protected static $_dsnClassMap = []; |
||
301 | |||
302 | /** |
||
303 | * A copy of the configuration profile for this |
||
304 | * instance. This copy can be modified with Email::profile(). |
||
305 | * |
||
306 | * @var array |
||
307 | */ |
||
308 | protected $_profile = []; |
||
309 | |||
310 | /** |
||
311 | * 8Bit character sets |
||
312 | * |
||
313 | * @var array |
||
314 | */ |
||
315 | protected $_charset8bit = ['UTF-8', 'SHIFT_JIS']; |
||
316 | |||
317 | /** |
||
318 | * Define Content-Type charset name |
||
319 | * |
||
320 | * @var array |
||
321 | */ |
||
322 | protected $_contentTypeCharset = [ |
||
323 | 'ISO-2022-JP-MS' => 'ISO-2022-JP' |
||
324 | ]; |
||
325 | |||
326 | /** |
||
327 | * Regex for email validation |
||
328 | * |
||
329 | * If null, filter_var() will be used. Use the emailPattern() method |
||
330 | * to set a custom pattern.' |
||
331 | * |
||
332 | * @var string |
||
333 | */ |
||
334 | protected $_emailPattern = self::EMAIL_PATTERN; |
||
335 | |||
336 | /** |
||
337 | * Constructor |
||
338 | * |
||
339 | * @param array|string|null $config Array of configs, or string to load configs from app.php |
||
340 | */ |
||
341 | public function __construct($config = null) |
||
342 | { |
||
343 | $this->_appCharset = Configure::read('App.encoding'); |
||
344 | if ($this->_appCharset !== null) { |
||
345 | $this->charset = $this->_appCharset; |
||
346 | } |
||
347 | $this->_domain = preg_replace('/\:\d+$/', '', env('HTTP_HOST')); |
||
348 | if (empty($this->_domain)) { |
||
349 | $this->_domain = php_uname('n'); |
||
350 | } |
||
351 | |||
352 | $this->viewBuilder() |
||
353 | ->setClassName('Cake\View\View') |
||
354 | ->setTemplate('') |
||
355 | ->setLayout('default') |
||
356 | ->setHelpers(['Html']); |
||
357 | |||
358 | if ($config === null) { |
||
359 | $config = static::getConfig('default'); |
||
360 | } |
||
361 | if ($config) { |
||
362 | $this->setProfile($config); |
||
363 | } |
||
364 | if (empty($this->headerCharset)) { |
||
365 | $this->headerCharset = $this->charset; |
||
366 | } |
||
367 | } |
||
368 | |||
369 | /** |
||
370 | * Clone ViewBuilder instance when email object is cloned. |
||
371 | * |
||
372 | * @return void |
||
373 | */ |
||
374 | public function __clone() |
||
375 | { |
||
376 | $this->_viewBuilder = clone $this->viewBuilder(); |
||
377 | } |
||
378 | |||
379 | /** |
||
380 | * Sets "from" address. |
||
381 | * |
||
382 | * @param string|array $email Null to get, String with email, |
||
383 | * Array with email as key, name as value or email as value (without name) |
||
384 | * @param string|null $name Name |
||
385 | * @return $this |
||
386 | * @throws \InvalidArgumentException |
||
387 | */ |
||
388 | public function setFrom($email, $name = null) |
||
389 | { |
||
390 | return $this->_setEmailSingle('_from', $email, $name, 'From requires only 1 email address.'); |
||
391 | } |
||
392 | |||
393 | /** |
||
394 | * Gets "from" address. |
||
395 | * |
||
396 | * @return array |
||
397 | */ |
||
398 | public function getFrom() |
||
399 | { |
||
400 | return $this->_from; |
||
401 | } |
||
402 | |||
403 | /** |
||
404 | * From |
||
405 | * |
||
406 | * @deprecated 3.4.0 Use setFrom()/getFrom() instead. |
||
407 | * @param string|array|null $email Null to get, String with email, |
||
408 | * Array with email as key, name as value or email as value (without name) |
||
409 | * @param string|null $name Name |
||
410 | * @return array|$this |
||
411 | * @throws \InvalidArgumentException |
||
412 | */ |
||
413 | public function from($email = null, $name = null) |
||
414 | { |
||
415 | deprecationWarning('Email::from() is deprecated. Use Email::setFrom() or Email::getFrom() instead.'); |
||
416 | if ($email === null) { |
||
417 | return $this->getFrom(); |
||
418 | } |
||
419 | |||
420 | return $this->setFrom($email, $name); |
||
421 | } |
||
422 | |||
423 | /** |
||
424 | * Sets "sender" address. |
||
425 | * |
||
426 | * @param string|array $email String with email, |
||
427 | * Array with email as key, name as value or email as value (without name) |
||
428 | * @param string|null $name Name |
||
429 | * @return $this |
||
430 | * @throws \InvalidArgumentException |
||
431 | */ |
||
432 | public function setSender($email, $name = null) |
||
433 | { |
||
434 | return $this->_setEmailSingle('_sender', $email, $name, 'Sender requires only 1 email address.'); |
||
435 | } |
||
436 | |||
437 | /** |
||
438 | * Gets "sender" address. |
||
439 | * |
||
440 | * @return array |
||
441 | */ |
||
442 | public function getSender() |
||
443 | { |
||
444 | return $this->_sender; |
||
445 | } |
||
446 | |||
447 | /** |
||
448 | * Sender |
||
449 | * |
||
450 | * @deprecated 3.4.0 Use setSender()/getSender() instead. |
||
451 | * @param string|array|null $email Null to get, String with email, |
||
452 | * Array with email as key, name as value or email as value (without name) |
||
453 | * @param string|null $name Name |
||
454 | * @return array|$this |
||
455 | * @throws \InvalidArgumentException |
||
456 | */ |
||
457 | public function sender($email = null, $name = null) |
||
458 | { |
||
459 | deprecationWarning('Email::sender() is deprecated. Use Email::setSender() or Email::getSender() instead.'); |
||
460 | |||
461 | if ($email === null) { |
||
462 | return $this->getSender(); |
||
463 | } |
||
464 | |||
465 | return $this->setSender($email, $name); |
||
466 | } |
||
467 | |||
468 | /** |
||
469 | * Sets "Reply-To" address. |
||
470 | * |
||
471 | * @param string|array $email String with email, |
||
472 | * Array with email as key, name as value or email as value (without name) |
||
473 | * @param string|null $name Name |
||
474 | * @return $this |
||
475 | * @throws \InvalidArgumentException |
||
476 | */ |
||
477 | public function setReplyTo($email, $name = null) |
||
478 | { |
||
479 | return $this->_setEmailSingle('_replyTo', $email, $name, 'Reply-To requires only 1 email address.'); |
||
480 | } |
||
481 | |||
482 | /** |
||
483 | * Gets "Reply-To" address. |
||
484 | * |
||
485 | * @return array |
||
486 | */ |
||
487 | public function getReplyTo() |
||
488 | { |
||
489 | return $this->_replyTo; |
||
490 | } |
||
491 | |||
492 | /** |
||
493 | * Reply-To |
||
494 | * |
||
495 | * @deprecated 3.4.0 Use setReplyTo()/getReplyTo() instead. |
||
496 | * @param string|array|null $email Null to get, String with email, |
||
497 | * Array with email as key, name as value or email as value (without name) |
||
498 | * @param string|null $name Name |
||
499 | * @return array|$this |
||
500 | * @throws \InvalidArgumentException |
||
501 | */ |
||
502 | public function replyTo($email = null, $name = null) |
||
503 | { |
||
504 | deprecationWarning('Email::replyTo() is deprecated. Use Email::setReplyTo() or Email::getReplyTo() instead.'); |
||
505 | |||
506 | if ($email === null) { |
||
507 | return $this->getReplyTo(); |
||
508 | } |
||
509 | |||
510 | return $this->setReplyTo($email, $name); |
||
511 | } |
||
512 | |||
513 | /** |
||
514 | * Sets Read Receipt (Disposition-Notification-To header). |
||
515 | * |
||
516 | * @param string|array $email String with email, |
||
517 | * Array with email as key, name as value or email as value (without name) |
||
518 | * @param string|null $name Name |
||
519 | * @return $this |
||
520 | * @throws \InvalidArgumentException |
||
521 | */ |
||
522 | public function setReadReceipt($email, $name = null) |
||
523 | { |
||
524 | return $this->_setEmailSingle('_readReceipt', $email, $name, 'Disposition-Notification-To requires only 1 email address.'); |
||
525 | } |
||
526 | |||
527 | /** |
||
528 | * Gets Read Receipt (Disposition-Notification-To header). |
||
529 | * |
||
530 | * @return array |
||
531 | */ |
||
532 | public function getReadReceipt() |
||
533 | { |
||
534 | return $this->_readReceipt; |
||
535 | } |
||
536 | |||
537 | /** |
||
538 | * Read Receipt (Disposition-Notification-To header) |
||
539 | * |
||
540 | * @deprecated 3.4.0 Use setReadReceipt()/getReadReceipt() instead. |
||
541 | * @param string|array|null $email Null to get, String with email, |
||
542 | * Array with email as key, name as value or email as value (without name) |
||
543 | * @param string|null $name Name |
||
544 | * @return array|$this |
||
545 | * @throws \InvalidArgumentException |
||
546 | */ |
||
547 | public function readReceipt($email = null, $name = null) |
||
548 | { |
||
549 | deprecationWarning('Email::readReceipt() is deprecated. Use Email::setReadReceipt() or Email::getReadReceipt() instead.'); |
||
550 | |||
551 | if ($email === null) { |
||
552 | return $this->getReadReceipt(); |
||
553 | } |
||
554 | |||
555 | return $this->setReadReceipt($email, $name); |
||
556 | } |
||
557 | |||
558 | /** |
||
559 | * Return Path |
||
560 | * |
||
561 | * @param string|array $email String with email, |
||
562 | * Array with email as key, name as value or email as value (without name) |
||
563 | * @param string|null $name Name |
||
564 | * @return $this |
||
565 | * @throws \InvalidArgumentException |
||
566 | */ |
||
567 | public function setReturnPath($email, $name = null) |
||
568 | { |
||
569 | return $this->_setEmailSingle('_returnPath', $email, $name, 'Return-Path requires only 1 email address.'); |
||
570 | } |
||
571 | |||
572 | /** |
||
573 | * Gets return path. |
||
574 | * |
||
575 | * @return array |
||
576 | */ |
||
577 | public function getReturnPath() |
||
578 | { |
||
579 | return $this->_returnPath; |
||
580 | } |
||
581 | |||
582 | /** |
||
583 | * Return Path |
||
584 | * |
||
585 | * @deprecated 3.4.0 Use setReturnPath()/getReturnPath() instead. |
||
586 | * @param string|array|null $email Null to get, String with email, |
||
587 | * Array with email as key, name as value or email as value (without name) |
||
588 | * @param string|null $name Name |
||
589 | * @return array|$this |
||
590 | * @throws \InvalidArgumentException |
||
591 | */ |
||
592 | public function returnPath($email = null, $name = null) |
||
593 | { |
||
594 | deprecationWarning('Email::returnPath() is deprecated. Use Email::setReturnPath() or Email::getReturnPath() instead.'); |
||
595 | if ($email === null) { |
||
596 | return $this->getReturnPath(); |
||
597 | } |
||
598 | |||
599 | return $this->setReturnPath($email, $name); |
||
600 | } |
||
601 | |||
602 | /** |
||
603 | * Sets "to" address. |
||
604 | * |
||
605 | * @param string|array $email String with email, |
||
606 | * Array with email as key, name as value or email as value (without name) |
||
607 | * @param string|null $name Name |
||
608 | * @return $this |
||
609 | */ |
||
610 | public function setTo($email, $name = null) |
||
611 | { |
||
612 | return $this->_setEmail('_to', $email, $name); |
||
613 | } |
||
614 | |||
615 | /** |
||
616 | * Gets "to" address |
||
617 | * |
||
618 | * @return array |
||
619 | */ |
||
620 | public function getTo() |
||
621 | { |
||
622 | return $this->_to; |
||
623 | } |
||
624 | |||
625 | /** |
||
626 | * To |
||
627 | * |
||
628 | * @deprecated 3.4.0 Use setTo()/getTo() instead. |
||
629 | * @param string|array|null $email Null to get, String with email, |
||
630 | * Array with email as key, name as value or email as value (without name) |
||
631 | * @param string|null $name Name |
||
632 | * @return array|$this |
||
633 | */ |
||
634 | public function to($email = null, $name = null) |
||
635 | { |
||
636 | deprecationWarning('Email::to() is deprecated. Use Email::setTo() or Email::getTo() instead.'); |
||
637 | |||
638 | if ($email === null) { |
||
639 | return $this->getTo(); |
||
640 | } |
||
641 | |||
642 | return $this->setTo($email, $name); |
||
643 | } |
||
644 | |||
645 | /** |
||
646 | * Add To |
||
647 | * |
||
648 | * @param string|array $email Null to get, String with email, |
||
649 | * Array with email as key, name as value or email as value (without name) |
||
650 | * @param string|null $name Name |
||
651 | * @return $this |
||
652 | */ |
||
653 | public function addTo($email, $name = null) |
||
654 | { |
||
655 | return $this->_addEmail('_to', $email, $name); |
||
656 | } |
||
657 | |||
658 | /** |
||
659 | * Sets "cc" address. |
||
660 | * |
||
661 | * @param string|array $email String with email, |
||
662 | * Array with email as key, name as value or email as value (without name) |
||
663 | * @param string|null $name Name |
||
664 | * @return $this |
||
665 | */ |
||
666 | public function setCc($email, $name = null) |
||
667 | { |
||
668 | return $this->_setEmail('_cc', $email, $name); |
||
669 | } |
||
670 | |||
671 | /** |
||
672 | * Gets "cc" address. |
||
673 | * |
||
674 | * @return array |
||
675 | */ |
||
676 | public function getCc() |
||
677 | { |
||
678 | return $this->_cc; |
||
679 | } |
||
680 | |||
681 | /** |
||
682 | * Cc |
||
683 | * |
||
684 | * @deprecated 3.4.0 Use setCc()/getCc() instead. |
||
685 | * @param string|array|null $email Null to get, String with email, |
||
686 | * Array with email as key, name as value or email as value (without name) |
||
687 | * @param string|null $name Name |
||
688 | * @return array|$this |
||
689 | */ |
||
690 | public function cc($email = null, $name = null) |
||
691 | { |
||
692 | deprecationWarning('Email::cc() is deprecated. Use Email::setCc() or Email::getCc() instead.'); |
||
693 | |||
694 | if ($email === null) { |
||
695 | return $this->getCc(); |
||
696 | } |
||
697 | |||
698 | return $this->setCc($email, $name); |
||
699 | } |
||
700 | |||
701 | /** |
||
702 | * Add Cc |
||
703 | * |
||
704 | * @param string|array $email Null to get, String with email, |
||
705 | * Array with email as key, name as value or email as value (without name) |
||
706 | * @param string|null $name Name |
||
707 | * @return $this |
||
708 | */ |
||
709 | public function addCc($email, $name = null) |
||
710 | { |
||
711 | return $this->_addEmail('_cc', $email, $name); |
||
712 | } |
||
713 | |||
714 | /** |
||
715 | * Sets "bcc" address. |
||
716 | * |
||
717 | * @param string|array $email String with email, |
||
718 | * Array with email as key, name as value or email as value (without name) |
||
719 | * @param string|null $name Name |
||
720 | * @return $this |
||
721 | */ |
||
722 | public function setBcc($email, $name = null) |
||
723 | { |
||
724 | return $this->_setEmail('_bcc', $email, $name); |
||
725 | } |
||
726 | |||
727 | /** |
||
728 | * Gets "bcc" address. |
||
729 | * |
||
730 | * @return array |
||
731 | */ |
||
732 | public function getBcc() |
||
733 | { |
||
734 | return $this->_bcc; |
||
735 | } |
||
736 | |||
737 | /** |
||
738 | * Bcc |
||
739 | * |
||
740 | * @deprecated 3.4.0 Use setBcc()/getBcc() instead. |
||
741 | * @param string|array|null $email Null to get, String with email, |
||
742 | * Array with email as key, name as value or email as value (without name) |
||
743 | * @param string|null $name Name |
||
744 | * @return array|$this |
||
745 | */ |
||
746 | public function bcc($email = null, $name = null) |
||
747 | { |
||
748 | deprecationWarning('Email::bcc() is deprecated. Use Email::setBcc() or Email::getBcc() instead.'); |
||
749 | |||
750 | if ($email === null) { |
||
751 | return $this->getBcc(); |
||
752 | } |
||
753 | |||
754 | return $this->setBcc($email, $name); |
||
755 | } |
||
756 | |||
757 | /** |
||
758 | * Add Bcc |
||
759 | * |
||
760 | * @param string|array $email Null to get, String with email, |
||
761 | * Array with email as key, name as value or email as value (without name) |
||
762 | * @param string|null $name Name |
||
763 | * @return $this |
||
764 | */ |
||
765 | public function addBcc($email, $name = null) |
||
766 | { |
||
767 | return $this->_addEmail('_bcc', $email, $name); |
||
768 | } |
||
769 | |||
770 | /** |
||
771 | * Charset setter. |
||
772 | * |
||
773 | * @param string|null $charset Character set. |
||
774 | * @return $this |
||
775 | */ |
||
776 | public function setCharset($charset) |
||
777 | { |
||
778 | $this->charset = $charset; |
||
779 | if (!$this->headerCharset) { |
||
780 | $this->headerCharset = $charset; |
||
781 | } |
||
782 | |||
783 | return $this; |
||
784 | } |
||
785 | |||
786 | /** |
||
787 | * Charset getter. |
||
788 | * |
||
789 | * @return string Charset |
||
790 | */ |
||
791 | public function getCharset() |
||
792 | { |
||
793 | return $this->charset; |
||
794 | } |
||
795 | |||
796 | /** |
||
797 | * Charset setter/getter |
||
798 | * |
||
799 | * @deprecated 3.4.0 Use setCharset()/getCharset() instead. |
||
800 | * @param string|null $charset Character set. |
||
801 | * @return string Charset |
||
802 | */ |
||
803 | public function charset($charset = null) |
||
804 | { |
||
805 | deprecationWarning('Email::charset() is deprecated. Use Email::setCharset() or Email::getCharset() instead.'); |
||
806 | |||
807 | if ($charset === null) { |
||
808 | return $this->getCharset(); |
||
809 | } |
||
810 | $this->setCharset($charset); |
||
811 | |||
812 | return $this->charset; |
||
813 | } |
||
814 | |||
815 | /** |
||
816 | * HeaderCharset setter. |
||
817 | * |
||
818 | * @param string|null $charset Character set. |
||
819 | * @return $this |
||
820 | */ |
||
821 | public function setHeaderCharset($charset) |
||
822 | { |
||
823 | $this->headerCharset = $charset; |
||
824 | |||
825 | return $this; |
||
826 | } |
||
827 | |||
828 | /** |
||
829 | * HeaderCharset getter. |
||
830 | * |
||
831 | * @return string Charset |
||
832 | */ |
||
833 | public function getHeaderCharset() |
||
834 | { |
||
835 | return $this->headerCharset; |
||
836 | } |
||
837 | |||
838 | /** |
||
839 | * HeaderCharset setter/getter |
||
840 | * |
||
841 | * @deprecated 3.4.0 Use setHeaderCharset()/getHeaderCharset() instead. |
||
842 | * @param string|null $charset Character set. |
||
843 | * @return string Charset |
||
844 | */ |
||
845 | public function headerCharset($charset = null) |
||
846 | { |
||
847 | deprecationWarning('Email::headerCharset() is deprecated. Use Email::setHeaderCharset() or Email::getHeaderCharset() instead.'); |
||
848 | |||
849 | if ($charset === null) { |
||
850 | return $this->getHeaderCharset(); |
||
851 | } |
||
852 | |||
853 | $this->setHeaderCharset($charset); |
||
854 | |||
855 | return $this->headerCharset; |
||
856 | } |
||
857 | |||
858 | /** |
||
859 | * TransferEncoding setter. |
||
860 | * |
||
861 | * @param string|null $encoding Encoding set. |
||
862 | * @return $this |
||
863 | */ |
||
864 | public function setTransferEncoding($encoding) |
||
865 | { |
||
866 | $encoding = strtolower($encoding); |
||
867 | if (!in_array($encoding, $this->_transferEncodingAvailable)) { |
||
868 | throw new InvalidArgumentException( |
||
869 | sprintf( |
||
870 | 'Transfer encoding not available. Can be : %s.', |
||
871 | implode(', ', $this->_transferEncodingAvailable) |
||
872 | ) |
||
873 | ); |
||
874 | } |
||
875 | $this->transferEncoding = $encoding; |
||
876 | |||
877 | return $this; |
||
878 | } |
||
879 | |||
880 | /** |
||
881 | * TransferEncoding getter. |
||
882 | * |
||
883 | * @return string|null Encoding |
||
884 | */ |
||
885 | public function getTransferEncoding() |
||
886 | { |
||
887 | return $this->transferEncoding; |
||
888 | } |
||
889 | |||
890 | /** |
||
891 | * EmailPattern setter/getter |
||
892 | * |
||
893 | * @param string|null $regex The pattern to use for email address validation, |
||
894 | * null to unset the pattern and make use of filter_var() instead. |
||
895 | * @return $this |
||
896 | */ |
||
897 | public function setEmailPattern($regex) |
||
898 | { |
||
899 | $this->_emailPattern = $regex; |
||
900 | |||
901 | return $this; |
||
902 | } |
||
903 | |||
904 | /** |
||
905 | * EmailPattern setter/getter |
||
906 | * |
||
907 | * @return string |
||
908 | */ |
||
909 | public function getEmailPattern() |
||
910 | { |
||
911 | return $this->_emailPattern; |
||
912 | } |
||
913 | |||
914 | /** |
||
915 | * EmailPattern setter/getter |
||
916 | * |
||
917 | * @deprecated 3.4.0 Use setEmailPattern()/getEmailPattern() instead. |
||
918 | * @param string|bool|null $regex The pattern to use for email address validation, |
||
919 | * null to unset the pattern and make use of filter_var() instead, false or |
||
920 | * nothing to return the current value |
||
921 | * @return string|$this |
||
922 | */ |
||
923 | public function emailPattern($regex = false) |
||
924 | { |
||
925 | deprecationWarning('Email::emailPattern() is deprecated. Use Email::setEmailPattern() or Email::getEmailPattern() instead.'); |
||
926 | |||
927 | if ($regex === false) { |
||
928 | return $this->getEmailPattern(); |
||
929 | } |
||
930 | |||
931 | return $this->setEmailPattern($regex); |
||
932 | } |
||
933 | |||
934 | /** |
||
935 | * Set email |
||
936 | * |
||
937 | * @param string $varName Property name |
||
938 | * @param string|array $email String with email, |
||
939 | * Array with email as key, name as value or email as value (without name) |
||
940 | * @param string $name Name |
||
941 | * @return $this |
||
942 | * @throws \InvalidArgumentException |
||
943 | */ |
||
944 | View Code Duplication | protected function _setEmail($varName, $email, $name) |
|
945 | { |
||
946 | if (!is_array($email)) { |
||
947 | $this->_validateEmail($email, $varName); |
||
948 | if ($name === null) { |
||
949 | $name = $email; |
||
950 | } |
||
951 | $this->{$varName} = [$email => $name]; |
||
952 | |||
953 | return $this; |
||
954 | } |
||
955 | $list = []; |
||
956 | foreach ($email as $key => $value) { |
||
957 | if (is_int($key)) { |
||
958 | $key = $value; |
||
959 | } |
||
960 | $this->_validateEmail($key, $varName); |
||
961 | $list[$key] = $value; |
||
962 | } |
||
963 | $this->{$varName} = $list; |
||
964 | |||
965 | return $this; |
||
966 | } |
||
967 | |||
968 | /** |
||
969 | * Validate email address |
||
970 | * |
||
971 | * @param string $email Email address to validate |
||
972 | * @param string $context Which property was set |
||
973 | * @return void |
||
974 | * @throws \InvalidArgumentException If email address does not validate |
||
975 | */ |
||
976 | protected function _validateEmail($email, $context) |
||
977 | { |
||
978 | if ($this->_emailPattern === null) { |
||
979 | if (filter_var($email, FILTER_VALIDATE_EMAIL)) { |
||
980 | return; |
||
981 | } |
||
982 | } elseif (preg_match($this->_emailPattern, $email)) { |
||
983 | return; |
||
984 | } |
||
985 | |||
986 | $context = ltrim($context, '_'); |
||
987 | if ($email == '') { |
||
988 | throw new InvalidArgumentException(sprintf('The email set for "%s" is empty.', $context)); |
||
989 | } |
||
990 | throw new InvalidArgumentException(sprintf('Invalid email set for "%s". You passed "%s".', $context, $email)); |
||
991 | } |
||
992 | |||
993 | /** |
||
994 | * Set only 1 email |
||
995 | * |
||
996 | * @param string $varName Property name |
||
997 | * @param string|array $email String with email, |
||
998 | * Array with email as key, name as value or email as value (without name) |
||
999 | * @param string $name Name |
||
1000 | * @param string $throwMessage Exception message |
||
1001 | * @return $this |
||
1002 | * @throws \InvalidArgumentException |
||
1003 | */ |
||
1004 | protected function _setEmailSingle($varName, $email, $name, $throwMessage) |
||
1005 | { |
||
1006 | if ($email === []) { |
||
1007 | $this->{$varName} = $email; |
||
1008 | |||
1009 | return $this; |
||
1010 | } |
||
1011 | |||
1012 | $current = $this->{$varName}; |
||
1013 | $this->_setEmail($varName, $email, $name); |
||
1014 | if (count($this->{$varName}) !== 1) { |
||
1015 | $this->{$varName} = $current; |
||
1016 | throw new InvalidArgumentException($throwMessage); |
||
1017 | } |
||
1018 | |||
1019 | return $this; |
||
1020 | } |
||
1021 | |||
1022 | /** |
||
1023 | * Add email |
||
1024 | * |
||
1025 | * @param string $varName Property name |
||
1026 | * @param string|array $email String with email, |
||
1027 | * Array with email as key, name as value or email as value (without name) |
||
1028 | * @param string $name Name |
||
1029 | * @return $this |
||
1030 | * @throws \InvalidArgumentException |
||
1031 | */ |
||
1032 | View Code Duplication | protected function _addEmail($varName, $email, $name) |
|
1033 | { |
||
1034 | if (!is_array($email)) { |
||
1035 | $this->_validateEmail($email, $varName); |
||
1036 | if ($name === null) { |
||
1037 | $name = $email; |
||
1038 | } |
||
1039 | $this->{$varName}[$email] = $name; |
||
1040 | |||
1041 | return $this; |
||
1042 | } |
||
1043 | $list = []; |
||
1044 | foreach ($email as $key => $value) { |
||
1045 | if (is_int($key)) { |
||
1046 | $key = $value; |
||
1047 | } |
||
1048 | $this->_validateEmail($key, $varName); |
||
1049 | $list[$key] = $value; |
||
1050 | } |
||
1051 | $this->{$varName} = array_merge($this->{$varName}, $list); |
||
1052 | |||
1053 | return $this; |
||
1054 | } |
||
1055 | |||
1056 | /** |
||
1057 | * Sets subject. |
||
1058 | * |
||
1059 | * @param string $subject Subject string. |
||
1060 | * @return $this |
||
1061 | */ |
||
1062 | public function setSubject($subject) |
||
1063 | { |
||
1064 | $this->_subject = $this->_encode((string)$subject); |
||
1065 | |||
1066 | return $this; |
||
1067 | } |
||
1068 | |||
1069 | /** |
||
1070 | * Gets subject. |
||
1071 | * |
||
1072 | * @return string |
||
1073 | */ |
||
1074 | public function getSubject() |
||
1075 | { |
||
1076 | return $this->_subject; |
||
1077 | } |
||
1078 | |||
1079 | /** |
||
1080 | * Get/Set Subject. |
||
1081 | * |
||
1082 | * @deprecated 3.4.0 Use setSubject()/getSubject() instead. |
||
1083 | * @param string|null $subject Subject string. |
||
1084 | * @return string|$this |
||
1085 | */ |
||
1086 | public function subject($subject = null) |
||
1087 | { |
||
1088 | deprecationWarning('Email::subject() is deprecated. Use Email::setSubject() or Email::getSubject() instead.'); |
||
1089 | |||
1090 | if ($subject === null) { |
||
1091 | return $this->getSubject(); |
||
1092 | } |
||
1093 | |||
1094 | return $this->setSubject($subject); |
||
1095 | } |
||
1096 | |||
1097 | /** |
||
1098 | * Get original subject without encoding |
||
1099 | * |
||
1100 | * @return string Original subject |
||
1101 | */ |
||
1102 | public function getOriginalSubject() |
||
1103 | { |
||
1104 | return $this->_decode($this->_subject); |
||
1105 | } |
||
1106 | |||
1107 | /** |
||
1108 | * Sets headers for the message |
||
1109 | * |
||
1110 | * @param array $headers Associative array containing headers to be set. |
||
1111 | * @return $this |
||
1112 | */ |
||
1113 | public function setHeaders(array $headers) |
||
1114 | { |
||
1115 | $this->_headers = $headers; |
||
1116 | |||
1117 | return $this; |
||
1118 | } |
||
1119 | |||
1120 | /** |
||
1121 | * Add header for the message |
||
1122 | * |
||
1123 | * @param array $headers Headers to set. |
||
1124 | * @return $this |
||
1125 | */ |
||
1126 | public function addHeaders(array $headers) |
||
1127 | { |
||
1128 | $this->_headers = Hash::merge($this->_headers, $headers); |
||
1129 | |||
1130 | return $this; |
||
1131 | } |
||
1132 | |||
1133 | /** |
||
1134 | * Get list of headers |
||
1135 | * |
||
1136 | * ### Includes: |
||
1137 | * |
||
1138 | * - `from` |
||
1139 | * - `replyTo` |
||
1140 | * - `readReceipt` |
||
1141 | * - `returnPath` |
||
1142 | * - `to` |
||
1143 | * - `cc` |
||
1144 | * - `bcc` |
||
1145 | * - `subject` |
||
1146 | * |
||
1147 | * @param array $include List of headers. |
||
1148 | * @return array |
||
1149 | */ |
||
1150 | public function getHeaders(array $include = []) |
||
1151 | { |
||
1152 | if ($include == array_values($include)) { |
||
1153 | $include = array_fill_keys($include, true); |
||
1154 | } |
||
1155 | $defaults = array_fill_keys( |
||
1156 | [ |
||
1157 | 'from', 'sender', 'replyTo', 'readReceipt', 'returnPath', |
||
1158 | 'to', 'cc', 'bcc', 'subject'], |
||
1159 | false |
||
1160 | ); |
||
1161 | $include += $defaults; |
||
1162 | |||
1163 | $headers = []; |
||
1164 | $relation = [ |
||
1165 | 'from' => 'From', |
||
1166 | 'replyTo' => 'Reply-To', |
||
1167 | 'readReceipt' => 'Disposition-Notification-To', |
||
1168 | 'returnPath' => 'Return-Path' |
||
1169 | ]; |
||
1170 | foreach ($relation as $var => $header) { |
||
1171 | if ($include[$var]) { |
||
1172 | $var = '_' . $var; |
||
1173 | $headers[$header] = current($this->_formatAddress($this->{$var})); |
||
1174 | } |
||
1175 | } |
||
1176 | if ($include['sender']) { |
||
1177 | if (key($this->_sender) === key($this->_from)) { |
||
1178 | $headers['Sender'] = ''; |
||
1179 | } else { |
||
1180 | $headers['Sender'] = current($this->_formatAddress($this->_sender)); |
||
1181 | } |
||
1182 | } |
||
1183 | |||
1184 | foreach (['to', 'cc', 'bcc'] as $var) { |
||
1185 | if ($include[$var]) { |
||
1186 | $classVar = '_' . $var; |
||
1187 | $headers[ucfirst($var)] = implode(', ', $this->_formatAddress($this->{$classVar})); |
||
1188 | } |
||
1189 | } |
||
1190 | |||
1191 | $headers += $this->_headers; |
||
1192 | if (!isset($headers['Date'])) { |
||
1193 | $headers['Date'] = date(DATE_RFC2822); |
||
1194 | } |
||
1195 | if ($this->_messageId !== false) { |
||
1196 | if ($this->_messageId === true) { |
||
1197 | $this->_messageId = '<' . str_replace('-', '', Text::uuid()) . '@' . $this->_domain . '>'; |
||
1198 | } |
||
1199 | |||
1200 | $headers['Message-ID'] = $this->_messageId; |
||
1201 | } |
||
1202 | |||
1203 | if ($this->_priority) { |
||
1204 | $headers['X-Priority'] = $this->_priority; |
||
1205 | } |
||
1206 | |||
1207 | if ($include['subject']) { |
||
1208 | $headers['Subject'] = $this->_subject; |
||
1209 | } |
||
1210 | |||
1211 | $headers['MIME-Version'] = '1.0'; |
||
1212 | if ($this->_attachments) { |
||
1213 | $headers['Content-Type'] = 'multipart/mixed; boundary="' . $this->_boundary . '"'; |
||
1214 | } elseif ($this->_emailFormat === 'both') { |
||
1215 | $headers['Content-Type'] = 'multipart/alternative; boundary="' . $this->_boundary . '"'; |
||
1216 | } elseif ($this->_emailFormat === 'text') { |
||
1217 | $headers['Content-Type'] = 'text/plain; charset=' . $this->_getContentTypeCharset(); |
||
1218 | } elseif ($this->_emailFormat === 'html') { |
||
1219 | $headers['Content-Type'] = 'text/html; charset=' . $this->_getContentTypeCharset(); |
||
1220 | } |
||
1221 | $headers['Content-Transfer-Encoding'] = $this->_getContentTransferEncoding(); |
||
1222 | |||
1223 | return $headers; |
||
1224 | } |
||
1225 | |||
1226 | /** |
||
1227 | * Format addresses |
||
1228 | * |
||
1229 | * If the address contains non alphanumeric/whitespace characters, it will |
||
1230 | * be quoted as characters like `:` and `,` are known to cause issues |
||
1231 | * in address header fields. |
||
1232 | * |
||
1233 | * @param array $address Addresses to format. |
||
1234 | * @return array |
||
1235 | */ |
||
1236 | protected function _formatAddress($address) |
||
1237 | { |
||
1238 | $return = []; |
||
1239 | foreach ($address as $email => $alias) { |
||
1240 | if ($email === $alias) { |
||
1241 | $return[] = $email; |
||
1242 | } else { |
||
1243 | $encoded = $this->_encode($alias); |
||
1244 | if ($encoded === $alias && preg_match('/[^a-z0-9 ]/i', $encoded)) { |
||
1245 | $encoded = '"' . str_replace('"', '\"', $encoded) . '"'; |
||
1246 | } |
||
1247 | $return[] = sprintf('%s <%s>', $encoded, $email); |
||
1248 | } |
||
1249 | } |
||
1250 | |||
1251 | return $return; |
||
1252 | } |
||
1253 | |||
1254 | /** |
||
1255 | * Sets template. |
||
1256 | * |
||
1257 | * @param string|null $template Template name or null to not use. |
||
1258 | * @return $this |
||
1259 | */ |
||
1260 | public function setTemplate($template) |
||
1261 | { |
||
1262 | deprecationWarning( |
||
1263 | 'Email::setTemplate() is deprecated. Use $email->viewBuilder()->setTemplate() instead.' |
||
1264 | ); |
||
1265 | |||
1266 | $this->viewBuilder()->setTemplate($template ?: ''); |
||
1267 | |||
1268 | return $this; |
||
1269 | } |
||
1270 | |||
1271 | /** |
||
1272 | * Gets template. |
||
1273 | * |
||
1274 | * @return string |
||
1275 | */ |
||
1276 | public function getTemplate() |
||
1277 | { |
||
1278 | deprecationWarning( |
||
1279 | 'Email::getTemplate() is deprecated. Use $email->viewBuilder()->getTemplate() instead.' |
||
1280 | ); |
||
1281 | |||
1282 | return $this->viewBuilder()->getTemplate(); |
||
1283 | } |
||
1284 | |||
1285 | /** |
||
1286 | * Sets layout. |
||
1287 | * |
||
1288 | * @param string|null $layout Layout name or null to not use |
||
1289 | * @return $this |
||
1290 | * @deprecated 3.7.0 Use $email->viewBuilder()->setLayout() instead. |
||
1291 | */ |
||
1292 | public function setLayout($layout) |
||
1293 | { |
||
1294 | deprecationWarning( |
||
1295 | 'Email::setLayout() is deprecated. Use $email->viewBuilder()->setLayout() instead.' |
||
1296 | ); |
||
1297 | |||
1298 | $this->viewBuilder()->setLayout($layout ?: false); |
||
1299 | |||
1300 | return $this; |
||
1301 | } |
||
1302 | |||
1303 | /** |
||
1304 | * Gets layout. |
||
1305 | * |
||
1306 | * @deprecated 3.7.0 Use $email->viewBuilder()->getLayout() instead. |
||
1307 | * @return string |
||
1308 | */ |
||
1309 | public function getLayout() |
||
1310 | { |
||
1311 | deprecationWarning( |
||
1312 | 'Email::getLayout() is deprecated. Use $email->viewBuilder()->getLayout() instead.' |
||
1313 | ); |
||
1314 | |||
1315 | return $this->viewBuilder()->getLayout(); |
||
1316 | } |
||
1317 | |||
1318 | /** |
||
1319 | * Template and layout |
||
1320 | * |
||
1321 | * @deprecated 3.4.0 Use setTemplate()/getTemplate() and setLayout()/getLayout() instead. |
||
1322 | * @param bool|string $template Template name or null to not use |
||
1323 | * @param bool|string $layout Layout name or null to not use |
||
1324 | * @return array|$this |
||
1325 | */ |
||
1326 | public function template($template = false, $layout = false) |
||
1327 | { |
||
1328 | deprecationWarning( |
||
1329 | 'Email::template() is deprecated. ' . |
||
1330 | 'Use $email->viewBuilder()->getTemplate()/setTemplate() ' . |
||
1331 | 'and $email->viewBuilder()->getLayout()/setLayout() instead.' |
||
1332 | ); |
||
1333 | |||
1334 | if ($template === false) { |
||
1335 | return [ |
||
1336 | 'template' => $this->getTemplate(), |
||
1337 | 'layout' => $this->getLayout() |
||
1338 | ]; |
||
1339 | } |
||
1340 | $this->setTemplate($template); |
||
1341 | if ($layout !== false) { |
||
1342 | $this->setLayout($layout); |
||
1343 | } |
||
1344 | |||
1345 | return $this; |
||
1346 | } |
||
1347 | |||
1348 | /** |
||
1349 | * Sets view class for render. |
||
1350 | * |
||
1351 | * @param string $viewClass View class name. |
||
1352 | * @return $this |
||
1353 | */ |
||
1354 | public function setViewRenderer($viewClass) |
||
1355 | { |
||
1356 | $this->viewBuilder()->setClassName($viewClass); |
||
1357 | |||
1358 | return $this; |
||
1359 | } |
||
1360 | |||
1361 | /** |
||
1362 | * Gets view class for render. |
||
1363 | * |
||
1364 | * @return string |
||
1365 | */ |
||
1366 | public function getViewRenderer() |
||
1367 | { |
||
1368 | return $this->viewBuilder()->getClassName(); |
||
1369 | } |
||
1370 | |||
1371 | /** |
||
1372 | * View class for render |
||
1373 | * |
||
1374 | * @deprecated 3.4.0 Use setViewRenderer()/getViewRenderer() instead. |
||
1375 | * @param string|null $viewClass View class name. |
||
1376 | * @return string|$this |
||
1377 | */ |
||
1378 | public function viewRender($viewClass = null) |
||
1379 | { |
||
1380 | deprecationWarning('Email::viewRender() is deprecated. Use Email::setViewRenderer() or Email::getViewRenderer() instead.'); |
||
1381 | |||
1382 | if ($viewClass === null) { |
||
1383 | return $this->getViewRenderer(); |
||
1384 | } |
||
1385 | $this->setViewRenderer($viewClass); |
||
1386 | |||
1387 | return $this; |
||
1388 | } |
||
1389 | |||
1390 | /** |
||
1391 | * Sets variables to be set on render. |
||
1392 | * |
||
1393 | * @param array $viewVars Variables to set for view. |
||
1394 | * @return $this |
||
1395 | */ |
||
1396 | public function setViewVars($viewVars) |
||
1397 | { |
||
1398 | $this->set((array)$viewVars); |
||
1399 | |||
1400 | return $this; |
||
1401 | } |
||
1402 | |||
1403 | /** |
||
1404 | * Gets variables to be set on render. |
||
1405 | * |
||
1406 | * @return array |
||
1407 | */ |
||
1408 | public function getViewVars() |
||
1409 | { |
||
1410 | return $this->viewVars; |
||
1411 | } |
||
1412 | |||
1413 | /** |
||
1414 | * Variables to be set on render |
||
1415 | * |
||
1416 | * @deprecated 3.4.0 Use setViewVars()/getViewVars() instead. |
||
1417 | * @param array|null $viewVars Variables to set for view. |
||
1418 | * @return array|$this |
||
1419 | */ |
||
1420 | public function viewVars($viewVars = null) |
||
1421 | { |
||
1422 | deprecationWarning('Email::viewVars() is deprecated. Use Email::setViewVars() or Email::getViewVars() instead.'); |
||
1423 | |||
1424 | if ($viewVars === null) { |
||
1425 | return $this->getViewVars(); |
||
1426 | } |
||
1427 | |||
1428 | return $this->setViewVars($viewVars); |
||
1429 | } |
||
1430 | |||
1431 | /** |
||
1432 | * Sets theme to use when rendering. |
||
1433 | * |
||
1434 | * @param string $theme Theme name. |
||
1435 | * @return $this |
||
1436 | * @deprecated 3.7.0 Use $email->viewBuilder()->setTheme() instead. |
||
1437 | */ |
||
1438 | public function setTheme($theme) |
||
1439 | { |
||
1440 | deprecationWarning( |
||
1441 | 'Email::setTheme() is deprecated. Use $email->viewBuilder()->setTheme() instead.' |
||
1442 | ); |
||
1443 | |||
1444 | $this->viewBuilder()->setTheme($theme); |
||
1445 | |||
1446 | return $this; |
||
1447 | } |
||
1448 | |||
1449 | /** |
||
1450 | * Gets theme to use when rendering. |
||
1451 | * |
||
1452 | * @return string |
||
1453 | * @deprecated 3.7.0 Use $email->viewBuilder()->getTheme() instead. |
||
1454 | */ |
||
1455 | public function getTheme() |
||
1456 | { |
||
1457 | deprecationWarning( |
||
1458 | 'Email::getTheme() is deprecated. Use $email->viewBuilder()->getTheme() instead.' |
||
1459 | ); |
||
1460 | |||
1461 | return $this->viewBuilder()->getTheme(); |
||
1462 | } |
||
1463 | |||
1464 | /** |
||
1465 | * Theme to use when rendering |
||
1466 | * |
||
1467 | * @deprecated 3.4.0 Use setTheme()/getTheme() instead. |
||
1468 | * @param string|null $theme Theme name. |
||
1469 | * @return string|$this |
||
1470 | */ |
||
1471 | View Code Duplication | public function theme($theme = null) |
|
1472 | { |
||
1473 | deprecationWarning( |
||
1474 | 'Email::theme() is deprecated. Use $email->viewBuilder()->getTheme()/setTheme() instead.' |
||
1475 | ); |
||
1476 | |||
1477 | if ($theme === null) { |
||
1478 | return $this->getTheme(); |
||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
Loading history...
|
|||
1479 | } |
||
1480 | |||
1481 | return $this->setTheme($theme); |
||
1482 | } |
||
1483 | |||
1484 | /** |
||
1485 | * Sets helpers to be used when rendering. |
||
1486 | * |
||
1487 | * @param array $helpers Helpers list. |
||
1488 | * @return $this |
||
1489 | * @deprecated 3.7.0 Use $email->viewBuilder()->setHelpers() instead. |
||
1490 | */ |
||
1491 | public function setHelpers(array $helpers) |
||
1492 | { |
||
1493 | deprecationWarning( |
||
1494 | 'Email::setHelpers() is deprecated. Use $email->viewBuilder()->setHelpers() instead.' |
||
1495 | ); |
||
1496 | |||
1497 | $this->viewBuilder()->setHelpers($helpers, false); |
||
1498 | |||
1499 | return $this; |
||
1500 | } |
||
1501 | |||
1502 | /** |
||
1503 | * Gets helpers to be used when rendering. |
||
1504 | * |
||
1505 | * @return array |
||
1506 | * @deprecated 3.7.0 Use $email->viewBuilder()->getHelpers() instead. |
||
1507 | */ |
||
1508 | public function getHelpers() |
||
1509 | { |
||
1510 | deprecationWarning( |
||
1511 | 'Email::getHelpers() is deprecated. Use $email->viewBuilder()->getHelpers() instead.' |
||
1512 | ); |
||
1513 | |||
1514 | return $this->viewBuilder()->getHelpers(); |
||
1515 | } |
||
1516 | |||
1517 | /** |
||
1518 | * Helpers to be used in render |
||
1519 | * |
||
1520 | * @deprecated 3.4.0 Use setHelpers()/getHelpers() instead. |
||
1521 | * @param array|null $helpers Helpers list. |
||
1522 | * @return array|$this |
||
1523 | */ |
||
1524 | View Code Duplication | public function helpers($helpers = null) |
|
1525 | { |
||
1526 | deprecationWarning( |
||
1527 | 'Email::helpers() is deprecated. Use $email->viewBuilder()->getHelpers()/setHelpers() instead.' |
||
1528 | ); |
||
1529 | |||
1530 | if ($helpers === null) { |
||
1531 | return $this->getHelpers(); |
||
1532 | } |
||
1533 | |||
1534 | return $this->setHelpers((array)$helpers); |
||
1535 | } |
||
1536 | |||
1537 | /** |
||
1538 | * Sets email format. |
||
1539 | * |
||
1540 | * @param string $format Formatting string. |
||
1541 | * @return $this |
||
1542 | * @throws \InvalidArgumentException |
||
1543 | */ |
||
1544 | public function setEmailFormat($format) |
||
1545 | { |
||
1546 | if (!in_array($format, $this->_emailFormatAvailable)) { |
||
1547 | throw new InvalidArgumentException('Format not available.'); |
||
1548 | } |
||
1549 | $this->_emailFormat = $format; |
||
1550 | |||
1551 | return $this; |
||
1552 | } |
||
1553 | |||
1554 | /** |
||
1555 | * Gets email format. |
||
1556 | * |
||
1557 | * @return string |
||
1558 | */ |
||
1559 | public function getEmailFormat() |
||
1560 | { |
||
1561 | return $this->_emailFormat; |
||
1562 | } |
||
1563 | |||
1564 | /** |
||
1565 | * Email format |
||
1566 | * |
||
1567 | * @deprecated 3.4.0 Use setEmailFormat()/getEmailFormat() instead. |
||
1568 | * @param string|null $format Formatting string. |
||
1569 | * @return string|$this |
||
1570 | * @throws \InvalidArgumentException |
||
1571 | */ |
||
1572 | public function emailFormat($format = null) |
||
1573 | { |
||
1574 | deprecationWarning('Email::emailFormat() is deprecated. Use Email::setEmailFormat() or Email::getEmailFormat() instead.'); |
||
1575 | |||
1576 | if ($format === null) { |
||
1577 | return $this->getEmailFormat(); |
||
1578 | } |
||
1579 | |||
1580 | return $this->setEmailFormat($format); |
||
1581 | } |
||
1582 | |||
1583 | /** |
||
1584 | * Sets the transport. |
||
1585 | * |
||
1586 | * When setting the transport you can either use the name |
||
1587 | * of a configured transport or supply a constructed transport. |
||
1588 | * |
||
1589 | * @param string|\Cake\Mailer\AbstractTransport $name Either the name of a configured |
||
1590 | * transport, or a transport instance. |
||
1591 | * @return $this |
||
1592 | * @throws \LogicException When the chosen transport lacks a send method. |
||
1593 | * @throws \InvalidArgumentException When $name is neither a string nor an object. |
||
1594 | */ |
||
1595 | public function setTransport($name) |
||
1596 | { |
||
1597 | if (is_string($name)) { |
||
1598 | $transport = TransportFactory::get($name); |
||
1599 | } elseif (is_object($name)) { |
||
1600 | $transport = $name; |
||
1601 | } else { |
||
1602 | throw new InvalidArgumentException( |
||
1603 | sprintf('The value passed for the "$name" argument must be either a string, or an object, %s given.', gettype($name)) |
||
1604 | ); |
||
1605 | } |
||
1606 | if (!method_exists($transport, 'send')) { |
||
1607 | throw new LogicException(sprintf('The "%s" do not have send method.', get_class($transport))); |
||
1608 | } |
||
1609 | |||
1610 | $this->_transport = $transport; |
||
1611 | |||
1612 | return $this; |
||
1613 | } |
||
1614 | |||
1615 | /** |
||
1616 | * Gets the transport. |
||
1617 | * |
||
1618 | * @return \Cake\Mailer\AbstractTransport |
||
1619 | */ |
||
1620 | public function getTransport() |
||
1621 | { |
||
1622 | return $this->_transport; |
||
1623 | } |
||
1624 | |||
1625 | /** |
||
1626 | * Get/set the transport. |
||
1627 | * |
||
1628 | * When setting the transport you can either use the name |
||
1629 | * of a configured transport or supply a constructed transport. |
||
1630 | * |
||
1631 | * @deprecated 3.4.0 Use setTransport()/getTransport() instead. |
||
1632 | * @param string|\Cake\Mailer\AbstractTransport|null $name Either the name of a configured |
||
1633 | * transport, or a transport instance. |
||
1634 | * @return \Cake\Mailer\AbstractTransport|$this |
||
1635 | * @throws \LogicException When the chosen transport lacks a send method. |
||
1636 | * @throws \InvalidArgumentException When $name is neither a string nor an object. |
||
1637 | */ |
||
1638 | public function transport($name = null) |
||
1639 | { |
||
1640 | deprecationWarning('Email::transport() is deprecated. Use Email::setTransport() or Email::getTransport() instead.'); |
||
1641 | |||
1642 | if ($name === null) { |
||
1643 | return $this->getTransport(); |
||
1644 | } |
||
1645 | |||
1646 | return $this->setTransport($name); |
||
1647 | } |
||
1648 | |||
1649 | /** |
||
1650 | * Sets message ID. |
||
1651 | * |
||
1652 | * @param bool|string $message True to generate a new Message-ID, False to ignore (not send in email), String to set as Message-ID. |
||
1653 | * @return $this |
||
1654 | * @throws \InvalidArgumentException |
||
1655 | */ |
||
1656 | public function setMessageId($message) |
||
1657 | { |
||
1658 | if (is_bool($message)) { |
||
1659 | $this->_messageId = $message; |
||
1660 | } else { |
||
1661 | if (!preg_match('/^\<.+@.+\>$/', $message)) { |
||
1662 | throw new InvalidArgumentException('Invalid format to Message-ID. The text should be something like "<[email protected]>"'); |
||
1663 | } |
||
1664 | $this->_messageId = $message; |
||
1665 | } |
||
1666 | |||
1667 | return $this; |
||
1668 | } |
||
1669 | |||
1670 | /** |
||
1671 | * Gets message ID. |
||
1672 | * |
||
1673 | * @return bool|string |
||
1674 | */ |
||
1675 | public function getMessageId() |
||
1676 | { |
||
1677 | return $this->_messageId; |
||
1678 | } |
||
1679 | |||
1680 | /** |
||
1681 | * Message-ID |
||
1682 | * |
||
1683 | * @deprecated 3.4.0 Use setMessageId()/getMessageId() instead. |
||
1684 | * @param bool|string|null $message True to generate a new Message-ID, False to ignore (not send in email), String to set as Message-ID |
||
1685 | * @return bool|string|$this |
||
1686 | * @throws \InvalidArgumentException |
||
1687 | */ |
||
1688 | public function messageId($message = null) |
||
1689 | { |
||
1690 | deprecationWarning('Email::messageId() is deprecated. Use Email::setMessageId() or Email::getMessageId() instead.'); |
||
1691 | |||
1692 | if ($message === null) { |
||
1693 | return $this->getMessageId(); |
||
1694 | } |
||
1695 | |||
1696 | return $this->setMessageId($message); |
||
1697 | } |
||
1698 | |||
1699 | /** |
||
1700 | * Sets domain. |
||
1701 | * |
||
1702 | * Domain as top level (the part after @). |
||
1703 | * |
||
1704 | * @param string $domain Manually set the domain for CLI mailing. |
||
1705 | * @return $this |
||
1706 | */ |
||
1707 | public function setDomain($domain) |
||
1708 | { |
||
1709 | $this->_domain = $domain; |
||
1710 | |||
1711 | return $this; |
||
1712 | } |
||
1713 | |||
1714 | /** |
||
1715 | * Gets domain. |
||
1716 | * |
||
1717 | * @return string |
||
1718 | */ |
||
1719 | public function getDomain() |
||
1720 | { |
||
1721 | return $this->_domain; |
||
1722 | } |
||
1723 | |||
1724 | /** |
||
1725 | * Domain as top level (the part after @) |
||
1726 | * |
||
1727 | * @deprecated 3.4.0 Use setDomain()/getDomain() instead. |
||
1728 | * @param string|null $domain Manually set the domain for CLI mailing |
||
1729 | * @return string|$this |
||
1730 | */ |
||
1731 | public function domain($domain = null) |
||
1732 | { |
||
1733 | deprecationWarning('Email::domain() is deprecated. Use Email::setDomain() or Email::getDomain() instead.'); |
||
1734 | |||
1735 | if ($domain === null) { |
||
1736 | return $this->getDomain(); |
||
1737 | } |
||
1738 | |||
1739 | return $this->setDomain($domain); |
||
1740 | } |
||
1741 | |||
1742 | /** |
||
1743 | * Add attachments to the email message |
||
1744 | * |
||
1745 | * Attachments can be defined in a few forms depending on how much control you need: |
||
1746 | * |
||
1747 | * Attach a single file: |
||
1748 | * |
||
1749 | * ``` |
||
1750 | * $email->setAttachments('path/to/file'); |
||
1751 | * ``` |
||
1752 | * |
||
1753 | * Attach a file with a different filename: |
||
1754 | * |
||
1755 | * ``` |
||
1756 | * $email->setAttachments(['custom_name.txt' => 'path/to/file.txt']); |
||
1757 | * ``` |
||
1758 | * |
||
1759 | * Attach a file and specify additional properties: |
||
1760 | * |
||
1761 | * ``` |
||
1762 | * $email->setAttachments(['custom_name.png' => [ |
||
1763 | * 'file' => 'path/to/file', |
||
1764 | * 'mimetype' => 'image/png', |
||
1765 | * 'contentId' => 'abc123', |
||
1766 | * 'contentDisposition' => false |
||
1767 | * ] |
||
1768 | * ]); |
||
1769 | * ``` |
||
1770 | * |
||
1771 | * Attach a file from string and specify additional properties: |
||
1772 | * |
||
1773 | * ``` |
||
1774 | * $email->setAttachments(['custom_name.png' => [ |
||
1775 | * 'data' => file_get_contents('path/to/file'), |
||
1776 | * 'mimetype' => 'image/png' |
||
1777 | * ] |
||
1778 | * ]); |
||
1779 | * ``` |
||
1780 | * |
||
1781 | * The `contentId` key allows you to specify an inline attachment. In your email text, you |
||
1782 | * can use `<img src="cid:abc123" />` to display the image inline. |
||
1783 | * |
||
1784 | * The `contentDisposition` key allows you to disable the `Content-Disposition` header, this can improve |
||
1785 | * attachment compatibility with outlook email clients. |
||
1786 | * |
||
1787 | * @param string|array $attachments String with the filename or array with filenames |
||
1788 | * @return $this |
||
1789 | * @throws \InvalidArgumentException |
||
1790 | */ |
||
1791 | public function setAttachments($attachments) |
||
1792 | { |
||
1793 | $attach = []; |
||
1794 | foreach ((array)$attachments as $name => $fileInfo) { |
||
1795 | if (!is_array($fileInfo)) { |
||
1796 | $fileInfo = ['file' => $fileInfo]; |
||
1797 | } |
||
1798 | if (!isset($fileInfo['file'])) { |
||
1799 | if (!isset($fileInfo['data'])) { |
||
1800 | throw new InvalidArgumentException('No file or data specified.'); |
||
1801 | } |
||
1802 | if (is_int($name)) { |
||
1803 | throw new InvalidArgumentException('No filename specified.'); |
||
1804 | } |
||
1805 | $fileInfo['data'] = chunk_split(base64_encode($fileInfo['data']), 76, "\r\n"); |
||
1806 | } else { |
||
1807 | $fileName = $fileInfo['file']; |
||
1808 | $fileInfo['file'] = realpath($fileInfo['file']); |
||
1809 | if ($fileInfo['file'] === false || !file_exists($fileInfo['file'])) { |
||
1810 | throw new InvalidArgumentException(sprintf('File not found: "%s"', $fileName)); |
||
1811 | } |
||
1812 | if (is_int($name)) { |
||
1813 | $name = basename($fileInfo['file']); |
||
1814 | } |
||
1815 | } |
||
1816 | View Code Duplication | if (!isset($fileInfo['mimetype']) && isset($fileInfo['file']) && function_exists('mime_content_type')) { |
|
1817 | $fileInfo['mimetype'] = mime_content_type($fileInfo['file']); |
||
1818 | } |
||
1819 | if (!isset($fileInfo['mimetype'])) { |
||
1820 | $fileInfo['mimetype'] = 'application/octet-stream'; |
||
1821 | } |
||
1822 | $attach[$name] = $fileInfo; |
||
1823 | } |
||
1824 | $this->_attachments = $attach; |
||
1825 | |||
1826 | return $this; |
||
1827 | } |
||
1828 | |||
1829 | /** |
||
1830 | * Gets attachments to the email message. |
||
1831 | * |
||
1832 | * @return array Array of attachments. |
||
1833 | */ |
||
1834 | public function getAttachments() |
||
1835 | { |
||
1836 | return $this->_attachments; |
||
1837 | } |
||
1838 | |||
1839 | /** |
||
1840 | * Add attachments to the email message |
||
1841 | * |
||
1842 | * Attachments can be defined in a few forms depending on how much control you need: |
||
1843 | * |
||
1844 | * Attach a single file: |
||
1845 | * |
||
1846 | * ``` |
||
1847 | * $email->setAttachments('path/to/file'); |
||
1848 | * ``` |
||
1849 | * |
||
1850 | * Attach a file with a different filename: |
||
1851 | * |
||
1852 | * ``` |
||
1853 | * $email->setAttachments(['custom_name.txt' => 'path/to/file.txt']); |
||
1854 | * ``` |
||
1855 | * |
||
1856 | * Attach a file and specify additional properties: |
||
1857 | * |
||
1858 | * ``` |
||
1859 | * $email->setAttachments(['custom_name.png' => [ |
||
1860 | * 'file' => 'path/to/file', |
||
1861 | * 'mimetype' => 'image/png', |
||
1862 | * 'contentId' => 'abc123', |
||
1863 | * 'contentDisposition' => false |
||
1864 | * ] |
||
1865 | * ]); |
||
1866 | * ``` |
||
1867 | * |
||
1868 | * Attach a file from string and specify additional properties: |
||
1869 | * |
||
1870 | * ``` |
||
1871 | * $email->setAttachments(['custom_name.png' => [ |
||
1872 | * 'data' => file_get_contents('path/to/file'), |
||
1873 | * 'mimetype' => 'image/png' |
||
1874 | * ] |
||
1875 | * ]); |
||
1876 | * ``` |
||
1877 | * |
||
1878 | * The `contentId` key allows you to specify an inline attachment. In your email text, you |
||
1879 | * can use `<img src="cid:abc123" />` to display the image inline. |
||
1880 | * |
||
1881 | * The `contentDisposition` key allows you to disable the `Content-Disposition` header, this can improve |
||
1882 | * attachment compatibility with outlook email clients. |
||
1883 | * |
||
1884 | * @deprecated 3.4.0 Use setAttachments()/getAttachments() instead. |
||
1885 | * @param string|array|null $attachments String with the filename or array with filenames |
||
1886 | * @return array|$this Either the array of attachments when getting or $this when setting. |
||
1887 | * @throws \InvalidArgumentException |
||
1888 | */ |
||
1889 | public function attachments($attachments = null) |
||
1890 | { |
||
1891 | deprecationWarning('Email::attachments() is deprecated. Use Email::setAttachments() or Email::getAttachments() instead.'); |
||
1892 | |||
1893 | if ($attachments === null) { |
||
1894 | return $this->getAttachments(); |
||
1895 | } |
||
1896 | |||
1897 | return $this->setAttachments($attachments); |
||
1898 | } |
||
1899 | |||
1900 | /** |
||
1901 | * Add attachments |
||
1902 | * |
||
1903 | * @param string|array $attachments String with the filename or array with filenames |
||
1904 | * @return $this |
||
1905 | * @throws \InvalidArgumentException |
||
1906 | * @see \Cake\Mailer\Email::attachments() |
||
1907 | */ |
||
1908 | public function addAttachments($attachments) |
||
1909 | { |
||
1910 | $current = $this->_attachments; |
||
1911 | $this->setAttachments($attachments); |
||
1912 | $this->_attachments = array_merge($current, $this->_attachments); |
||
1913 | |||
1914 | return $this; |
||
1915 | } |
||
1916 | |||
1917 | /** |
||
1918 | * Get generated message (used by transport classes) |
||
1919 | * |
||
1920 | * @param string|null $type Use MESSAGE_* constants or null to return the full message as array |
||
1921 | * @return string|array String if type is given, array if type is null |
||
1922 | */ |
||
1923 | public function message($type = null) |
||
1924 | { |
||
1925 | switch ($type) { |
||
1926 | case static::MESSAGE_HTML: |
||
1927 | return $this->_htmlMessage; |
||
1928 | case static::MESSAGE_TEXT: |
||
1929 | return $this->_textMessage; |
||
1930 | } |
||
1931 | |||
1932 | return $this->_message; |
||
1933 | } |
||
1934 | |||
1935 | /** |
||
1936 | * Sets priority. |
||
1937 | * |
||
1938 | * @param int|null $priority 1 (highest) to 5 (lowest) |
||
1939 | * @return $this |
||
1940 | */ |
||
1941 | public function setPriority($priority) |
||
1942 | { |
||
1943 | $this->_priority = $priority; |
||
1944 | |||
1945 | return $this; |
||
1946 | } |
||
1947 | |||
1948 | /** |
||
1949 | * Gets priority. |
||
1950 | * |
||
1951 | * @return int |
||
1952 | */ |
||
1953 | public function getPriority() |
||
1954 | { |
||
1955 | return $this->_priority; |
||
1956 | } |
||
1957 | |||
1958 | /** |
||
1959 | * Sets transport configuration. |
||
1960 | * |
||
1961 | * Use this method to define transports to use in delivery profiles. |
||
1962 | * Once defined you cannot edit the configurations, and must use |
||
1963 | * Email::dropTransport() to flush the configuration first. |
||
1964 | * |
||
1965 | * When using an array of configuration data a new transport |
||
1966 | * will be constructed for each message sent. When using a Closure, the |
||
1967 | * closure will be evaluated for each message. |
||
1968 | * |
||
1969 | * The `className` is used to define the class to use for a transport. |
||
1970 | * It can either be a short name, or a fully qualified class name |
||
1971 | * |
||
1972 | * @param string|array $key The configuration name to write. Or |
||
1973 | * an array of multiple transports to set. |
||
1974 | * @param array|\Cake\Mailer\AbstractTransport|null $config Either an array of configuration |
||
1975 | * data, or a transport instance. Null when using key as array. |
||
1976 | * @return void |
||
1977 | * @deprecated 3.7.0 Use TransportFactory::setConfig() instead. |
||
1978 | */ |
||
1979 | public static function setConfigTransport($key, $config = null) |
||
1980 | { |
||
1981 | deprecationWarning('Email::setConfigTransport() is deprecated. Use TransportFactory::setConfig() instead.'); |
||
1982 | |||
1983 | TransportFactory::setConfig($key, $config); |
||
1984 | } |
||
1985 | |||
1986 | /** |
||
1987 | * Gets current transport configuration. |
||
1988 | * |
||
1989 | * @param string $key The configuration name to read. |
||
1990 | * @return array|null Transport config. |
||
1991 | * @deprecated 3.7.0 Use TransportFactory::getConfig() instead. |
||
1992 | */ |
||
1993 | public static function getConfigTransport($key) |
||
1994 | { |
||
1995 | deprecationWarning('Email::getConfigTransport() is deprecated. Use TransportFactory::getConfig() instead.'); |
||
1996 | |||
1997 | return TransportFactory::getConfig($key); |
||
1998 | } |
||
1999 | |||
2000 | /** |
||
2001 | * Add or read transport configuration. |
||
2002 | * |
||
2003 | * Use this method to define transports to use in delivery profiles. |
||
2004 | * Once defined you cannot edit the configurations, and must use |
||
2005 | * Email::dropTransport() to flush the configuration first. |
||
2006 | * |
||
2007 | * When using an array of configuration data a new transport |
||
2008 | * will be constructed for each message sent. When using a Closure, the |
||
2009 | * closure will be evaluated for each message. |
||
2010 | * |
||
2011 | * The `className` is used to define the class to use for a transport. |
||
2012 | * It can either be a short name, or a fully qualified classname |
||
2013 | * |
||
2014 | * @deprecated 3.4.0 Use TransportFactory::setConfig()/getConfig() instead. |
||
2015 | * @param string|array $key The configuration name to read/write. Or |
||
2016 | * an array of multiple transports to set. |
||
2017 | * @param array|\Cake\Mailer\AbstractTransport|null $config Either an array of configuration |
||
2018 | * data, or a transport instance. |
||
2019 | * @return array|null Either null when setting or an array of data when reading. |
||
2020 | * @throws \BadMethodCallException When modifying an existing configuration. |
||
2021 | */ |
||
2022 | public static function configTransport($key, $config = null) |
||
2023 | { |
||
2024 | deprecationWarning('Email::configTransport() is deprecated. Use TransportFactory::setConfig() or TransportFactory::getConfig() instead.'); |
||
2025 | |||
2026 | if ($config === null && is_string($key)) { |
||
2027 | return TransportFactory::getConfig($key); |
||
2028 | } |
||
2029 | if ($config === null && is_array($key)) { |
||
2030 | TransportFactory::setConfig($key); |
||
2031 | |||
2032 | return null; |
||
2033 | } |
||
2034 | |||
2035 | TransportFactory::setConfig($key, $config); |
||
2036 | } |
||
2037 | |||
2038 | /** |
||
2039 | * Returns an array containing the named transport configurations |
||
2040 | * |
||
2041 | * @return array Array of configurations. |
||
2042 | * @deprecated 3.7.0 Use TransportFactory::configured() instead. |
||
2043 | */ |
||
2044 | public static function configuredTransport() |
||
2045 | { |
||
2046 | deprecationWarning('Email::configuredTransport() is deprecated. Use TransportFactory::configured().'); |
||
2047 | |||
2048 | return TransportFactory::configured(); |
||
2049 | } |
||
2050 | |||
2051 | /** |
||
2052 | * Delete transport configuration. |
||
2053 | * |
||
2054 | * @param string $key The transport name to remove. |
||
2055 | * @return void |
||
2056 | * @deprecated 3.7.0 Use TransportFactory::drop() instead. |
||
2057 | */ |
||
2058 | public static function dropTransport($key) |
||
2059 | { |
||
2060 | deprecationWarning('Email::dropTransport() is deprecated. Use TransportFactory::drop().'); |
||
2061 | |||
2062 | TransportFactory::drop($key); |
||
2063 | } |
||
2064 | |||
2065 | /** |
||
2066 | * Sets the configuration profile to use for this instance. |
||
2067 | * |
||
2068 | * @param string|array $config String with configuration name, or |
||
2069 | * an array with config. |
||
2070 | * @return $this |
||
2071 | */ |
||
2072 | public function setProfile($config) |
||
2073 | { |
||
2074 | if (!is_array($config)) { |
||
2075 | $config = (string)$config; |
||
2076 | } |
||
2077 | $this->_applyConfig($config); |
||
2078 | |||
2079 | return $this; |
||
2080 | } |
||
2081 | |||
2082 | /** |
||
2083 | * Gets the configuration profile to use for this instance. |
||
2084 | * |
||
2085 | * @return string|array |
||
2086 | */ |
||
2087 | public function getProfile() |
||
2088 | { |
||
2089 | return $this->_profile; |
||
2090 | } |
||
2091 | |||
2092 | /** |
||
2093 | * Get/Set the configuration profile to use for this instance. |
||
2094 | * |
||
2095 | * @deprecated 3.4.0 Use setProfile()/getProfile() instead. |
||
2096 | * @param array|string|null $config String with configuration name, or |
||
2097 | * an array with config or null to return current config. |
||
2098 | * @return string|array|$this |
||
2099 | */ |
||
2100 | public function profile($config = null) |
||
2101 | { |
||
2102 | deprecationWarning('Email::profile() is deprecated. Use Email::setProfile() or Email::getProfile() instead.'); |
||
2103 | |||
2104 | if ($config === null) { |
||
2105 | return $this->getProfile(); |
||
2106 | } |
||
2107 | |||
2108 | return $this->setProfile($config); |
||
2109 | } |
||
2110 | |||
2111 | /** |
||
2112 | * Send an email using the specified content, template and layout |
||
2113 | * |
||
2114 | * @param string|array|null $content String with message or array with messages |
||
2115 | * @return array |
||
2116 | * @throws \BadMethodCallException |
||
2117 | */ |
||
2118 | public function send($content = null) |
||
2119 | { |
||
2120 | if (empty($this->_from)) { |
||
2121 | throw new BadMethodCallException('From is not specified.'); |
||
2122 | } |
||
2123 | if (empty($this->_to) && empty($this->_cc) && empty($this->_bcc)) { |
||
2124 | throw new BadMethodCallException('You need specify one destination on to, cc or bcc.'); |
||
2125 | } |
||
2126 | |||
2127 | if (is_array($content)) { |
||
2128 | $content = implode("\n", $content) . "\n"; |
||
2129 | } |
||
2130 | |||
2131 | $this->_message = $this->_render($this->_wrap($content)); |
||
2132 | |||
2133 | $transport = $this->getTransport(); |
||
2134 | if (!$transport) { |
||
2135 | $msg = 'Cannot send email, transport was not defined. Did you call transport() or define ' . |
||
2136 | ' a transport in the set profile?'; |
||
2137 | throw new BadMethodCallException($msg); |
||
2138 | } |
||
2139 | $contents = $transport->send($this); |
||
2140 | $this->_logDelivery($contents); |
||
2141 | |||
2142 | return $contents; |
||
2143 | } |
||
2144 | |||
2145 | /** |
||
2146 | * Log the email message delivery. |
||
2147 | * |
||
2148 | * @param array $contents The content with 'headers' and 'message' keys. |
||
2149 | * @return void |
||
2150 | */ |
||
2151 | protected function _logDelivery($contents) |
||
2152 | { |
||
2153 | if (empty($this->_profile['log'])) { |
||
2154 | return; |
||
2155 | } |
||
2156 | $config = [ |
||
2157 | 'level' => 'debug', |
||
2158 | 'scope' => 'email' |
||
2159 | ]; |
||
2160 | if ($this->_profile['log'] !== true) { |
||
2161 | if (!is_array($this->_profile['log'])) { |
||
2162 | $this->_profile['log'] = ['level' => $this->_profile['log']]; |
||
2163 | } |
||
2164 | $config = $this->_profile['log'] + $config; |
||
2165 | } |
||
2166 | Log::write( |
||
2167 | $config['level'], |
||
2168 | PHP_EOL . $this->flatten($contents['headers']) . PHP_EOL . PHP_EOL . $this->flatten($contents['message']), |
||
2169 | $config['scope'] |
||
2170 | ); |
||
2171 | } |
||
2172 | |||
2173 | /** |
||
2174 | * Converts given value to string |
||
2175 | * |
||
2176 | * @param string|array $value The value to convert |
||
2177 | * @return string |
||
2178 | */ |
||
2179 | protected function flatten($value) |
||
2180 | { |
||
2181 | return is_array($value) ? implode(';', $value) : (string)$value; |
||
2182 | } |
||
2183 | |||
2184 | /** |
||
2185 | * Static method to fast create an instance of \Cake\Mailer\Email |
||
2186 | * |
||
2187 | * @param string|array|null $to Address to send (see Cake\Mailer\Email::to()). If null, will try to use 'to' from transport config |
||
2188 | * @param string|null $subject String of subject or null to use 'subject' from transport config |
||
2189 | * @param string|array|null $message String with message or array with variables to be used in render |
||
2190 | * @param string|array $config String to use Email delivery profile from app.php or array with configs |
||
2191 | * @param bool $send Send the email or just return the instance pre-configured |
||
2192 | * @return static Instance of Cake\Mailer\Email |
||
2193 | * @throws \InvalidArgumentException |
||
2194 | */ |
||
2195 | public static function deliver($to = null, $subject = null, $message = null, $config = 'default', $send = true) |
||
2196 | { |
||
2197 | $class = __CLASS__; |
||
2198 | |||
2199 | if (is_array($config) && !isset($config['transport'])) { |
||
2200 | $config['transport'] = 'default'; |
||
2201 | } |
||
2202 | /* @var \Cake\Mailer\Email $instance */ |
||
2203 | $instance = new $class($config); |
||
2204 | if ($to !== null) { |
||
2205 | $instance->setTo($to); |
||
2206 | } |
||
2207 | if ($subject !== null) { |
||
2208 | $instance->setSubject($subject); |
||
2209 | } |
||
2210 | if (is_array($message)) { |
||
2211 | $instance->setViewVars($message); |
||
2212 | $message = null; |
||
2213 | } elseif ($message === null && array_key_exists('message', $config = $instance->getProfile())) { |
||
2214 | $message = $config['message']; |
||
2215 | } |
||
2216 | |||
2217 | if ($send === true) { |
||
2218 | $instance->send($message); |
||
2219 | } |
||
2220 | |||
2221 | return $instance; |
||
2222 | } |
||
2223 | |||
2224 | /** |
||
2225 | * Apply the config to an instance |
||
2226 | * |
||
2227 | * @param string|array $config Configuration options. |
||
2228 | * @return void |
||
2229 | * @throws \InvalidArgumentException When using a configuration that doesn't exist. |
||
2230 | */ |
||
2231 | protected function _applyConfig($config) |
||
2232 | { |
||
2233 | if (is_string($config)) { |
||
2234 | $name = $config; |
||
2235 | $config = static::getConfig($name); |
||
2236 | if (empty($config)) { |
||
2237 | throw new InvalidArgumentException(sprintf('Unknown email configuration "%s".', $name)); |
||
2238 | } |
||
2239 | unset($name); |
||
2240 | } |
||
2241 | |||
2242 | $this->_profile = array_merge($this->_profile, $config); |
||
2243 | |||
2244 | $simpleMethods = [ |
||
2245 | 'from', 'sender', 'to', 'replyTo', 'readReceipt', 'returnPath', |
||
2246 | 'cc', 'bcc', 'messageId', 'domain', 'subject', 'attachments', |
||
2247 | 'transport', 'emailFormat', 'emailPattern', 'charset', 'headerCharset' |
||
2248 | ]; |
||
2249 | foreach ($simpleMethods as $method) { |
||
2250 | if (isset($config[$method])) { |
||
2251 | $this->{'set' . ucfirst($method)}($config[$method]); |
||
2252 | } |
||
2253 | } |
||
2254 | |||
2255 | if (empty($this->headerCharset)) { |
||
2256 | $this->headerCharset = $this->charset; |
||
2257 | } |
||
2258 | if (isset($config['headers'])) { |
||
2259 | $this->setHeaders($config['headers']); |
||
2260 | } |
||
2261 | |||
2262 | $viewBuilderMethods = [ |
||
2263 | 'template', 'layout', 'theme' |
||
2264 | ]; |
||
2265 | foreach ($viewBuilderMethods as $method) { |
||
2266 | if (array_key_exists($method, $config)) { |
||
2267 | $this->viewBuilder()->{'set' . ucfirst($method)}($config[$method]); |
||
2268 | } |
||
2269 | } |
||
2270 | |||
2271 | if (array_key_exists('helpers', $config)) { |
||
2272 | $this->viewBuilder()->setHelpers($config['helpers'], false); |
||
2273 | } |
||
2274 | if (array_key_exists('viewRender', $config)) { |
||
2275 | $this->viewBuilder()->setClassName($config['viewRender']); |
||
2276 | } |
||
2277 | if (array_key_exists('viewVars', $config)) { |
||
2278 | $this->set($config['viewVars']); |
||
2279 | } |
||
2280 | } |
||
2281 | |||
2282 | /** |
||
2283 | * Reset all the internal variables to be able to send out a new email. |
||
2284 | * |
||
2285 | * @return $this |
||
2286 | */ |
||
2287 | public function reset() |
||
2288 | { |
||
2289 | $this->_to = []; |
||
2290 | $this->_from = []; |
||
2291 | $this->_sender = []; |
||
2292 | $this->_replyTo = []; |
||
2293 | $this->_readReceipt = []; |
||
2294 | $this->_returnPath = []; |
||
2295 | $this->_cc = []; |
||
2296 | $this->_bcc = []; |
||
2297 | $this->_messageId = true; |
||
2298 | $this->_subject = ''; |
||
2299 | $this->_headers = []; |
||
2300 | $this->_textMessage = ''; |
||
2301 | $this->_htmlMessage = ''; |
||
2302 | $this->_message = []; |
||
2303 | $this->_emailFormat = 'text'; |
||
2304 | $this->_transport = null; |
||
2305 | $this->_priority = null; |
||
2306 | $this->charset = 'utf-8'; |
||
2307 | $this->headerCharset = null; |
||
2308 | $this->transferEncoding = null; |
||
2309 | $this->_attachments = []; |
||
2310 | $this->_profile = []; |
||
2311 | $this->_emailPattern = self::EMAIL_PATTERN; |
||
2312 | |||
2313 | $this->viewBuilder()->setLayout('default'); |
||
2314 | $this->viewBuilder()->setTemplate(''); |
||
2315 | $this->viewBuilder()->setClassName('Cake\View\View'); |
||
2316 | $this->viewVars = []; |
||
2317 | $this->viewBuilder()->setTheme(false); |
||
2318 | $this->viewBuilder()->setHelpers(['Html'], false); |
||
2319 | |||
2320 | return $this; |
||
2321 | } |
||
2322 | |||
2323 | /** |
||
2324 | * Encode the specified string using the current charset |
||
2325 | * |
||
2326 | * @param string $text String to encode |
||
2327 | * @return string Encoded string |
||
2328 | */ |
||
2329 | protected function _encode($text) |
||
2330 | { |
||
2331 | $restore = mb_internal_encoding(); |
||
2332 | mb_internal_encoding($this->_appCharset); |
||
2333 | if (empty($this->headerCharset)) { |
||
2334 | $this->headerCharset = $this->charset; |
||
2335 | } |
||
2336 | $return = mb_encode_mimeheader($text, $this->headerCharset, 'B'); |
||
2337 | mb_internal_encoding($restore); |
||
2338 | |||
2339 | return $return; |
||
2340 | } |
||
2341 | |||
2342 | /** |
||
2343 | * Decode the specified string |
||
2344 | * |
||
2345 | * @param string $text String to decode |
||
2346 | * @return string Decoded string |
||
2347 | */ |
||
2348 | protected function _decode($text) |
||
2349 | { |
||
2350 | $restore = mb_internal_encoding(); |
||
2351 | mb_internal_encoding($this->_appCharset); |
||
2352 | $return = mb_decode_mimeheader($text); |
||
2353 | mb_internal_encoding($restore); |
||
2354 | |||
2355 | return $return; |
||
2356 | } |
||
2357 | |||
2358 | /** |
||
2359 | * Translates a string for one charset to another if the App.encoding value |
||
2360 | * differs and the mb_convert_encoding function exists |
||
2361 | * |
||
2362 | * @param string $text The text to be converted |
||
2363 | * @param string $charset the target encoding |
||
2364 | * @return string |
||
2365 | */ |
||
2366 | protected function _encodeString($text, $charset) |
||
2367 | { |
||
2368 | if ($this->_appCharset === $charset) { |
||
2369 | return $text; |
||
2370 | } |
||
2371 | |||
2372 | return mb_convert_encoding($text, $charset, $this->_appCharset); |
||
2373 | } |
||
2374 | |||
2375 | /** |
||
2376 | * Wrap the message to follow the RFC 2822 - 2.1.1 |
||
2377 | * |
||
2378 | * @param string $message Message to wrap |
||
2379 | * @param int $wrapLength The line length |
||
2380 | * @return array Wrapped message |
||
2381 | */ |
||
2382 | protected function _wrap($message, $wrapLength = Email::LINE_LENGTH_MUST) |
||
2383 | { |
||
2384 | if (strlen($message) === 0) { |
||
2385 | return ['']; |
||
2386 | } |
||
2387 | $message = str_replace(["\r\n", "\r"], "\n", $message); |
||
2388 | $lines = explode("\n", $message); |
||
2389 | $formatted = []; |
||
2390 | $cut = ($wrapLength == Email::LINE_LENGTH_MUST); |
||
2391 | |||
2392 | foreach ($lines as $line) { |
||
2393 | if (empty($line) && $line !== '0') { |
||
2394 | $formatted[] = ''; |
||
2395 | continue; |
||
2396 | } |
||
2397 | if (strlen($line) < $wrapLength) { |
||
2398 | $formatted[] = $line; |
||
2399 | continue; |
||
2400 | } |
||
2401 | if (!preg_match('/<[a-z]+.*>/i', $line)) { |
||
2402 | $formatted = array_merge( |
||
2403 | $formatted, |
||
2404 | explode("\n", Text::wordWrap($line, $wrapLength, "\n", $cut)) |
||
2405 | ); |
||
2406 | continue; |
||
2407 | } |
||
2408 | |||
2409 | $tagOpen = false; |
||
2410 | $tmpLine = $tag = ''; |
||
2411 | $tmpLineLength = 0; |
||
2412 | for ($i = 0, $count = strlen($line); $i < $count; $i++) { |
||
2413 | $char = $line[$i]; |
||
2414 | if ($tagOpen) { |
||
2415 | $tag .= $char; |
||
2416 | if ($char === '>') { |
||
2417 | $tagLength = strlen($tag); |
||
2418 | if ($tagLength + $tmpLineLength < $wrapLength) { |
||
2419 | $tmpLine .= $tag; |
||
2420 | $tmpLineLength += $tagLength; |
||
2421 | } else { |
||
2422 | if ($tmpLineLength > 0) { |
||
2423 | $formatted = array_merge( |
||
2424 | $formatted, |
||
2425 | explode("\n", Text::wordWrap(trim($tmpLine), $wrapLength, "\n", $cut)) |
||
2426 | ); |
||
2427 | $tmpLine = ''; |
||
2428 | $tmpLineLength = 0; |
||
2429 | } |
||
2430 | if ($tagLength > $wrapLength) { |
||
2431 | $formatted[] = $tag; |
||
2432 | } else { |
||
2433 | $tmpLine = $tag; |
||
2434 | $tmpLineLength = $tagLength; |
||
2435 | } |
||
2436 | } |
||
2437 | $tag = ''; |
||
2438 | $tagOpen = false; |
||
2439 | } |
||
2440 | continue; |
||
2441 | } |
||
2442 | if ($char === '<') { |
||
2443 | $tagOpen = true; |
||
2444 | $tag = '<'; |
||
2445 | continue; |
||
2446 | } |
||
2447 | if ($char === ' ' && $tmpLineLength >= $wrapLength) { |
||
2448 | $formatted[] = $tmpLine; |
||
2449 | $tmpLineLength = 0; |
||
2450 | continue; |
||
2451 | } |
||
2452 | $tmpLine .= $char; |
||
2453 | $tmpLineLength++; |
||
2454 | if ($tmpLineLength === $wrapLength) { |
||
2455 | $nextChar = $line[$i + 1]; |
||
2456 | if ($nextChar === ' ' || $nextChar === '<') { |
||
2457 | $formatted[] = trim($tmpLine); |
||
2458 | $tmpLine = ''; |
||
2459 | $tmpLineLength = 0; |
||
2460 | if ($nextChar === ' ') { |
||
2461 | $i++; |
||
2462 | } |
||
2463 | View Code Duplication | } else { |
|
2464 | $lastSpace = strrpos($tmpLine, ' '); |
||
2465 | if ($lastSpace === false) { |
||
2466 | continue; |
||
2467 | } |
||
2468 | $formatted[] = trim(substr($tmpLine, 0, $lastSpace)); |
||
2469 | $tmpLine = substr($tmpLine, $lastSpace + 1); |
||
2470 | |||
2471 | $tmpLineLength = strlen($tmpLine); |
||
2472 | } |
||
2473 | } |
||
2474 | } |
||
2475 | if (!empty($tmpLine)) { |
||
2476 | $formatted[] = $tmpLine; |
||
2477 | } |
||
2478 | } |
||
2479 | $formatted[] = ''; |
||
2480 | |||
2481 | return $formatted; |
||
2482 | } |
||
2483 | |||
2484 | /** |
||
2485 | * Create unique boundary identifier |
||
2486 | * |
||
2487 | * @return void |
||
2488 | */ |
||
2489 | protected function _createBoundary() |
||
2490 | { |
||
2491 | if ($this->_attachments || $this->_emailFormat === 'both') { |
||
2492 | $this->_boundary = md5(Security::randomBytes(16)); |
||
2493 | } |
||
2494 | } |
||
2495 | |||
2496 | /** |
||
2497 | * Attach non-embedded files by adding file contents inside boundaries. |
||
2498 | * |
||
2499 | * @param string|null $boundary Boundary to use. If null, will default to $this->_boundary |
||
2500 | * @return array An array of lines to add to the message |
||
2501 | */ |
||
2502 | protected function _attachFiles($boundary = null) |
||
2503 | { |
||
2504 | if ($boundary === null) { |
||
2505 | $boundary = $this->_boundary; |
||
2506 | } |
||
2507 | |||
2508 | $msg = []; |
||
2509 | foreach ($this->_attachments as $filename => $fileInfo) { |
||
2510 | if (!empty($fileInfo['contentId'])) { |
||
2511 | continue; |
||
2512 | } |
||
2513 | $data = isset($fileInfo['data']) ? $fileInfo['data'] : $this->_readFile($fileInfo['file']); |
||
2514 | $hasDisposition = ( |
||
2515 | !isset($fileInfo['contentDisposition']) || |
||
2516 | $fileInfo['contentDisposition'] |
||
2517 | ); |
||
2518 | $part = new FormDataPart(false, $data, false); |
||
2519 | |||
2520 | if ($hasDisposition) { |
||
2521 | $part->disposition('attachment'); |
||
2522 | $part->filename($filename); |
||
2523 | } |
||
2524 | $part->transferEncoding('base64'); |
||
2525 | $part->type($fileInfo['mimetype']); |
||
2526 | |||
2527 | $msg[] = '--' . $boundary; |
||
2528 | $msg[] = (string)$part; |
||
2529 | $msg[] = ''; |
||
2530 | } |
||
2531 | |||
2532 | return $msg; |
||
2533 | } |
||
2534 | |||
2535 | /** |
||
2536 | * Read the file contents and return a base64 version of the file contents. |
||
2537 | * |
||
2538 | * @param string $path The absolute path to the file to read. |
||
2539 | * @return string File contents in base64 encoding |
||
2540 | */ |
||
2541 | protected function _readFile($path) |
||
2542 | { |
||
2543 | $File = new File($path); |
||
2544 | |||
2545 | return chunk_split(base64_encode($File->read())); |
||
2546 | } |
||
2547 | |||
2548 | /** |
||
2549 | * Attach inline/embedded files to the message. |
||
2550 | * |
||
2551 | * @param string|null $boundary Boundary to use. If null, will default to $this->_boundary |
||
2552 | * @return array An array of lines to add to the message |
||
2553 | */ |
||
2554 | protected function _attachInlineFiles($boundary = null) |
||
2555 | { |
||
2556 | if ($boundary === null) { |
||
2557 | $boundary = $this->_boundary; |
||
2558 | } |
||
2559 | |||
2560 | $msg = []; |
||
2561 | foreach ($this->_attachments as $filename => $fileInfo) { |
||
2562 | if (empty($fileInfo['contentId'])) { |
||
2563 | continue; |
||
2564 | } |
||
2565 | $data = isset($fileInfo['data']) ? $fileInfo['data'] : $this->_readFile($fileInfo['file']); |
||
2566 | |||
2567 | $msg[] = '--' . $boundary; |
||
2568 | $part = new FormDataPart(false, $data, 'inline'); |
||
2569 | $part->type($fileInfo['mimetype']); |
||
2570 | $part->transferEncoding('base64'); |
||
2571 | $part->contentId($fileInfo['contentId']); |
||
2572 | $part->filename($filename); |
||
2573 | $msg[] = (string)$part; |
||
2574 | $msg[] = ''; |
||
2575 | } |
||
2576 | |||
2577 | return $msg; |
||
2578 | } |
||
2579 | |||
2580 | /** |
||
2581 | * Render the body of the email. |
||
2582 | * |
||
2583 | * @param array $content Content to render |
||
2584 | * @return array Email body ready to be sent |
||
2585 | */ |
||
2586 | protected function _render($content) |
||
2587 | { |
||
2588 | $this->_textMessage = $this->_htmlMessage = ''; |
||
2589 | |||
2590 | $content = implode("\n", $content); |
||
2591 | $rendered = $this->_renderTemplates($content); |
||
2592 | |||
2593 | $this->_createBoundary(); |
||
2594 | $msg = []; |
||
2595 | |||
2596 | $contentIds = array_filter((array)Hash::extract($this->_attachments, '{s}.contentId')); |
||
2597 | $hasInlineAttachments = count($contentIds) > 0; |
||
2598 | $hasAttachments = !empty($this->_attachments); |
||
2599 | $hasMultipleTypes = count($rendered) > 1; |
||
2600 | $multiPart = ($hasAttachments || $hasMultipleTypes); |
||
2601 | |||
2602 | $boundary = $relBoundary = $textBoundary = $this->_boundary; |
||
2603 | |||
2604 | View Code Duplication | if ($hasInlineAttachments) { |
|
2605 | $msg[] = '--' . $boundary; |
||
2606 | $msg[] = 'Content-Type: multipart/related; boundary="rel-' . $boundary . '"'; |
||
2607 | $msg[] = ''; |
||
2608 | $relBoundary = $textBoundary = 'rel-' . $boundary; |
||
2609 | } |
||
2610 | |||
2611 | View Code Duplication | if ($hasMultipleTypes && $hasAttachments) { |
|
2612 | $msg[] = '--' . $relBoundary; |
||
2613 | $msg[] = 'Content-Type: multipart/alternative; boundary="alt-' . $boundary . '"'; |
||
2614 | $msg[] = ''; |
||
2615 | $textBoundary = 'alt-' . $boundary; |
||
2616 | } |
||
2617 | |||
2618 | View Code Duplication | if (isset($rendered['text'])) { |
|
2619 | if ($multiPart) { |
||
2620 | $msg[] = '--' . $textBoundary; |
||
2621 | $msg[] = 'Content-Type: text/plain; charset=' . $this->_getContentTypeCharset(); |
||
2622 | $msg[] = 'Content-Transfer-Encoding: ' . $this->_getContentTransferEncoding(); |
||
2623 | $msg[] = ''; |
||
2624 | } |
||
2625 | $this->_textMessage = $rendered['text']; |
||
2626 | $content = explode("\n", $this->_textMessage); |
||
2627 | $msg = array_merge($msg, $content); |
||
2628 | $msg[] = ''; |
||
2629 | } |
||
2630 | |||
2631 | View Code Duplication | if (isset($rendered['html'])) { |
|
2632 | if ($multiPart) { |
||
2633 | $msg[] = '--' . $textBoundary; |
||
2634 | $msg[] = 'Content-Type: text/html; charset=' . $this->_getContentTypeCharset(); |
||
2635 | $msg[] = 'Content-Transfer-Encoding: ' . $this->_getContentTransferEncoding(); |
||
2636 | $msg[] = ''; |
||
2637 | } |
||
2638 | $this->_htmlMessage = $rendered['html']; |
||
2639 | $content = explode("\n", $this->_htmlMessage); |
||
2640 | $msg = array_merge($msg, $content); |
||
2641 | $msg[] = ''; |
||
2642 | } |
||
2643 | |||
2644 | if ($textBoundary !== $relBoundary) { |
||
2645 | $msg[] = '--' . $textBoundary . '--'; |
||
2646 | $msg[] = ''; |
||
2647 | } |
||
2648 | |||
2649 | if ($hasInlineAttachments) { |
||
2650 | $attachments = $this->_attachInlineFiles($relBoundary); |
||
2651 | $msg = array_merge($msg, $attachments); |
||
2652 | $msg[] = ''; |
||
2653 | $msg[] = '--' . $relBoundary . '--'; |
||
2654 | $msg[] = ''; |
||
2655 | } |
||
2656 | |||
2657 | if ($hasAttachments) { |
||
2658 | $attachments = $this->_attachFiles($boundary); |
||
2659 | $msg = array_merge($msg, $attachments); |
||
2660 | } |
||
2661 | if ($hasAttachments || $hasMultipleTypes) { |
||
2662 | $msg[] = ''; |
||
2663 | $msg[] = '--' . $boundary . '--'; |
||
2664 | $msg[] = ''; |
||
2665 | } |
||
2666 | |||
2667 | return $msg; |
||
2668 | } |
||
2669 | |||
2670 | /** |
||
2671 | * Gets the text body types that are in this email message |
||
2672 | * |
||
2673 | * @return array Array of types. Valid types are 'text' and 'html' |
||
2674 | */ |
||
2675 | protected function _getTypes() |
||
2676 | { |
||
2677 | $types = [$this->_emailFormat]; |
||
2678 | if ($this->_emailFormat === 'both') { |
||
2679 | $types = ['html', 'text']; |
||
2680 | } |
||
2681 | |||
2682 | return $types; |
||
2683 | } |
||
2684 | |||
2685 | /** |
||
2686 | * Build and set all the view properties needed to render the templated emails. |
||
2687 | * If there is no template set, the $content will be returned in a hash |
||
2688 | * of the text content types for the email. |
||
2689 | * |
||
2690 | * @param string $content The content passed in from send() in most cases. |
||
2691 | * @return array The rendered content with html and text keys. |
||
2692 | */ |
||
2693 | protected function _renderTemplates($content) |
||
2694 | { |
||
2695 | $types = $this->_getTypes(); |
||
2696 | $rendered = []; |
||
2697 | $template = $this->viewBuilder()->getTemplate(); |
||
2698 | if (empty($template)) { |
||
2699 | foreach ($types as $type) { |
||
2700 | $rendered[$type] = $this->_encodeString($content, $this->charset); |
||
2701 | } |
||
2702 | |||
2703 | return $rendered; |
||
2704 | } |
||
2705 | |||
2706 | $View = $this->createView(); |
||
2707 | |||
2708 | list($templatePlugin) = pluginSplit($View->getTemplate()); |
||
2709 | list($layoutPlugin) = pluginSplit($View->getLayout()); |
||
2710 | if ($templatePlugin) { |
||
2711 | $View->setPlugin($templatePlugin); |
||
2712 | } elseif ($layoutPlugin) { |
||
2713 | $View->setPlugin($layoutPlugin); |
||
2714 | } |
||
2715 | |||
2716 | if ($View->get('content') === null) { |
||
2717 | $View->set('content', $content); |
||
2718 | } |
||
2719 | |||
2720 | foreach ($types as $type) { |
||
2721 | $View->hasRendered = false; |
||
2722 | $View->setTemplatePath('Email' . DIRECTORY_SEPARATOR . $type); |
||
2723 | $View->setLayoutPath('Email' . DIRECTORY_SEPARATOR . $type); |
||
2724 | |||
2725 | $render = $View->render(); |
||
2726 | $render = str_replace(["\r\n", "\r"], "\n", $render); |
||
2727 | $rendered[$type] = $this->_encodeString($render, $this->charset); |
||
2728 | } |
||
2729 | |||
2730 | foreach ($rendered as $type => $content) { |
||
2731 | $rendered[$type] = $this->_wrap($content); |
||
2732 | $rendered[$type] = implode("\n", $rendered[$type]); |
||
2733 | $rendered[$type] = rtrim($rendered[$type], "\n"); |
||
2734 | } |
||
2735 | |||
2736 | return $rendered; |
||
2737 | } |
||
2738 | |||
2739 | /** |
||
2740 | * Return the Content-Transfer Encoding value based |
||
2741 | * on the set transferEncoding or set charset. |
||
2742 | * |
||
2743 | * @return string |
||
2744 | */ |
||
2745 | protected function _getContentTransferEncoding() |
||
2746 | { |
||
2747 | if ($this->transferEncoding) { |
||
2748 | return $this->transferEncoding; |
||
2749 | } |
||
2750 | |||
2751 | $charset = strtoupper($this->charset); |
||
2752 | if (in_array($charset, $this->_charset8bit)) { |
||
2753 | return '8bit'; |
||
2754 | } |
||
2755 | |||
2756 | return '7bit'; |
||
2757 | } |
||
2758 | |||
2759 | /** |
||
2760 | * Return charset value for Content-Type. |
||
2761 | * |
||
2762 | * Checks fallback/compatibility types which include workarounds |
||
2763 | * for legacy japanese character sets. |
||
2764 | * |
||
2765 | * @return string |
||
2766 | */ |
||
2767 | protected function _getContentTypeCharset() |
||
2768 | { |
||
2769 | $charset = strtoupper($this->charset); |
||
2770 | if (array_key_exists($charset, $this->_contentTypeCharset)) { |
||
2771 | return strtoupper($this->_contentTypeCharset[$charset]); |
||
2772 | } |
||
2773 | |||
2774 | return strtoupper($this->charset); |
||
2775 | } |
||
2776 | |||
2777 | /** |
||
2778 | * Serializes the email object to a value that can be natively serialized and re-used |
||
2779 | * to clone this email instance. |
||
2780 | * |
||
2781 | * It has certain limitations for viewVars that are good to know: |
||
2782 | * |
||
2783 | * - ORM\Query executed and stored as resultset |
||
2784 | * - SimpleXMLElements stored as associative array |
||
2785 | * - Exceptions stored as strings |
||
2786 | * - Resources, \Closure and \PDO are not supported. |
||
2787 | * |
||
2788 | * @return array Serializable array of configuration properties. |
||
2789 | * @throws \Exception When a view var object can not be properly serialized. |
||
2790 | */ |
||
2791 | public function jsonSerialize() |
||
2792 | { |
||
2793 | $properties = [ |
||
2794 | '_to', '_from', '_sender', '_replyTo', '_cc', '_bcc', '_subject', |
||
2795 | '_returnPath', '_readReceipt', '_emailFormat', '_emailPattern', '_domain', |
||
2796 | '_attachments', '_messageId', '_headers', '_appCharset', 'viewVars', 'charset', 'headerCharset' |
||
2797 | ]; |
||
2798 | |||
2799 | $array = ['viewConfig' => $this->viewBuilder()->jsonSerialize()]; |
||
2800 | |||
2801 | foreach ($properties as $property) { |
||
2802 | $array[$property] = $this->{$property}; |
||
2803 | } |
||
2804 | |||
2805 | array_walk($array['_attachments'], function (&$item, $key) { |
||
2806 | if (!empty($item['file'])) { |
||
2807 | $item['data'] = $this->_readFile($item['file']); |
||
2808 | unset($item['file']); |
||
2809 | } |
||
2810 | }); |
||
2811 | |||
2812 | array_walk_recursive($array['viewVars'], [$this, '_checkViewVars']); |
||
2813 | |||
2814 | return array_filter($array, function ($i) { |
||
2815 | return !is_array($i) && strlen($i) || !empty($i); |
||
2816 | }); |
||
2817 | } |
||
2818 | |||
2819 | /** |
||
2820 | * Iterates through hash to clean up and normalize. |
||
2821 | * |
||
2822 | * @param mixed $item Reference to the view var value. |
||
2823 | * @param string $key View var key. |
||
2824 | * @return void |
||
2825 | */ |
||
2826 | protected function _checkViewVars(&$item, $key) |
||
2827 | { |
||
2828 | if ($item instanceof Exception) { |
||
2829 | $item = (string)$item; |
||
2830 | } |
||
2831 | |||
2832 | if (is_resource($item) || |
||
2833 | $item instanceof Closure || |
||
2834 | $item instanceof PDO |
||
2835 | ) { |
||
2836 | throw new RuntimeException(sprintf( |
||
2837 | 'Failed serializing the `%s` %s in the `%s` view var', |
||
2838 | is_resource($item) ? get_resource_type($item) : get_class($item), |
||
2839 | is_resource($item) ? 'resource' : 'object', |
||
2840 | $key |
||
2841 | )); |
||
2842 | } |
||
2843 | } |
||
2844 | |||
2845 | /** |
||
2846 | * Configures an email instance object from serialized config. |
||
2847 | * |
||
2848 | * @param array $config Email configuration array. |
||
2849 | * @return $this Configured email instance. |
||
2850 | */ |
||
2851 | public function createFromArray($config) |
||
2852 | { |
||
2853 | if (isset($config['viewConfig'])) { |
||
2854 | $this->viewBuilder()->createFromArray($config['viewConfig']); |
||
2855 | unset($config['viewConfig']); |
||
2856 | } |
||
2857 | |||
2858 | foreach ($config as $property => $value) { |
||
2859 | $this->{$property} = $value; |
||
2860 | } |
||
2861 | |||
2862 | return $this; |
||
2863 | } |
||
2864 | |||
2865 | /** |
||
2866 | * Serializes the Email object. |
||
2867 | * |
||
2868 | * @return string |
||
2869 | */ |
||
2870 | public function serialize() |
||
2871 | { |
||
2872 | $array = $this->jsonSerialize(); |
||
2873 | array_walk_recursive($array, function (&$item, $key) { |
||
2874 | if ($item instanceof SimpleXMLElement) { |
||
2875 | $item = json_decode(json_encode((array)$item), true); |
||
2876 | } |
||
2877 | }); |
||
2878 | |||
2879 | return serialize($array); |
||
2880 | } |
||
2881 | |||
2882 | /** |
||
2883 | * Unserializes the Email object. |
||
2884 | * |
||
2885 | * @param string $data Serialized string. |
||
2886 | * @return static Configured email instance. |
||
2887 | */ |
||
2888 | public function unserialize($data) |
||
2889 | { |
||
2890 | return $this->createFromArray(unserialize($data)); |
||
2891 | } |
||
2892 | } |
||
2893 |