[ Index ] |
PHP Cross Reference of Joomla 4.2.2 documentation |
[Summary view] [Print] [Text view]
1 <?php 2 3 /** 4 * Joomla! Content Management System 5 * 6 * @copyright (C) 2006 Open Source Matters, Inc. <https://www.joomla.org> 7 * @license GNU General Public License version 2 or later; see LICENSE.txt 8 */ 9 10 namespace Joomla\CMS\Mail; 11 12 use Joomla\CMS\Factory; 13 use Joomla\CMS\Language\Text; 14 use Joomla\CMS\Log\Log; 15 use Joomla\CMS\Mail\Exception\MailDisabledException; 16 use PHPMailer\PHPMailer\Exception as phpmailerException; 17 use PHPMailer\PHPMailer\PHPMailer; 18 19 // phpcs:disable PSR1.Files.SideEffects 20 \defined('JPATH_PLATFORM') or die; 21 // phpcs:enable PSR1.Files.SideEffects 22 23 /** 24 * Email Class. Provides a common interface to send email from the Joomla! Platform 25 * 26 * @since 1.7.0 27 */ 28 class Mail extends PHPMailer 29 { 30 /** 31 * Mail instances container. 32 * 33 * @var Mail[] 34 * @since 1.7.3 35 */ 36 protected static $instances = array(); 37 38 /** 39 * Charset of the message. 40 * 41 * @var string 42 * @since 1.7.0 43 */ 44 public $CharSet = 'utf-8'; 45 46 /** 47 * Constructor 48 * 49 * @param boolean $exceptions Flag if Exceptions should be thrown 50 * 51 * @since 1.7.0 52 */ 53 public function __construct($exceptions = true) 54 { 55 parent::__construct($exceptions); 56 57 // PHPMailer has an issue using the relative path for its language files 58 $this->setLanguage('en_gb', __DIR__ . '/language/'); 59 60 // Configure a callback function to handle errors when $this->debug() is called 61 $this->Debugoutput = function ($message, $level) { 62 Log::add(sprintf('Error in Mail API: %s', $message), Log::ERROR, 'mail'); 63 }; 64 65 // If debug mode is enabled then set SMTPDebug to the maximum level 66 if (\defined('JDEBUG') && JDEBUG) { 67 $this->SMTPDebug = 4; 68 } 69 70 // Don't disclose the PHPMailer version 71 $this->XMailer = ' '; 72 73 /** 74 * Which validator to use by default when validating email addresses. 75 * Validation patterns supported: 76 * `auto` Pick best pattern automatically; 77 * `pcre8` Use the squiloople.com pattern, requires PCRE > 8.0; 78 * `pcre` Use old PCRE implementation; 79 * `php` Use PHP built-in FILTER_VALIDATE_EMAIL; 80 * `html5` Use the pattern given by the HTML5 spec for 'email' type form input elements. 81 * `noregex` Don't use a regex: super fast, really dumb. 82 * 83 * The default used by phpmailer is `php` but this does not support dotless domains so instead we use `html5` 84 * 85 * @see PHPMailer::validateAddress() 86 * 87 * @var string|callable 88 */ 89 PHPMailer::$validator = 'html5'; 90 } 91 92 /** 93 * Returns the global email object, only creating it if it doesn't already exist. 94 * 95 * NOTE: If you need an instance to use that does not have the global configuration 96 * values, use an id string that is not 'Joomla'. 97 * 98 * @param string $id The id string for the Mail instance [optional] 99 * @param boolean $exceptions Flag if Exceptions should be thrown [optional] 100 * 101 * @return Mail The global Mail object 102 * 103 * @since 1.7.0 104 */ 105 public static function getInstance($id = 'Joomla', $exceptions = true) 106 { 107 if (empty(static::$instances[$id])) { 108 static::$instances[$id] = new static($exceptions); 109 } 110 111 return static::$instances[$id]; 112 } 113 114 /** 115 * Send the mail 116 * 117 * @return boolean Boolean true if successful, false if exception throwing is disabled. 118 * 119 * @since 1.7.0 120 * 121 * @throws MailDisabledException if the mail function is disabled 122 * @throws phpmailerException if sending failed 123 */ 124 public function Send() 125 { 126 if (!Factory::getApplication()->get('mailonline', 1)) { 127 throw new MailDisabledException( 128 MailDisabledException::REASON_USER_DISABLED, 129 Text::_('JLIB_MAIL_FUNCTION_OFFLINE'), 130 500 131 ); 132 } 133 134 if ($this->Mailer === 'mail' && !\function_exists('mail')) { 135 throw new MailDisabledException( 136 MailDisabledException::REASON_MAIL_FUNCTION_NOT_AVAILABLE, 137 Text::_('JLIB_MAIL_FUNCTION_DISABLED'), 138 500 139 ); 140 } 141 142 try { 143 $result = parent::send(); 144 } catch (phpmailerException $e) { 145 // If auto TLS is disabled just let this bubble up 146 if (!$this->SMTPAutoTLS) { 147 throw $e; 148 } 149 150 $result = false; 151 } 152 153 /* 154 * If sending failed and auto TLS is enabled, retry sending with the feature disabled 155 * 156 * See https://github.com/PHPMailer/PHPMailer/wiki/Troubleshooting#opportunistic-tls for more info 157 */ 158 if (!$result && $this->SMTPAutoTLS) { 159 $this->SMTPAutoTLS = false; 160 161 try { 162 $result = parent::send(); 163 } finally { 164 // Reset the value for any future emails 165 $this->SMTPAutoTLS = true; 166 } 167 } 168 169 return $result; 170 } 171 172 /** 173 * Set the email sender 174 * 175 * @param mixed $from email address and Name of sender 176 * <code>array([0] => email Address, [1] => Name)</code> 177 * or as a string 178 * 179 * @return Mail|boolean Returns this object for chaining on success or boolean false on failure. 180 * 181 * @since 1.7.0 182 * 183 * @throws \UnexpectedValueException if the sender is not a valid address 184 * @throws phpmailerException if setting the sender failed and exception throwing is enabled 185 */ 186 public function setSender($from) 187 { 188 if (\is_array($from)) { 189 // If $from is an array we assume it has an address and a name 190 if (isset($from[2])) { 191 // If it is an array with entries, use them 192 $result = $this->setFrom(MailHelper::cleanLine($from[0]), MailHelper::cleanLine($from[1]), (bool) $from[2]); 193 } else { 194 $result = $this->setFrom(MailHelper::cleanLine($from[0]), MailHelper::cleanLine($from[1])); 195 } 196 } elseif (\is_string($from)) { 197 // If it is a string we assume it is just the address 198 $result = $this->setFrom(MailHelper::cleanLine($from)); 199 } else { 200 // If it is neither, we log a message and throw an exception 201 Log::add(Text::sprintf('JLIB_MAIL_INVALID_EMAIL_SENDER', $from), Log::WARNING, 'jerror'); 202 203 throw new \UnexpectedValueException(sprintf('Invalid email sender: %s', $from)); 204 } 205 206 if ($result === false) { 207 return false; 208 } 209 210 return $this; 211 } 212 213 /** 214 * Set the email subject 215 * 216 * @param string $subject Subject of the email 217 * 218 * @return Mail Returns this object for chaining. 219 * 220 * @since 1.7.0 221 */ 222 public function setSubject($subject) 223 { 224 $this->Subject = MailHelper::cleanLine($subject); 225 226 return $this; 227 } 228 229 /** 230 * Set the email body 231 * 232 * @param string $content Body of the email 233 * 234 * @return Mail Returns this object for chaining. 235 * 236 * @since 1.7.0 237 */ 238 public function setBody($content) 239 { 240 /* 241 * Filter the Body 242 * @todo: Check for XSS 243 */ 244 $this->Body = MailHelper::cleanText($content); 245 246 return $this; 247 } 248 249 /** 250 * Add recipients to the email. 251 * 252 * @param mixed $recipient Either a string or array of strings [email address(es)] 253 * @param mixed $name Either a string or array of strings [name(s)] 254 * @param string $method The parent method's name. 255 * 256 * @return Mail|boolean Returns this object for chaining on success or boolean false on failure. 257 * 258 * @since 1.7.0 259 * 260 * @throws \InvalidArgumentException if the argument array counts do not match 261 * @throws phpmailerException if setting the address failed and exception throwing is enabled 262 */ 263 protected function add($recipient, $name = '', $method = 'addAddress') 264 { 265 $method = lcfirst($method); 266 267 // If the recipient is an array, add each recipient... otherwise just add the one 268 if (\is_array($recipient)) { 269 if (\is_array($name)) { 270 $combined = array_combine($recipient, $name); 271 272 if ($combined === false) { 273 throw new \InvalidArgumentException("The number of elements for each array isn't equal."); 274 } 275 276 foreach ($combined as $recipientEmail => $recipientName) { 277 $recipientEmail = MailHelper::cleanLine($recipientEmail); 278 $recipientName = MailHelper::cleanLine($recipientName); 279 280 // Check for boolean false return if exception handling is disabled 281 if (\call_user_func('parent::' . $method, $recipientEmail, $recipientName) === false) { 282 return false; 283 } 284 } 285 } else { 286 $name = MailHelper::cleanLine($name); 287 288 foreach ($recipient as $to) { 289 $to = MailHelper::cleanLine($to); 290 291 // Check for boolean false return if exception handling is disabled 292 if (\call_user_func('parent::' . $method, $to, $name) === false) { 293 return false; 294 } 295 } 296 } 297 } else { 298 $recipient = MailHelper::cleanLine($recipient); 299 300 // Check for boolean false return if exception handling is disabled 301 if (\call_user_func('parent::' . $method, $recipient, $name) === false) { 302 return false; 303 } 304 } 305 306 return $this; 307 } 308 309 /** 310 * Add recipients to the email 311 * 312 * @param mixed $recipient Either a string or array of strings [email address(es)] 313 * @param mixed $name Either a string or array of strings [name(s)] 314 * 315 * @return Mail|boolean Returns this object for chaining on success or false on failure when exception throwing is disabled. 316 * 317 * @since 1.7.0 318 * 319 * @throws phpmailerException if exception throwing is enabled 320 */ 321 public function addRecipient($recipient, $name = '') 322 { 323 return $this->add($recipient, $name, 'addAddress'); 324 } 325 326 /** 327 * Add carbon copy recipients to the email 328 * 329 * @param mixed $cc Either a string or array of strings [email address(es)] 330 * @param mixed $name Either a string or array of strings [name(s)] 331 * 332 * @return Mail|boolean Returns this object for chaining on success or boolean false on failure when exception throwing is enabled. 333 * 334 * @since 1.7.0 335 * 336 * @throws phpmailerException if exception throwing is enabled 337 */ 338 public function addCc($cc, $name = '') 339 { 340 // If the carbon copy recipient is an array, add each recipient... otherwise just add the one 341 if (isset($cc)) { 342 return $this->add($cc, $name, 'addCC'); 343 } 344 345 return $this; 346 } 347 348 /** 349 * Add blind carbon copy recipients to the email 350 * 351 * @param mixed $bcc Either a string or array of strings [email address(es)] 352 * @param mixed $name Either a string or array of strings [name(s)] 353 * 354 * @return Mail|boolean Returns this object for chaining on success or boolean false on failure when exception throwing is disabled. 355 * 356 * @since 1.7.0 357 * 358 * @throws phpmailerException if exception throwing is enabled 359 */ 360 public function addBcc($bcc, $name = '') 361 { 362 // If the blind carbon copy recipient is an array, add each recipient... otherwise just add the one 363 if (isset($bcc)) { 364 return $this->add($bcc, $name, 'addBCC'); 365 } 366 367 return $this; 368 } 369 370 /** 371 * Add file attachment to the email 372 * 373 * @param mixed $path Either a string or array of strings [filenames] 374 * @param mixed $name Either a string or array of strings [names]. N.B. if this is an array it must contain the same 375 * number of elements as the array of paths supplied. 376 * @param mixed $encoding The encoding of the attachment 377 * @param mixed $type The mime type 378 * @param string $disposition The disposition of the attachment 379 * 380 * @return Mail|boolean Returns this object for chaining on success or boolean false on failure when exception throwing is disabled. 381 * 382 * @since 3.0.1 383 * @throws \InvalidArgumentException if the argument array counts do not match 384 * @throws phpmailerException if setting the attachment failed and exception throwing is enabled 385 */ 386 public function addAttachment($path, $name = '', $encoding = 'base64', $type = 'application/octet-stream', $disposition = 'attachment') 387 { 388 // If the file attachments is an array, add each file... otherwise just add the one 389 if (isset($path)) { 390 $result = true; 391 392 if (\is_array($path)) { 393 if (!empty($name) && \count($path) != \count($name)) { 394 throw new \InvalidArgumentException('The number of attachments must be equal with the number of name'); 395 } 396 397 foreach ($path as $key => $file) { 398 if (!empty($name)) { 399 $result = parent::addAttachment($file, $name[$key], $encoding, $type); 400 } else { 401 if (!empty($name)) { 402 $result = parent::addAttachment($file, $name[$key], $encoding, $type, $disposition); 403 } else { 404 $result = parent::addAttachment($file, $name, $encoding, $type, $disposition); 405 } 406 } 407 } 408 409 // Check for boolean false return if exception handling is disabled 410 if ($result === false) { 411 return false; 412 } 413 } else { 414 $result = parent::addAttachment($path, $name, $encoding, $type); 415 } 416 417 // Check for boolean false return if exception handling is disabled 418 if ($result === false) { 419 return false; 420 } 421 } 422 423 return $this; 424 } 425 426 /** 427 * Unset all file attachments from the email 428 * 429 * @return Mail Returns this object for chaining. 430 * 431 * @since 3.0.1 432 */ 433 public function clearAttachments() 434 { 435 parent::clearAttachments(); 436 437 return $this; 438 } 439 440 /** 441 * Unset file attachments specified by array index. 442 * 443 * @param integer $index The numerical index of the attachment to remove 444 * 445 * @return Mail Returns this object for chaining. 446 * 447 * @since 3.0.1 448 */ 449 public function removeAttachment($index = 0) 450 { 451 if (isset($this->attachment[$index])) { 452 unset($this->attachment[$index]); 453 } 454 455 return $this; 456 } 457 458 /** 459 * Add Reply to email address(es) to the email 460 * 461 * @param mixed $replyto Either a string or array of strings [email address(es)] 462 * @param mixed $name Either a string or array of strings [name(s)] 463 * 464 * @return Mail|boolean Returns this object for chaining on success or boolean false on failure when exception throwing is disabled. 465 * 466 * @since 1.7.0 467 * 468 * @throws phpmailerException if exception throwing is enabled 469 */ 470 public function addReplyTo($replyto, $name = '') 471 { 472 return $this->add($replyto, $name, 'addReplyTo'); 473 } 474 475 /** 476 * Sets message type to HTML 477 * 478 * @param boolean $ishtml Boolean true or false. 479 * 480 * @return Mail Returns this object for chaining. 481 * 482 * @since 3.1.4 483 */ 484 public function isHtml($ishtml = true) 485 { 486 parent::isHTML($ishtml); 487 488 return $this; 489 } 490 491 /** 492 * Send messages using $Sendmail. 493 * 494 * This overrides the parent class to remove the restriction on the executable's name containing the word "sendmail" 495 * 496 * @return void 497 * 498 * @since 1.7.0 499 */ 500 public function isSendmail() 501 { 502 // Prefer the Joomla configured sendmail path and default to the configured PHP path otherwise 503 $sendmail = Factory::getApplication()->get('sendmail', ini_get('sendmail_path')); 504 505 // And if we still don't have a path, then use the system default for Linux 506 if (empty($sendmail)) { 507 $sendmail = '/usr/sbin/sendmail'; 508 } 509 510 $this->Sendmail = $sendmail; 511 $this->Mailer = 'sendmail'; 512 } 513 514 /** 515 * Use sendmail for sending the email 516 * 517 * @param string $sendmail Path to sendmail [optional] 518 * 519 * @return boolean True on success 520 * 521 * @since 1.7.0 522 */ 523 public function useSendmail($sendmail = null) 524 { 525 $this->Sendmail = $sendmail; 526 527 if (!empty($this->Sendmail)) { 528 $this->isSendmail(); 529 530 return true; 531 } else { 532 $this->isMail(); 533 534 return false; 535 } 536 } 537 538 /** 539 * Use SMTP for sending the email 540 * 541 * @param string $auth SMTP Authentication [optional] 542 * @param string $host SMTP Host [optional] 543 * @param string $user SMTP Username [optional] 544 * @param string $pass SMTP Password [optional] 545 * @param string $secure Use secure methods 546 * @param integer $port The SMTP port 547 * 548 * @return boolean True on success 549 * 550 * @since 1.7.0 551 */ 552 public function useSmtp($auth = null, $host = null, $user = null, $pass = null, $secure = null, $port = 25) 553 { 554 $this->SMTPAuth = $auth; 555 $this->Host = $host; 556 $this->Username = $user; 557 $this->Password = $pass; 558 $this->Port = $port; 559 560 if ($secure === 'ssl' || $secure === 'tls') { 561 $this->SMTPSecure = $secure; 562 } 563 564 if ( 565 ($this->SMTPAuth !== null && $this->Host !== null && $this->Username !== null && $this->Password !== null) 566 || ($this->SMTPAuth === null && $this->Host !== null) 567 ) { 568 $this->isSMTP(); 569 570 return true; 571 } else { 572 $this->isMail(); 573 574 return false; 575 } 576 } 577 578 /** 579 * Function to send an email 580 * 581 * @param string $from From email address 582 * @param string $fromName From name 583 * @param mixed $recipient Recipient email address(es) 584 * @param string $subject email subject 585 * @param string $body Message body 586 * @param boolean $mode false = plain text, true = HTML 587 * @param mixed $cc CC email address(es) 588 * @param mixed $bcc BCC email address(es) 589 * @param mixed $attachment Attachment file name(s) 590 * @param mixed $replyTo Reply to email address(es) 591 * @param mixed $replyToName Reply to name(s) 592 * 593 * @return boolean True on success, false on failure when exception throwing is disabled. 594 * 595 * @since 1.7.0 596 * 597 * @throws MailDisabledException if the mail function is disabled 598 * @throws phpmailerException if exception throwing is enabled 599 */ 600 public function sendMail( 601 $from, 602 $fromName, 603 $recipient, 604 $subject, 605 $body, 606 $mode = false, 607 $cc = null, 608 $bcc = null, 609 $attachment = null, 610 $replyTo = null, 611 $replyToName = null 612 ) { 613 // Create config object 614 $app = Factory::getApplication(); 615 616 $this->setSubject($subject); 617 $this->setBody($body); 618 619 // Are we sending the email as HTML? 620 $this->isHtml($mode); 621 622 /* 623 * Do not send the message if adding any of the below items fails 624 */ 625 626 if ($this->addRecipient($recipient) === false) { 627 return false; 628 } 629 630 if ($this->addCc($cc) === false) { 631 return false; 632 } 633 634 if ($this->addBcc($bcc) === false) { 635 return false; 636 } 637 638 if ($this->addAttachment($attachment) === false) { 639 return false; 640 } 641 642 // Take care of reply email addresses 643 if (\is_array($replyTo)) { 644 $numReplyTo = \count($replyTo); 645 646 for ($i = 0; $i < $numReplyTo; $i++) { 647 if ($this->addReplyTo($replyTo[$i], $replyToName[$i]) === false) { 648 return false; 649 } 650 } 651 } elseif (isset($replyTo)) { 652 if ($this->addReplyTo($replyTo, $replyToName) === false) { 653 return false; 654 } 655 } elseif ($app->get('replyto')) { 656 $this->addReplyTo($app->get('replyto'), $app->get('replytoname')); 657 } 658 659 // Add sender to replyTo only if no replyTo received 660 $autoReplyTo = empty($this->ReplyTo); 661 662 if ($this->setSender(array($from, $fromName, $autoReplyTo)) === false) { 663 return false; 664 } 665 666 return $this->Send(); 667 } 668 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Wed Sep 7 05:41:13 2022 | Chilli.vc Blog - For Webmaster,Blog-Writer,System Admin and Domainer |