From 7fe640bb471785fe5ec2bf08ae7cace72a1b2aa9 Mon Sep 17 00:00:00 2001 From: Kijin Sung Date: Wed, 8 Apr 2020 00:11:20 +0900 Subject: [PATCH] Re-add mail transport to SwiftMailer --- .../lib/classes/Swift/MailTransport.php | 47 +++ .../classes/Swift/Transport/MailTransport.php | 294 ++++++++++++++++++ 2 files changed, 341 insertions(+) create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/MailTransport.php create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/MailTransport.php diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/MailTransport.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/MailTransport.php new file mode 100644 index 000000000..18556989a --- /dev/null +++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/MailTransport.php @@ -0,0 +1,47 @@ +createDependenciesFor('transport.mail') + ); + + $this->setExtraParams($extraParams); + } + + /** + * Create a new MailTransport instance. + * + * @param string $extraParams To be passed to mail() + * + * @return self + */ + public static function newInstance($extraParams = '-f%s') + { + return new self($extraParams); + } +} diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/MailTransport.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/MailTransport.php new file mode 100644 index 000000000..55e932384 --- /dev/null +++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/MailTransport.php @@ -0,0 +1,294 @@ +_extraParams = $params; + + return $this; + } + + /** + * Get the additional parameters used on the mail() function. + * + * This string is formatted for sprintf() where %s is the sender address. + * + * @return string + */ + public function getExtraParams() + { + return $this->_extraParams; + } + + /** + * Send the given Message. + * + * Recipient/sender data will be retrieved from the Message API. + * The return value is the number of recipients who were accepted for delivery. + * + * @param Swift_Mime_Message $message + * @param string[] $failedRecipients An array of failures by-reference + * + * @return int + */ + public function send(Swift_Mime_SimpleMessage $message, &$failedRecipients = null) + { + $failedRecipients = (array) $failedRecipients; + + $count = ( + count((array) $message->getTo()) + + count((array) $message->getCc()) + + count((array) $message->getBcc()) + ); + + $toHeader = $message->getHeaders()->get('To'); + $subjectHeader = $message->getHeaders()->get('Subject'); + + if (0 === $count) { + $this->_throwException(new Swift_TransportException('Cannot send message without a recipient')); + } + $to = $toHeader ? $toHeader->getFieldBody() : ''; + $subject = $subjectHeader ? $subjectHeader->getFieldBody() : ''; + + $reversePath = $this->_getReversePath($message); + + // Remove headers that would otherwise be duplicated + $message->getHeaders()->remove('To'); + $message->getHeaders()->remove('Subject'); + + $messageStr = $message->toString(); + + if ($toHeader) { + $message->getHeaders()->set($toHeader); + } + $message->getHeaders()->set($subjectHeader); + + // Separate headers from body + if (false !== $endHeaders = strpos($messageStr, "\r\n\r\n")) { + $headers = substr($messageStr, 0, $endHeaders)."\r\n"; //Keep last EOL + $body = substr($messageStr, $endHeaders + 4); + } else { + $headers = $messageStr."\r\n"; + $body = ''; + } + + unset($messageStr); + + if ("\r\n" != PHP_EOL) { + // Non-windows (not using SMTP) + $headers = str_replace("\r\n", PHP_EOL, $headers); + $subject = str_replace("\r\n", PHP_EOL, $subject); + $body = str_replace("\r\n", PHP_EOL, $body); + $to = str_replace("\r\n", PHP_EOL, $to); + } else { + // Windows, using SMTP + $headers = str_replace("\r\n.", "\r\n..", $headers); + $subject = str_replace("\r\n.", "\r\n..", $subject); + $body = str_replace("\r\n.", "\r\n..", $body); + $to = str_replace("\r\n.", "\r\n..", $to); + } + + if ($this->mail($to, $subject, $body, $headers, $this->_formatExtraParams($this->_extraParams, $reversePath))) { + if ($evt) { + $evt->setResult(Swift_Events_SendEvent::RESULT_SUCCESS); + $evt->setFailedRecipients($failedRecipients); + } + } else { + $failedRecipients = array_merge( + $failedRecipients, + array_keys((array) $message->getTo()), + array_keys((array) $message->getCc()), + array_keys((array) $message->getBcc()) + ); + + if ($evt) { + $evt->setResult(Swift_Events_SendEvent::RESULT_FAILED); + $evt->setFailedRecipients($failedRecipients); + } + + $message->generateId(); + + $count = 0; + } + + return $count; + } + + /** + * Register a plugin. + * + * @param Swift_Events_EventListener $plugin + */ + public function registerPlugin(Swift_Events_EventListener $plugin) + { + + } + + /** Throw a TransportException, first sending it to any listeners */ + protected function _throwException(Swift_TransportException $e) + { + throw $e; + } + + /** + * Send mail via the mail() function. + * + * This method takes the same arguments as PHP mail(). + * + * @param string $to + * @param string $subject + * @param string $body + * @param string $headers + * @param string $extraParams + * + * @return bool + */ + public function mail($to, $subject, $body, $headers = null, $extraParams = null) + { + return @mail($to, $subject, $body, $headers, $extraParams); + } + + /** Determine the best-use reverse path for this message */ + private function _getReversePath(Swift_Mime_SimpleMessage $message) + { + $return = $message->getReturnPath(); + $sender = $message->getSender(); + $from = $message->getFrom(); + $path = null; + if (!empty($return)) { + $path = $return; + } elseif (!empty($sender)) { + $keys = array_keys($sender); + $path = array_shift($keys); + } elseif (!empty($from)) { + $keys = array_keys($from); + $path = array_shift($keys); + } + + return $path; + } + + /** + * Fix CVE-2016-10074 by disallowing potentially unsafe shell characters. + * + * Note that escapeshellarg and escapeshellcmd are inadequate for our purposes, especially on Windows. + * + * @param string $string The string to be validated + * + * @return bool + */ + private function _isShellSafe($string) + { + // Future-proof + if (escapeshellcmd($string) !== $string || !in_array(escapeshellarg($string), array("'$string'", "\"$string\""))) { + return false; + } + + $length = strlen($string); + for ($i = 0; $i < $length; ++$i) { + $c = $string[$i]; + // All other characters have a special meaning in at least one common shell, including = and +. + // Full stop (.) has a special meaning in cmd.exe, but its impact should be negligible here. + // Note that this does permit non-Latin alphanumeric characters based on the current locale. + if (!ctype_alnum($c) && strpos('@_-.', $c) === false) { + return false; + } + } + + return true; + } + + /** + * Return php mail extra params to use for invoker->mail. + * + * @param $extraParams + * @param $reversePath + * + * @return string|null + */ + private function _formatExtraParams($extraParams, $reversePath) + { + if (false !== strpos($extraParams, '-f%s')) { + if (empty($reversePath) || false === $this->_isShellSafe($reversePath)) { + $extraParams = str_replace('-f%s', '', $extraParams); + } else { + $extraParams = sprintf($extraParams, $reversePath); + } + } + + return !empty($extraParams) ? $extraParams : null; + } +}