Bug #24471 ยป 16911.patch
t3lib/config_default.php (working copy) | ||
---|---|---|
$TYPO3_CONF_VARS['SC_OPTIONS']['errors']['exceptionalErrors'] = $TYPO3_CONF_VARS['SYS']['exceptionalErrors'];
|
||
// Mail sending via Swift Mailer
|
||
$TYPO3_CONF_VARS['SC_OPTIONS']['t3lib/utility/class.t3lib_utility_mail.php']['substituteMailDelivery'][] = 'tx_t3lib_mail_hooks->sendMail';
|
||
$TYPO3_CONF_VARS['SC_OPTIONS']['t3lib/utility/class.t3lib_utility_mail.php']['substituteMailDelivery'][] = 't3lib_mail_SwiftMailerAdapter';
|
||
// Turn error logging on/off.
|
||
if (($displayErrors = intval($TYPO3_CONF_VARS['SYS']['displayErrors'])) != '-1') {
|
t3lib/core_autoload.php (working copy) | ||
---|---|---|
't3lib_formprotection_backendformprotection' => PATH_t3lib . 'formprotection/class.t3lib_formprotection_backendformprotection.php',
|
||
't3lib_formprotection_installtoolformprotection' => PATH_t3lib . 'formprotection/class.t3lib_formprotection_installtoolformprotection.php',
|
||
't3lib_localrecordlistgettablehook' => PATH_t3lib . 'interfaces/interface.t3lib_localrecordlistgettablehook.php',
|
||
't3lib_mail_maileradapter' => PATH_t3lib . 'interfaces/interface.t3lib_mail_maileradapter.php',
|
||
't3lib_pageselect_getpagehook' => PATH_t3lib . 'interfaces/interface.t3lib_pageselect_getpagehook.php',
|
||
't3lib_pageselect_getrecordoverlayhook' => PATH_t3lib . 'interfaces/interface.t3lib_pageselect_getrecordoverlayhook.php',
|
||
't3lib_pageselect_getpageoverlayhook' => PATH_t3lib . 'interfaces/interface.t3lib_pageselect_getpageoverlayhook.php',
|
||
... | ... | |
't3lib_mail_mboxtransport' => PATH_t3lib . 'mail/class.t3lib_mail_mboxtransport.php',
|
||
't3lib_mail_message' => PATH_t3lib . 'mail/class.t3lib_mail_message.php',
|
||
't3lib_mail_mailer' => PATH_t3lib . 'mail/class.t3lib_mail_mailer.php',
|
||
'tx_t3lib_mail_hooks' => PATH_t3lib . 'mail/class.tx_t3lib_mail_hooks.php',
|
||
't3lib_mail_swiftmaileradapter' => PATH_t3lib . 'mail/class.t3lib_mail_swiftmaileradapter.php',
|
||
't3lib_matchcondition_abstract' => PATH_t3lib . 'matchcondition/class.t3lib_matchcondition_abstract.php',
|
||
't3lib_matchcondition_backend' => PATH_t3lib . 'matchcondition/class.t3lib_matchcondition_backend.php',
|
||
't3lib_matchcondition_frontend' => PATH_t3lib . 'matchcondition/class.t3lib_matchcondition_frontend.php',
|
t3lib/interfaces/interface.t3lib_mail_maileradapter.php (revision 0) | ||
---|---|---|
<?php
|
||
/***************************************************************
|
||
* Copyright notice
|
||
*
|
||
* (c) 2011 Ingo Renner <ingo@typo3.org>
|
||
* All rights reserved
|
||
*
|
||
* This script is part of the TYPO3 project. The TYPO3 project is
|
||
* free software; you can redistribute it and/or modify
|
||
* it under the terms of the GNU General Public License as published by
|
||
* the Free Software Foundation; either version 2 of the License, or
|
||
* (at your option) any later version.
|
||
*
|
||
* The GNU General Public License can be found at
|
||
* http://www.gnu.org/copyleft/gpl.html.
|
||
* A copy is found in the textfile GPL.txt and important notices to the license
|
||
* from the author is found in LICENSE.txt distributed with these scripts.
|
||
*
|
||
*
|
||
* This script is distributed in the hope that it will be useful,
|
||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
* GNU General Public License for more details.
|
||
*
|
||
* This copyright notice MUST APPEAR in all copies of the script!
|
||
***************************************************************/
|
||
|
||
/**
|
||
* Mailer Adapter interface
|
||
*
|
||
* @author Ingo Renner <ingo@typo3.org>
|
||
* @package TYPO3
|
||
* @subpackage t3lib
|
||
*/
|
||
interface t3lib_mail_MailerAdapter {
|
||
|
||
/**
|
||
* Mail sending function
|
||
*
|
||
* @param string $to Mail recipient.
|
||
* @param string $subject Mail subject.
|
||
* @param string $messageBody Mail body.
|
||
* @param array $additionalHeaders Additional mail headers.
|
||
* @param array $additionalParameters Additional mailer parameters.
|
||
* @param boolean $fakeSending Whether to fake sending or not, used in Unit Tests.
|
||
* @return boolean TRUE if the mail was successfully sent, FALSE otherwise.
|
||
*/
|
||
public function mail($to, $subject, $messageBody, $additionalHeaders = NULL, $additionalParameters = NULL, $fakeSending = FALSE);
|
||
|
||
}
|
||
|
||
?>
|
t3lib/mail/class.t3lib_mail_swiftmaileradapter.php (working copy) | ||
---|---|---|
<?php
|
||
/***************************************************************
|
||
* Copyright notice
|
||
*
|
||
* (c) 2010 Jigal van Hemert <jigal@xs4all.nl>
|
||
* All rights reserved
|
||
*
|
||
* This script is part of the TYPO3 project. The TYPO3 project is
|
||
* free software; you can redistribute it and/or modify
|
||
* it under the terms of the GNU General Public License as published by
|
||
* the Free Software Foundation; either version 2 of the License, or
|
||
* (at your option) any later version.
|
||
*
|
||
* The GNU General Public License can be found at
|
||
* http://www.gnu.org/copyleft/gpl.html.
|
||
* A copy is found in the textfile GPL.txt and important notices to the license
|
||
* from the author is found in LICENSE.txt distributed with these scripts.
|
||
*
|
||
*
|
||
* This script is distributed in the hope that it will be useful,
|
||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
* GNU General Public License for more details.
|
||
*
|
||
* This copyright notice MUST APPEAR in all copies of the script!
|
||
***************************************************************/
|
||
|
||
/**
|
||
* Hook subscriber for using Swift Mailer with the t3lib_utility_mail function
|
||
*
|
||
* $Id$
|
||
*
|
||
* @author Jigal van Hemert <jigal@xs4all.nl>
|
||
* @package TYPO3
|
||
* @subpackage t3lib
|
||
*/
|
||
class tx_t3lib_mail_hooks {
|
||
|
||
/** @var $mailerObject t3lib_mail_Mailer */
|
||
protected $mailerObject;
|
||
|
||
/** @var $messageObject Swift_Message */
|
||
protected $messageObject;
|
||
|
||
/** @var $messageHeaders Swift_Mime_HeaderSet */
|
||
protected $messageHeaders;
|
||
|
||
/**
|
||
* @param array $parameters Array with keys: 'to', 'subject', 'messageBody', 'additionalHeaders', 'additionalParameters'
|
||
* @param bool $fakeSending If set fake sending a mail
|
||
* @throws t3lib_exception
|
||
* @return bool
|
||
*/
|
||
public function sendMail(array $parameters = array(), $fakeSending = FALSE) {
|
||
|
||
// report success for fake sending
|
||
if ($fakeSending === TRUE) {
|
||
return TRUE;
|
||
}
|
||
// create mailer object
|
||
$this->mailerObject = t3lib_div::makeInstance('t3lib_mail_Mailer');
|
||
|
||
// create message object
|
||
$this->messageObject = Swift_Message::newInstance($parameters['subject'], $parameters['messageBody']);
|
||
$this->messageObject->setTo($parameters['to']);
|
||
// handle additional headers
|
||
$headers = t3lib_div::trimExplode(LF, $parameters['additionalHeaders'], TRUE);
|
||
$this->messageHeaders = $this->messageObject->getHeaders();
|
||
foreach ($headers as $header) {
|
||
list($headerName, $headerValue) = t3lib_div::trimExplode(':', $header, FALSE, 2);
|
||
$this->setHeader($headerName, $headerValue);
|
||
}
|
||
// handle additional parameters (force return path)
|
||
if (preg_match('/-f\s*(\S*?)/', $parameters['additionalParameters'], $matches)) {
|
||
$this->messageObject->setReturnPath($this->unEscapeShellArg($matches[1]));
|
||
}
|
||
// handle from:
|
||
$from = $this->messageObject->getFrom();
|
||
if (count($from) > 0) {
|
||
reset($from);
|
||
list($fromAddress, $fromName) = each($from);
|
||
} else {
|
||
$fromAddress = $this->messageObject->getReturnPath();
|
||
$fromName = $fromAddress;
|
||
}
|
||
if (strlen($fromAddress) == 0) {
|
||
$fromAddress = 'no-reply@example.org';
|
||
$fromName = 'TYPO3 Installation';
|
||
}
|
||
$this->messageObject->setFrom(array($fromAddress => $fromName));
|
||
// send mail
|
||
$result = $this->mailerObject->send($this->messageObject);
|
||
|
||
// report success/failure
|
||
return (bool) $result;
|
||
}
|
||
|
||
/**
|
||
* Tries to undo the action by escapeshellarg()
|
||
*
|
||
* @param $escapedString String escaped by escapeshellarg()
|
||
* @return string String with escapeshellarg() action undone as best as possible
|
||
*/
|
||
protected function unEscapeShellArg($escapedString) {
|
||
if (TYPO3_OS === 'WIN') {
|
||
// on Windows double quotes are used and % signs are replaced by spaces
|
||
if (preg_match('/^"([^"]*)"$/', trim($escapedString), $matches)) {
|
||
$result = str_replace('\"', '"', $matches[1]);
|
||
// % signs are replaced with spaces, so they can't be recovered
|
||
}
|
||
} else {
|
||
// on Unix-like systems single quotes are escaped
|
||
if (preg_match('/^\'([^' . preg_quote('\'') . ']*)\'$/', trim($escapedString), $matches)) {
|
||
$result = str_replace('\\\'', '\'', $matches[1]);
|
||
}
|
||
}
|
||
return $result;
|
||
}
|
||
|
||
/**
|
||
* Handles setting and replacing of mail headers
|
||
*
|
||
* @param $headerName Name of header
|
||
* @param $headerValue Value of header
|
||
* @return void
|
||
*/
|
||
protected function setHeader($headerName, $headerValue) {
|
||
if ($this->messageHeaders->has($headerName)) {
|
||
$header = $this->messageHeaders->get($headerName);
|
||
$headerType = $header->getFieldType();
|
||
switch ($headerType) {
|
||
case Swift_Mime_Header::TYPE_TEXT:
|
||
$header->setValue($headerValue);
|
||
break;
|
||
case Swift_Mime_Header::TYPE_PARAMETERIZED:
|
||
$header->setValue($headerValue);
|
||
break;
|
||
case Swift_Mime_Header::TYPE_MAILBOX:
|
||
// mailbox headers look like:
|
||
// name <email@example.org>, othermail@example.org, ...
|
||
// pattern matches cases with and without name
|
||
// comma is added to match each item in a comma separated list
|
||
preg_match_all('/,\s*([^<]+)(<([^>]*?)>)?/', ', ' . $headerValue, $addresses, PREG_SET_ORDER);
|
||
$addressList = array();
|
||
foreach ($addresses as $address) {
|
||
if (!$address[2]) {
|
||
// item with name found ( name <email@example.org> )
|
||
if (t3lib_div::validEmail($address[1])) {
|
||
$addressList[] = $address[1];
|
||
}
|
||
} else {
|
||
// item without name found ( email@example.org )
|
||
if (t3lib_div::validEmail($address[3])) {
|
||
$addressList[$address[3]] = $address[1];
|
||
}
|
||
}
|
||
}
|
||
if (count($addressList) > 0) {
|
||
$header->setNameAddresses($addressList);
|
||
}
|
||
break;
|
||
case Swift_Mime_Header::TYPE_DATE:
|
||
$header->setTimeStamp(strtotime($headerValue));
|
||
break;
|
||
case Swift_Mime_Header::TYPE_ID:
|
||
// remove '<' and '>' from ID headers
|
||
$header->setId(trim($headerValue, '<>'));
|
||
break;
|
||
case Swift_Mime_Header::TYPE_PATH:
|
||
$header->setAddress($headerValue);
|
||
break;
|
||
}
|
||
// change value
|
||
} else {
|
||
switch ($headerName) {
|
||
// mailbox headers
|
||
case 'From':
|
||
case 'To':
|
||
case 'Cc':
|
||
case 'Bcc':
|
||
case 'Reply-To':
|
||
case 'Sender':
|
||
// mailbox headers look like:
|
||
// name <email@example.org>, othermail@example.org, ...
|
||
// pattern matches cases with and without name
|
||
// comma is added to match each item in a comma separated list
|
||
preg_match_all('/,\s*(.*?)(<([^>]*?)>)?/', ', ' . $headerValue, $addresses, PREG_SET_ORDER);
|
||
$addressList = array();
|
||
foreach ($addresses as $address) {
|
||
if ($address[2]) {
|
||
// item with name found ( name <email@example.org> )
|
||
if (t3lib_div::validEmail($address[1])) {
|
||
$addressList[] = $address[1];
|
||
}
|
||
} else {
|
||
// item without name found ( email@example.org )
|
||
if (t3lib_div::validEmail($address[3])) {
|
||
$addressList[$address[3]] = $address[1];
|
||
}
|
||
}
|
||
}
|
||
if (count($addressList) > 0) {
|
||
$header->addMailboxHeader($headerName, $addressList);
|
||
}
|
||
break;
|
||
// date headers
|
||
case 'Date':
|
||
$this->messageHeaders->addDateHeader($headerName, strtotime($headerValue));
|
||
break;
|
||
// ID headers
|
||
case 'Message-ID':
|
||
// remove '<' and '>' from ID headers
|
||
$this->messageHeaders->addIdHeader($headerName, trim($headerValue, '<>'));
|
||
// path headers
|
||
case 'Return-Path':
|
||
$this->messageHeaders->addPathHeader($headerName, $headerValue);
|
||
break;
|
||
// parameterized headers
|
||
case 'Content-Type':
|
||
case 'Content-Disposition':
|
||
$this->messageHeaders->addParameterizedHeader($headerName, $headerValue);
|
||
break;
|
||
// text headers
|
||
default:
|
||
$this->messageHeaders->addTextheader($headerName, $headerValue);
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
<?php
|
||
/***************************************************************
|
||
* Copyright notice
|
||
*
|
||
* (c) 2010 Jigal van Hemert <jigal@xs4all.nl>
|
||
* All rights reserved
|
||
*
|
||
* This script is part of the TYPO3 project. The TYPO3 project is
|
||
* free software; you can redistribute it and/or modify
|
||
* it under the terms of the GNU General Public License as published by
|
||
* the Free Software Foundation; either version 2 of the License, or
|
||
* (at your option) any later version.
|
||
*
|
||
* The GNU General Public License can be found at
|
||
* http://www.gnu.org/copyleft/gpl.html.
|
||
* A copy is found in the textfile GPL.txt and important notices to the license
|
||
* from the author is found in LICENSE.txt distributed with these scripts.
|
||
*
|
||
*
|
||
* This script is distributed in the hope that it will be useful,
|
||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
* GNU General Public License for more details.
|
||
*
|
||
* This copyright notice MUST APPEAR in all copies of the script!
|
||
***************************************************************/
|
||
/**
|
||
* Hook subscriber for using Swift Mailer with the t3lib_utility_mail function
|
||
*
|
||
* $Id$
|
||
*
|
||
* @author Jigal van Hemert <jigal@xs4all.nl>
|
||
* @package TYPO3
|
||
* @subpackage t3lib
|
||
*/
|
||
class t3lib_mail_SwiftMailerAdapter implements t3lib_mail_MailerAdapter {
|
||
/** @var $mailer t3lib_mail_Mailer */
|
||
protected $mailer;
|
||
/** @var $message Swift_Message */
|
||
protected $message;
|
||
/** @var $messageHeaders Swift_Mime_HeaderSet */
|
||
protected $messageHeaders;
|
||
/** @var string */
|
||
protected $boundary = '';
|
||
/**
|
||
* Constructor
|
||
*
|
||
* @return void
|
||
*/
|
||
public function __construct() {
|
||
// create mailer object
|
||
$this->mailer = t3lib_div::makeInstance('t3lib_mail_Mailer');
|
||
// create message object
|
||
$this->message = Swift_Message::newInstance();
|
||
}
|
||
/**
|
||
* Parses parts of the mail message and sends it with the Swift Mailer functions
|
||
*
|
||
* @param string $to Email address to send the message to
|
||
* @param string $subject Subject of mail message
|
||
* @param string $messageBody Raw body (may be multipart)
|
||
* @param array $additionalHeaders Additional mail headers
|
||
* @param array $additionalParameters Extra parameters for the mail() command
|
||
* @param bool $fakeSending If set fake sending a mail
|
||
* @throws t3lib_exception
|
||
* @return bool
|
||
*/
|
||
public function mail($to, $subject, $messageBody, $additionalHeaders = NULL, $additionalParameters = NULL, $fakeSending = FALSE) {
|
||
// report success for fake sending
|
||
if ($fakeSending === TRUE) {
|
||
return TRUE;
|
||
}
|
||
$this->message->setSubject($subject);
|
||
$this->message->setTo($to);
|
||
// handle additional headers
|
||
$headers = t3lib_div::trimExplode(LF, $additionalHeaders, TRUE);
|
||
$this->messageHeaders = $this->message->getHeaders();
|
||
foreach ($headers as $header) {
|
||
list($headerName, $headerValue) = t3lib_div::trimExplode(':', $header, FALSE, 2);
|
||
$this->setHeader($headerName, $headerValue);
|
||
}
|
||
// handle additional parameters (force return path)
|
||
if (preg_match('/-f\s*(\S*?)/', $additionalParameters, $matches)) {
|
||
$this->message->setReturnPath($this->unescapeShellArguments($matches[1]));
|
||
}
|
||
// handle from:
|
||
$this->fixSender();
|
||
// handle message body
|
||
$this->setBody($messageBody);
|
||
// send mail
|
||
$result = $this->mailer->send($this->message);
|
||
// report success/failure
|
||
return (bool) $result;
|
||
}
|
||
/**
|
||
* Tries to undo the action by escapeshellarg()
|
||
*
|
||
* @param $escapedString String escaped by escapeshellarg()
|
||
* @return string String with escapeshellarg() action undone as best as possible
|
||
*/
|
||
protected function unescapeShellArguments($escapedString) {
|
||
if (TYPO3_OS === 'WIN') {
|
||
// on Windows double quotes are used and % signs are replaced by spaces
|
||
if (preg_match('/^"([^"]*)"$/', trim($escapedString), $matches)) {
|
||
$result = str_replace('\"', '"', $matches[1]);
|
||
// % signs are replaced with spaces, so they can't be recovered
|
||
}
|
||
} else {
|
||
// on Unix-like systems single quotes are escaped
|
||
if (preg_match('/^\'([^' . preg_quote('\'') . ']*)\'$/', trim($escapedString), $matches)) {
|
||
$result = str_replace('\\\'', '\'', $matches[1]);
|
||
}
|
||
}
|
||
return $result;
|
||
}
|
||
/**
|
||
* Handles setting and replacing of mail headers
|
||
*
|
||
* @param $headerName Name of header
|
||
* @param $headerValue Value of header
|
||
* @return void
|
||
*/
|
||
protected function setHeader($headerName, $headerValue) {
|
||
// check for boundary in headers
|
||
if (preg_match('/^boundary="(.*)"$/', $headerName, $matches) > 0) {
|
||
$this->boundary = $matches[1];
|
||
return;
|
||
}
|
||
// process other, real headers
|
||
if ($this->messageHeaders->has($headerName)) {
|
||
$header = $this->messageHeaders->get($headerName);
|
||
$headerType = $header->getFieldType();
|
||
switch ($headerType) {
|
||
case Swift_Mime_Header::TYPE_TEXT:
|
||
$header->setValue($headerValue);
|
||
break;
|
||
case Swift_Mime_Header::TYPE_PARAMETERIZED:
|
||
$header->setValue(rtrim($headerValue, ';'));
|
||
break;
|
||
case Swift_Mime_Header::TYPE_MAILBOX:
|
||
$addressList = $this->parseAddresses($headerValue);
|
||
if (count($addressList) > 0) {
|
||
$header->setNameAddresses($addressList);
|
||
}
|
||
break;
|
||
case Swift_Mime_Header::TYPE_DATE:
|
||
$header->setTimeStamp(strtotime($headerValue));
|
||
break;
|
||
case Swift_Mime_Header::TYPE_ID:
|
||
// remove '<' and '>' from ID headers
|
||
$header->setId(trim($headerValue, '<>'));
|
||
break;
|
||
case Swift_Mime_Header::TYPE_PATH:
|
||
$header->setAddress($headerValue);
|
||
break;
|
||
}
|
||
// change value
|
||
} else {
|
||
switch ($headerName) {
|
||
// mailbox headers
|
||
case 'From':
|
||
case 'To':
|
||
case 'Cc':
|
||
case 'Bcc':
|
||
case 'Reply-To':
|
||
case 'Sender':
|
||
$addressList = $this->parseAddresses($headerValue);
|
||
if (count($addressList) > 0) {
|
||
$header->addMailboxHeader($headerName, $addressList);
|
||
}
|
||
break;
|
||
// date headers
|
||
case 'Date':
|
||
$this->messageHeaders->addDateHeader($headerName, strtotime($headerValue));
|
||
break;
|
||
// ID headers
|
||
case 'Message-ID':
|
||
// remove '<' and '>' from ID headers
|
||
$this->messageHeaders->addIdHeader($headerName, trim($headerValue, '<>'));
|
||
// path headers
|
||
case 'Return-Path':
|
||
$this->messageHeaders->addPathHeader($headerName, $headerValue);
|
||
break;
|
||
// parameterized headers
|
||
case 'Content-Type':
|
||
case 'Content-Disposition':
|
||
$this->messageHeaders->addParameterizedHeader($headerName, rtrim($headerValue, ';'));
|
||
break;
|
||
// text headers
|
||
default:
|
||
$this->messageHeaders->addTextheader($headerName, $headerValue);
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
/**
|
||
* Sets body of mail message. Handles multi-part and single part messages. Encoded body parts are decoded prior to adding
|
||
* them to the message object.
|
||
*
|
||
* @param string $body Raw body, may be multi-part
|
||
* @return void
|
||
*/
|
||
protected function setBody($body) {
|
||
if ($this->boundary) {
|
||
// handle multi-part
|
||
$bodyParts = preg_split('/--' . preg_quote($this->boundary) . '(--)?/m', $body, NULL, PREG_SPLIT_NO_EMPTY);
|
||
foreach ($bodyParts as $bodyPart) {
|
||
// skip empty parts
|
||
if (trim($bodyPart) == '') {
|
||
continue;
|
||
}
|
||
// keep leading white space when exploding the text
|
||
$lines = explode(LF, $bodyPart);
|
||
// set defaults for this part
|
||
$encoding = '';
|
||
$charset = 'utf-8';
|
||
$contentType = 'text/plain';
|
||
// skip intro messages
|
||
if (trim($lines[0]) == 'This is a multi-part message in MIME format.') {
|
||
continue;
|
||
}
|
||
// first line is empty leftover from splitting
|
||
array_shift($lines);
|
||
while (count($lines) > 0) {
|
||
$line = array_shift($lines);
|
||
if (preg_match('/^content-type:(.*);( charset=(.*))?$/i', $line, $matches)) {
|
||
$contentType = trim($matches[1]);
|
||
if ($matches[2]) {
|
||
$charset = trim($matches[3]);
|
||
}
|
||
} else if (preg_match('/^content-transfer-encoding:(.*)$/i', $line, $matches)) {
|
||
$encoding = trim($matches[1]);
|
||
} else if (strlen(trim($line)) == 0) {
|
||
// empty line before actual content of this part
|
||
break;
|
||
}
|
||
}
|
||
// use rest of part as body, but reverse encoding first
|
||
$bodyPart = $this->decode(implode(LF, $lines), $encoding);
|
||
$this->message->addPart($bodyPart, $contentType, $charset);
|
||
}
|
||
} else {
|
||
// Handle single body
|
||
// The headers have already been set, so use header information
|
||
$contentType = $this->message->getContentType();
|
||
$charset = $this->message->getCharset();
|
||
$encoding = $this->message->getEncoder();
|
||
// reverse encoding and set body
|
||
$rawBody = $this->decode($body, $encoding);
|
||
$this->message->setBody($rawBody, $contentType, $charset);
|
||
}
|
||
}
|
||
/**
|
||
* Reverts encoding of body text
|
||
*
|
||
* @param string $text Body text to be decoded
|
||
* @param string $encoding Encoding type to be reverted
|
||
* @return string Decoded message body
|
||
*/
|
||
protected function decode($text, $encoding) {
|
||
$result = $text;
|
||
switch ($encoding) {
|
||
case 'quoted-printable':
|
||
$result = quoted_printable_decode($text);
|
||
break;
|
||
case 'base64':
|
||
$result = base64_decode($text);
|
||
break;
|
||
}
|
||
return $result;
|
||
}
|
||
/**
|
||
* Parses mailbox headers and turns them into an array.
|
||
*
|
||
* Mailbox headers are a comma separated list of 'name <email@example.org' combinations or plain email addresses (or a mix
|
||
* of these).
|
||
* The resulting array has key-value pairs where the key is either a number (no name in the mailbox header) or a display
|
||
* name and the value is the email address.
|
||
*
|
||
* @param string $rawAddresses Comma separated list of email addresses (optionally with display name)
|
||
* @return array Parsed list of addresses.
|
||
*/
|
||
protected function parseAddresses($rawAddresses = '') {
|
||
// comma is added to match each item in a comma separated list
|
||
preg_match_all('/,\s*([^<]+)(<([^>]*?)>)?/', ', ' . $rawAddresses, $addresses, PREG_SET_ORDER);
|
||
$addressList = array();
|
||
foreach ($addresses as $address) {
|
||
if ($address[2]) {
|
||
// item with name found ( name <email@example.org> )
|
||
if (t3lib_div::validEmail($address[1])) {
|
||
$addressList[] = $address[1];
|
||
}
|
||
} else {
|
||
// item without name found ( email@example.org )
|
||
if (t3lib_div::validEmail($address[3])) {
|
||
$addressList[$address[3]] = trim($address[1], "\n\r\t\0\x0B \"");
|
||
}
|
||
}
|
||
}
|
||
return $addressList;
|
||
}
|
||
/**
|
||
* Makes sure there is a correct sender set.
|
||
*
|
||
* If there is no from header the returnpath will be used. If that also fails a fake address will be used to make sure
|
||
* Swift Mailer will be able to send the message. Some SMTP server will not accept mail messages without a valid sender.
|
||
*
|
||
* @return void
|
||
*/
|
||
protected function fixSender() {
|
||
$from = $this->message->getFrom();
|
||
if (count($from) > 0) {
|
||
reset($from);
|
||
list($fromAddress, $fromName) = each($from);
|
||
} else {
|
||
$fromAddress = $this->message->getReturnPath();
|
||
$fromName = $fromAddress;
|
||
}
|
||
if (strlen($fromAddress) == 0) {
|
||
$fromAddress = 'no-reply@example.org';
|
||
$fromName = 'TYPO3 CMS';
|
||
}
|
||
$this->message->setFrom(array($fromAddress => $fromName));
|
||
}
|
||
}
|
t3lib/mail/class.tx_t3lib_mail_hooks.php (working copy) | ||
---|---|---|
<?php
|
||
/***************************************************************
|
||
* Copyright notice
|
||
*
|
||
* (c) 2010 Jigal van Hemert <jigal@xs4all.nl>
|
||
* All rights reserved
|
||
*
|
||
* This script is part of the TYPO3 project. The TYPO3 project is
|
||
* free software; you can redistribute it and/or modify
|
||
* it under the terms of the GNU General Public License as published by
|
||
* the Free Software Foundation; either version 2 of the License, or
|
||
* (at your option) any later version.
|
||
*
|
||
* The GNU General Public License can be found at
|
||
* http://www.gnu.org/copyleft/gpl.html.
|
||
* A copy is found in the textfile GPL.txt and important notices to the license
|
||
* from the author is found in LICENSE.txt distributed with these scripts.
|
||
*
|
||
*
|
||
* This script is distributed in the hope that it will be useful,
|
||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
* GNU General Public License for more details.
|
||
*
|
||
* This copyright notice MUST APPEAR in all copies of the script!
|
||
***************************************************************/
|
||
|
||
/**
|
||
* Hook subscriber for using Swift Mailer with the t3lib_utility_mail function
|
||
*
|
||
* $Id$
|
||
*
|
||
* @author Jigal van Hemert <jigal@xs4all.nl>
|
||
* @package TYPO3
|
||
* @subpackage t3lib
|
||
*/
|
||
class tx_t3lib_mail_hooks {
|
||
|
||
/** @var $mailerObject t3lib_mail_Mailer */
|
||
protected $mailerObject;
|
||
|
||
/** @var $messageObject Swift_Message */
|
||
protected $messageObject;
|
||
|
||
/** @var $messageHeaders Swift_Mime_HeaderSet */
|
||
protected $messageHeaders;
|
||
|
||
/**
|
||
* @param array $parameters Array with keys: 'to', 'subject', 'messageBody', 'additionalHeaders', 'additionalParameters'
|
||
* @param bool $fakeSending If set fake sending a mail
|
||
* @throws t3lib_exception
|
||
* @return bool
|
||
*/
|
||
public function sendMail(array $parameters = array(), $fakeSending = FALSE) {
|
||
|
||
// report success for fake sending
|
||
if ($fakeSending === TRUE) {
|
||
return TRUE;
|
||
}
|
||
// create mailer object
|
||
$this->mailerObject = t3lib_div::makeInstance('t3lib_mail_Mailer');
|
||
|
||
// create message object
|
||
$this->messageObject = Swift_Message::newInstance($parameters['subject'], $parameters['messageBody']);
|
||
$this->messageObject->setTo($parameters['to']);
|
||
// handle additional headers
|
||
$headers = t3lib_div::trimExplode(LF, $parameters['additionalHeaders'], TRUE);
|
||
$this->messageHeaders = $this->messageObject->getHeaders();
|
||
foreach ($headers as $header) {
|
||
list($headerName, $headerValue) = t3lib_div::trimExplode(':', $header, FALSE, 2);
|
||
$this->setHeader($headerName, $headerValue);
|
||
}
|
||
// handle additional parameters (force return path)
|
||
if (preg_match('/-f\s*(\S*?)/', $parameters['additionalParameters'], $matches)) {
|
||
$this->messageObject->setReturnPath($this->unEscapeShellArg($matches[1]));
|
||
}
|
||
// handle from:
|
||
$from = $this->messageObject->getFrom();
|
||
if (count($from) > 0) {
|
||
reset($from);
|
||
list($fromAddress, $fromName) = each($from);
|
||
} else {
|
||
$fromAddress = $this->messageObject->getReturnPath();
|
||
$fromName = $fromAddress;
|
||
}
|
||
if (strlen($fromAddress) == 0) {
|
||
$fromAddress = 'no-reply@example.org';
|
||
$fromName = 'TYPO3 Installation';
|
||
}
|
||
$this->messageObject->setFrom(array($fromAddress => $fromName));
|
||
// send mail
|
||
$result = $this->mailerObject->send($this->messageObject);
|
||
|
||
// report success/failure
|
||
return (bool) $result;
|
||
}
|
||
|
||
/**
|
||
* Tries to undo the action by escapeshellarg()
|
||
*
|
||
* @param $escapedString String escaped by escapeshellarg()
|
||
* @return string String with escapeshellarg() action undone as best as possible
|
||
*/
|
||
protected function unEscapeShellArg($escapedString) {
|
||
if (TYPO3_OS === 'WIN') {
|
||
// on Windows double quotes are used and % signs are replaced by spaces
|
||
if (preg_match('/^"([^"]*)"$/', trim($escapedString), $matches)) {
|
||
$result = str_replace('\"', '"', $matches[1]);
|
||
// % signs are replaced with spaces, so they can't be recovered
|
||
}
|
||
} else {
|
||
// on Unix-like systems single quotes are escaped
|
||
if (preg_match('/^\'([^' . preg_quote('\'') . ']*)\'$/', trim($escapedString), $matches)) {
|
||
$result = str_replace('\\\'', '\'', $matches[1]);
|
||
}
|
||
}
|
||
return $result;
|
||
}
|
||
|
||
/**
|
||
* Handles setting and replacing of mail headers
|
||
*
|
||
* @param $headerName Name of header
|
||
* @param $headerValue Value of header
|
||
* @return void
|
||
*/
|
||
protected function setHeader($headerName, $headerValue) {
|
||
if ($this->messageHeaders->has($headerName)) {
|
||
$header = $this->messageHeaders->get($headerName);
|
||
$headerType = $header->getFieldType();
|
||
switch ($headerType) {
|
||
case Swift_Mime_Header::TYPE_TEXT:
|
||
$header->setValue($headerValue);
|
||
break;
|
||
case Swift_Mime_Header::TYPE_PARAMETERIZED:
|
||
$header->setValue($headerValue);
|
||
break;
|
||
case Swift_Mime_Header::TYPE_MAILBOX:
|
||
// mailbox headers look like:
|
||
// name <email@example.org>, othermail@example.org, ...
|
||
// pattern matches cases with and without name
|
||
// comma is added to match each item in a comma separated list
|
||
preg_match_all('/,\s*([^<]+)(<([^>]*?)>)?/', ', ' . $headerValue, $addresses, PREG_SET_ORDER);
|
||
$addressList = array();
|
||
foreach ($addresses as $address) {
|
||
if (!$address[2]) {
|
||
// item with name found ( name <email@example.org> )
|
||
if (t3lib_div::validEmail($address[1])) {
|
||
$addressList[] = $address[1];
|
||
}
|
||
} else {
|
||
// item without name found ( email@example.org )
|
||
if (t3lib_div::validEmail($address[3])) {
|
||
$addressList[$address[3]] = $address[1];
|
||
}
|
||
}
|
||
}
|
||
if (count($addressList) > 0) {
|
||
$header->setNameAddresses($addressList);
|
||
}
|
||
break;
|
||
case Swift_Mime_Header::TYPE_DATE:
|
||
$header->setTimeStamp(strtotime($headerValue));
|
||
break;
|
||
case Swift_Mime_Header::TYPE_ID:
|
||
// remove '<' and '>' from ID headers
|
||
$header->setId(trim($headerValue, '<>'));
|
||
break;
|
||
case Swift_Mime_Header::TYPE_PATH:
|
||
$header->setAddress($headerValue);
|
||
break;
|
||
}
|
||
// change value
|
||
} else {
|
||
switch ($headerName) {
|
||
// mailbox headers
|
||
case 'From':
|
||
case 'To':
|
||
case 'Cc':
|
||
case 'Bcc':
|
||
case 'Reply-To':
|
||
case 'Sender':
|
||
// mailbox headers look like:
|
||
// name <email@example.org>, othermail@example.org, ...
|
||
// pattern matches cases with and without name
|
||
// comma is added to match each item in a comma separated list
|
||
preg_match_all('/,\s*(.*?)(<([^>]*?)>)?/', ', ' . $headerValue, $addresses, PREG_SET_ORDER);
|
||
$addressList = array();
|
||
foreach ($addresses as $address) {
|
||
if ($address[2]) {
|
||
// item with name found ( name <email@example.org> )
|
||
if (t3lib_div::validEmail($address[1])) {
|
||
$addressList[] = $address[1];
|
||
}
|
||
} else {
|
||
// item without name found ( email@example.org )
|
||
if (t3lib_div::validEmail($address[3])) {
|
||
$addressList[$address[3]] = $address[1];
|
||
}
|
||
}
|
||
}
|
||
if (count($addressList) > 0) {
|
||
$header->addMailboxHeader($headerName, $addressList);
|
||
}
|
||
break;
|
||
// date headers
|
||
case 'Date':
|
||
$this->messageHeaders->addDateHeader($headerName, strtotime($headerValue));
|
||
break;
|
||
// ID headers
|
||
case 'Message-ID':
|
||
// remove '<' and '>' from ID headers
|
||
$this->messageHeaders->addIdHeader($headerName, trim($headerValue, '<>'));
|
||
// path headers
|
||
case 'Return-Path':
|
||
$this->messageHeaders->addPathHeader($headerName, $headerValue);
|
||
break;
|
||
// parameterized headers
|
||
case 'Content-Type':
|
||
case 'Content-Disposition':
|
||
$this->messageHeaders->addParameterizedHeader($headerName, $headerValue);
|
||
break;
|
||
// text headers
|
||
default:
|
||
$this->messageHeaders->addTextheader($headerName, $headerValue);
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
t3lib/utility/class.t3lib_utility_mail.php (working copy) | ||
---|---|---|
'additionalParameters' => $additionalParameters,
|
||
);
|
||
$fakeThis = FALSE;
|
||
foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/utility/class.t3lib_utility_mail.php']['substituteMailDelivery'] as $hookMethod) {
|
||
$success = $success && t3lib_div::callUserFunction($hookMethod, $parameters, $fakeThis);
|
||
foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/utility/class.t3lib_utility_mail.php']['substituteMailDelivery'] as $hookSubscriber) {
|
||
$hookSubscriberContainsArrow = strpos($hookSubscriber, '->');
|
||
if ($hookSubscriberContainsArrow !== FALSE) {
|
||
// deprecated, remove in TYPO3 4.7
|
||
t3lib_div::deprecationLog(
|
||
'The usage of user function notation for the substituteMailDelivery hook is deprecated,
|
||
use the t3lib_mail_MailerAdapter interface instead.'
|
||
);
|
||
$success = $success && t3lib_div::callUserFunction($hookSubscriber, $parameters, $fakeThis);
|
||
} else {
|
||
$mailerAdapter = t3lib_div::makeInstance($hookSubscriber);
|
||
if ($mailerAdapter instanceof t3lib_mail_MailerAdapter) {
|
||
$success = $success && $mailerAdapter->mail($to, $subject, $messageBody, $additionalHeaders, $additionalParameters, $fakeThis);
|
||
} else {
|
||
throw new RuntimeException(
|
||
$hookSubscriber . ' is not an implementation of t3lib_mail_MailerAdapter,
|
||
but must implement that interface to be used in the substituteMailDelivery hook.',
|
||
1294062286
|
||
);
|
||
}
|
||
}
|
||
}
|
||
} else {
|
||
if (t3lib_utility_PhpOptions::isSafeModeEnabled() && !is_null($additionalParameters)) {
|