diff --git a/libraries/joomla/mail/mail.php b/libraries/joomla/mail/mail.php index 42fecf90e498a..eddc0826a7084 100644 --- a/libraries/joomla/mail/mail.php +++ b/libraries/joomla/mail/mail.php @@ -160,6 +160,35 @@ public function Send() } } + /** + * Set the From and FromName properties. + * + * @param string $address The sender email address + * @param string $name The sender name + * @param boolean $auto Whether to also set the Sender address, defaults to true + * + * @return boolean + * + * @since 11.1 + */ + public function setFrom($address, $name = '', $auto = true) + { + try + { + if (parent::setFrom($address, $name, $auto) === false) + { + return false; + } + } + catch (phpmailerException $e) + { + // The parent method will have already called the logging callback, just log our deprecated error handling message + JLog::add(__METHOD__ . '() will not catch phpmailerException objects as of 4.0.', JLog::WARNING, 'deprecated'); + + return false; + } + } + /** * Set the email sender * @@ -167,37 +196,54 @@ public function Send() * array([0] => email Address, [1] => Name) * or as a string * - * @return JMail Returns this object for chaining. + * @return JMail|boolean Returns this object for chaining on success or boolean false on failure. * * @since 11.1 * @throws UnexpectedValueException */ public function setSender($from) { - if (is_array($from)) + // Wrapped in try/catch if PHPMailer is configured to throw exceptions + try { - // If $from is an array we assume it has an address and a name - if (isset($from[2])) + if (is_array($from)) + { + // If $from is an array we assume it has an address and a name + if (isset($from[2])) + { + // If it is an array with entries, use them + $result = $this->setFrom(JMailHelper::cleanLine($from[0]), JMailHelper::cleanLine($from[1]), (bool) $from[2]); + } + else + { + $result = $this->setFrom(JMailHelper::cleanLine($from[0]), JMailHelper::cleanLine($from[1])); + } + } + elseif (is_string($from)) { - // If it is an array with entries, use them - $this->setFrom(JMailHelper::cleanLine($from[0]), JMailHelper::cleanLine($from[1]), (bool) $from[2]); + // If it is a string we assume it is just the address + $result = $this->setFrom(JMailHelper::cleanLine($from)); } else { - $this->setFrom(JMailHelper::cleanLine($from[0]), JMailHelper::cleanLine($from[1])); + // If it is neither, we log a message and throw an exception + JLog::add(JText::sprintf('JLIB_MAIL_INVALID_EMAIL_SENDER', $from), JLog::WARNING, 'jerror'); + + throw new UnexpectedValueException(sprintf('Invalid email Sender: %s, JMail::setSender(%s)', $from)); + } + + // Check for boolean false return if exception handling is disabled + if ($result === false) + { + return false; } } - elseif (is_string($from)) - { - // If it is a string we assume it is just the address - $this->setFrom(JMailHelper::cleanLine($from)); - } - else + catch (phpmailerException $e) { - // If it is neither, we log a message and throw an exception - JLog::add(JText::sprintf('JLIB_MAIL_INVALID_EMAIL_SENDER', $from), JLog::WARNING, 'jerror'); + // The parent method will have already called the logging callback, just log our deprecated error handling message + JLog::add(__METHOD__ . '() will not catch phpmailerException objects as of 4.0.', JLog::WARNING, 'deprecated'); - throw new UnexpectedValueException(sprintf('Invalid email Sender: %s, JMail::setSender(%s)', $from)); + return false; } return $this; @@ -246,7 +292,7 @@ public function setBody($content) * @param mixed $name Either a string or array of strings [name(s)] * @param string $method The parent method's name. * - * @return JMail Returns this object for chaining. + * @return JMail|boolean Returns this object for chaining on success or boolean false on failure. * * @since 11.1 * @throws InvalidArgumentException @@ -271,7 +317,23 @@ protected function add($recipient, $name = '', $method = 'addAddress') { $recipientEmail = JMailHelper::cleanLine($recipientEmail); $recipientName = JMailHelper::cleanLine($recipientName); - call_user_func('parent::' . $method, $recipientEmail, $recipientName); + + // Wrapped in try/catch if PHPMailer is configured to throw exceptions + try + { + // Check for boolean false return if exception handling is disabled + if (call_user_func('parent::' . $method, $recipientEmail, $recipientName) === false) + { + return false; + } + } + catch (phpmailerException $e) + { + // The parent method will have already called the logging callback, just log our deprecated error handling message + JLog::add(__METHOD__ . '() will not catch phpmailerException objects as of 4.0.', JLog::WARNING, 'deprecated'); + + return false; + } } } else @@ -281,14 +343,46 @@ protected function add($recipient, $name = '', $method = 'addAddress') foreach ($recipient as $to) { $to = JMailHelper::cleanLine($to); - call_user_func('parent::' . $method, $to, $name); + + // Wrapped in try/catch if PHPMailer is configured to throw exceptions + try + { + // Check for boolean false return if exception handling is disabled + if (call_user_func('parent::' . $method, $to, $name) === false) + { + return false; + } + } + catch (phpmailerException $e) + { + // The parent method will have already called the logging callback, just log our deprecated error handling message + JLog::add(__METHOD__ . '() will not catch phpmailerException objects as of 4.0.', JLog::WARNING, 'deprecated'); + + return false; + } } } } else { $recipient = JMailHelper::cleanLine($recipient); - call_user_func('parent::' . $method, $recipient, $name); + + // Wrapped in try/catch if PHPMailer is configured to throw exceptions + try + { + // Check for boolean false return if exception handling is disabled + if (call_user_func('parent::' . $method, $recipient, $name) === false) + { + return false; + } + } + catch (phpmailerException $e) + { + // The parent method will have already called the logging callback, just log our deprecated error handling message + JLog::add(__METHOD__ . '() will not catch phpmailerException objects as of 4.0.', JLog::WARNING, 'deprecated'); + + return false; + } } return $this; @@ -300,15 +394,13 @@ protected function add($recipient, $name = '', $method = 'addAddress') * @param mixed $recipient Either a string or array of strings [email address(es)] * @param mixed $name Either a string or array of strings [name(s)] * - * @return JMail Returns this object for chaining. + * @return JMail|boolean Returns this object for chaining. * * @since 11.1 */ public function addRecipient($recipient, $name = '') { - $this->add($recipient, $name, 'addAddress'); - - return $this; + return $this->add($recipient, $name, 'addAddress'); } /** @@ -317,7 +409,7 @@ public function addRecipient($recipient, $name = '') * @param mixed $cc Either a string or array of strings [email address(es)] * @param mixed $name Either a string or array of strings [name(s)] * - * @return JMail Returns this object for chaining. + * @return JMail|boolean Returns this object for chaining on success or boolean false on failure. * * @since 11.1 */ @@ -326,7 +418,7 @@ public function addCc($cc, $name = '') // If the carbon copy recipient is an array, add each recipient... otherwise just add the one if (isset($cc)) { - $this->add($cc, $name, 'addCC'); + return $this->add($cc, $name, 'addCC'); } return $this; @@ -338,7 +430,7 @@ public function addCc($cc, $name = '') * @param mixed $bcc Either a string or array of strings [email address(es)] * @param mixed $name Either a string or array of strings [name(s)] * - * @return JMail Returns this object for chaining. + * @return JMail|boolean Returns this object for chaining on success or boolean false on failure. * * @since 11.1 */ @@ -347,7 +439,7 @@ public function addBcc($bcc, $name = '') // If the blind carbon copy recipient is an array, add each recipient... otherwise just add the one if (isset($bcc)) { - $this->add($bcc, $name, 'addBCC'); + return $this->add($bcc, $name, 'addBCC'); } return $this; @@ -362,7 +454,7 @@ public function addBcc($bcc, $name = '') * @param mixed $type The mime type * @param string $disposition The disposition of the attachment * - * @return JMail Returns this object for chaining. + * @return JMail|boolean Returns this object for chaining on success or boolean false on failure. * * @since 12.2 * @throws InvalidArgumentException @@ -372,28 +464,45 @@ public function addAttachment($path, $name = '', $encoding = 'base64', $type = ' // If the file attachments is an array, add each file... otherwise just add the one if (isset($path)) { - if (is_array($path)) + // Wrapped in try/catch if PHPMailer is configured to throw exceptions + try { - if (!empty($name) && count($path) != count($name)) + if (is_array($path)) { - throw new InvalidArgumentException("The number of attachments must be equal with the number of name"); - } - - foreach ($path as $key => $file) - { - if (!empty($name)) + if (!empty($name) && count($path) != count($name)) { - parent::addAttachment($file, $name[$key], $encoding, $type); + throw new InvalidArgumentException("The number of attachments must be equal with the number of name"); } - else + + foreach ($path as $key => $file) { - parent::addAttachment($file, $name, $encoding, $type); + if (!empty($name)) + { + $result = parent::addAttachment($file, $name[$key], $encoding, $type); + } + else + { + $result = parent::addAttachment($file, $name, $encoding, $type); + } } } + else + { + $result = parent::addAttachment($path, $name, $encoding, $type); + } + + // Check for boolean false return if exception handling is disabled + if ($result === false) + { + return false; + } } - else + catch (phpmailerException $e) { - parent::addAttachment($path, $name, $encoding, $type); + // The parent method will have already called the logging callback, just log our deprecated error handling message + JLog::add(__METHOD__ . '() will not catch phpmailerException objects as of 4.0.', JLog::WARNING, 'deprecated'); + + return false; } } @@ -439,15 +548,13 @@ public function removeAttachment($index = 0) * @param mixed $replyto Either a string or array of strings [email address(es)] * @param mixed $name Either a string or array of strings [name(s)] * - * @return JMail Returns this object for chaining. + * @return JMail|boolean Returns this object for chaining on success or boolean false on failure. * * @since 11.1 */ public function addReplyTo($replyto, $name = '') { - $this->add($replyto, $name, 'addReplyTo'); - - return $this; + return $this->add($replyto, $name, 'addReplyTo'); } /** @@ -563,10 +670,29 @@ public function sendMail($from, $fromName, $recipient, $subject, $body, $mode = // Are we sending the email as HTML? $this->isHtml($mode); - $this->addRecipient($recipient); - $this->addCc($cc); - $this->addBcc($bcc); - $this->addAttachment($attachment); + /* + * Do not send the message if adding any of the below items fails + */ + + if ($this->addRecipient($recipient) === false) + { + return false; + } + + if ($this->addCc($cc) === false) + { + return false; + } + + if ($this->addBcc($bcc) === false) + { + return false; + } + + if ($this->addAttachment($attachment) === false) + { + return false; + } // Take care of reply email addresses if (is_array($replyTo)) @@ -575,17 +701,27 @@ public function sendMail($from, $fromName, $recipient, $subject, $body, $mode = for ($i = 0; $i < $numReplyTo; $i++) { - $this->addReplyTo($replyTo[$i], $replyToName[$i]); + if ($this->addReplyTo($replyTo[$i], $replyToName[$i]) === false) + { + return false; + } } } elseif (isset($replyTo)) { - $this->addReplyTo($replyTo, $replyToName); + if ($this->addReplyTo($replyTo, $replyToName) === false) + { + return false; + } } // Add sender to replyTo only if no replyTo received $autoReplyTo = (empty($this->ReplyTo)) ? true : false; - $this->setSender(array($from, $fromName, $autoReplyTo)); + + if ($this->setSender(array($from, $fromName, $autoReplyTo)) === false) + { + return false; + } return $this->Send(); } @@ -612,7 +748,11 @@ public function sendAdminMail($adminName, $adminEmail, $email, $type, $title, $a $message = sprintf(JText::_('JLIB_MAIL_MSG_ADMIN'), $adminName, $type, $title, $author, $url, $url, 'administrator', $type); $message .= JText::_('JLIB_MAIL_MSG') . "\n"; - $this->addRecipient($adminEmail); + if ($this->addRecipient($recipient) === false) + { + return false; + } + $this->setSubject($subject); $this->setBody($message);