0ea4e4fdea8eac0424974b0adb5c070091391231
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Classes / Utility / MailUtility.php
1 <?php
2 namespace TYPO3\CMS\Core\Utility;
3
4 /**
5 * This file is part of the TYPO3 CMS project.
6 *
7 * It is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU General Public License, either version 2
9 * of the License, or any later version.
10 *
11 * For the full copyright and license information, please read the
12 * LICENSE.txt file that was distributed with this source code.
13 *
14 * The TYPO3 project - inspiring people to share!
15 */
16
17 use TYPO3\CMS\Core\Utility\GeneralUtility;
18
19 /**
20 * Class to handle mail specific functionality
21 *
22 * @author Tolleiv Nietsch <nietsch@aoemedia.de>
23 */
24 class MailUtility {
25
26 /**
27 * Proxy for the PHP mail() function. Adds possibility to hook in and send the mails in a different way.
28 * The hook can be used by adding function to the configuration array:
29 * $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/utility/class.t3lib_utility_mail.php']['substituteMailDelivery']
30 *
31 * @param string $to Email address to send to.
32 * @param string $subject Subject line, non-encoded. (see PHP function mail())
33 * @param string $messageBody Message content, non-encoded. (see PHP function mail())
34 * @param string $additionalHeaders Additional headers for the mail (see PHP function mail())
35 * @param string $additionalParameters Additional flags for the sending mail tool (see PHP function mail())
36 * @return boolean Indicates whether the mail has been sent or not
37 * @see PHP function mail() []
38 * @link http://www.php.net/manual/en/function.mail.php
39 * @deprecated since 6.1, will be removed two versions later - Use \TYPO3\CMS\Core\Mail\Mailer instead
40 */
41 static public function mail($to, $subject, $messageBody, $additionalHeaders = NULL, $additionalParameters = NULL) {
42 GeneralUtility::logDeprecatedFunction();
43 $success = TRUE;
44 // If the mail does not have a From: header, fall back to the default in TYPO3_CONF_VARS.
45 if (!preg_match('/^From:/im', $additionalHeaders) && $GLOBALS['TYPO3_CONF_VARS']['MAIL']['defaultMailFromAddress']) {
46 if (!is_null($additionalHeaders) && substr($additionalHeaders, -1) != LF) {
47 $additionalHeaders .= LF;
48 }
49 if ($GLOBALS['TYPO3_CONF_VARS']['MAIL']['defaultMailFromName']) {
50 $additionalHeaders .= 'From: "' . $GLOBALS['TYPO3_CONF_VARS']['MAIL']['defaultMailFromName'] . '" <' . $GLOBALS['TYPO3_CONF_VARS']['MAIL']['defaultMailFromAddress'] . '>';
51 } else {
52 $additionalHeaders .= 'From: ' . $GLOBALS['TYPO3_CONF_VARS']['MAIL']['defaultMailFromAddress'];
53 }
54 }
55 if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/utility/class.t3lib_utility_mail.php']['substituteMailDelivery'])) {
56 $parameters = array(
57 'to' => $to,
58 'subject' => $subject,
59 'messageBody' => $messageBody,
60 'additionalHeaders' => $additionalHeaders,
61 'additionalParameters' => $additionalParameters
62 );
63 $fakeThis = FALSE;
64 foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/utility/class.t3lib_utility_mail.php']['substituteMailDelivery'] as $hookSubscriber) {
65 $hookSubscriberContainsArrow = strpos($hookSubscriber, '->');
66 if ($hookSubscriberContainsArrow !== FALSE) {
67 throw new \RuntimeException($hookSubscriber . ' is an invalid hook implementation. Please consider using an implementation of TYPO3\\CMS\\Core\\Mail\\MailerAdapter.', 1322287600);
68 } else {
69 $mailerAdapter = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance($hookSubscriber);
70 if ($mailerAdapter instanceof \TYPO3\CMS\Core\Mail\MailerAdapterInterface) {
71 $success = $success && $mailerAdapter->mail($to, $subject, $messageBody, $additionalHeaders, $additionalParameters, $fakeThis);
72 } else {
73 throw new \RuntimeException($hookSubscriber . ' is not an implementation of TYPO3\\CMS\\Core\\Mail\\MailerAdapter,
74 but must implement that interface to be used in the substituteMailDelivery hook.', 1294062286);
75 }
76 }
77 }
78 } else {
79 if (is_null($additionalParameters)) {
80 $success = @mail($to, $subject, $messageBody, $additionalHeaders);
81 } else {
82 $success = @mail($to, $subject, $messageBody, $additionalHeaders, $additionalParameters);
83 }
84 }
85 if (!$success) {
86 \TYPO3\CMS\Core\Utility\GeneralUtility::sysLog('Mail to "' . $to . '" could not be sent (Subject: "' . $subject . '").', 'Core', \TYPO3\CMS\Core\Utility\GeneralUtility::SYSLOG_SEVERITY_ERROR);
87 }
88 return $success;
89 }
90
91 /**
92 * Gets a valid "from" for mail messages (email and name).
93 *
94 * Ready to be passed to $mail->setFrom()
95 *
96 * @return array key=Valid email address which can be used as sender, value=Valid name which can be used as a sender. NULL if no address is configured
97 */
98 static public function getSystemFrom() {
99 $address = self::getSystemFromAddress();
100 $name = self::getSystemFromName();
101 if (!$address) {
102 return NULL;
103 } elseif ($name) {
104 return array($address => $name);
105 } else {
106 return array($address);
107 }
108 }
109
110 /**
111 * Creates a valid "from" name for mail messages.
112 *
113 * As configured in Install Tool.
114 *
115 * @return string The name (unquoted, unformatted). NULL if none is set
116 */
117 static public function getSystemFromName() {
118 if ($GLOBALS['TYPO3_CONF_VARS']['MAIL']['defaultMailFromName']) {
119 return $GLOBALS['TYPO3_CONF_VARS']['MAIL']['defaultMailFromName'];
120 } else {
121 return NULL;
122 }
123 }
124
125 /**
126 * Creates a valid email address for the sender of mail messages.
127 *
128 * Uses a fallback chain:
129 * $TYPO3_CONF_VARS['MAIL']['defaultMailFromAddress'] ->
130 * no-reply@FirstDomainRecordFound ->
131 * no-reply@php_uname('n') ->
132 * no-reply@example.com
133 *
134 * Ready to be passed to $mail->setFrom()
135 *
136 * @return string An email address
137 */
138 static public function getSystemFromAddress() {
139 // default, first check the localconf setting
140 $address = $GLOBALS['TYPO3_CONF_VARS']['MAIL']['defaultMailFromAddress'];
141 if (!\TYPO3\CMS\Core\Utility\GeneralUtility::validEmail($address)) {
142 // just get us a domain record we can use as the host
143 $host = '';
144 $domainRecord = $GLOBALS['TYPO3_DB']->exec_SELECTgetSingleRow('domainName', 'sys_domain', 'hidden = 0', '', 'pid ASC, sorting ASC');
145 if (!empty($domainRecord['domainName'])) {
146 $tempUrl = $domainRecord['domainName'];
147 if (!\TYPO3\CMS\Core\Utility\GeneralUtility::isFirstPartOfStr($tempUrl, 'http')) {
148 // shouldn't be the case anyways, but you never know
149 // ... there're crazy people out there
150 $tempUrl = 'http://' . $tempUrl;
151 }
152 $host = parse_url($tempUrl, PHP_URL_HOST);
153 }
154 $address = 'no-reply@' . $host;
155 if (!\TYPO3\CMS\Core\Utility\GeneralUtility::validEmail($address)) {
156 // still nothing, get host name from server
157 $address = 'no-reply@' . php_uname('n');
158 if (!\TYPO3\CMS\Core\Utility\GeneralUtility::validEmail($address)) {
159 // if everything fails use a dummy address
160 $address = 'no-reply@example.com';
161 }
162 }
163 }
164 return $address;
165 }
166
167 /**
168 * Breaks up a single line of text for emails
169 * Words - longer than $lineWidth - will not be split into parts
170 *
171 * @param string $str The string to break up
172 * @param string $newlineChar The string to implode the broken lines with (default/typically \n)
173 * @param integer $lineWidth The line width
174 * @return string Reformated text
175 */
176 static public function breakLinesForEmail($str, $newlineChar = LF, $lineWidth = 76) {
177 $lines = array();
178 $substrStart = 0;
179 while (strlen($str) > $substrStart) {
180 $substr = substr($str, $substrStart, $lineWidth);
181 // has line exceeded (reached) the maximum width?
182 if (strlen($substr) == $lineWidth) {
183 // find last space-char
184 $spacePos = strrpos(rtrim($substr), ' ');
185 // space-char found?
186 if ($spacePos !== FALSE) {
187 // take everything up to last space-char
188 $theLine = substr($substr, 0, $spacePos);
189 $substrStart++;
190 } else {
191 // search for space-char in remaining text
192 // makes this line longer than $lineWidth!
193 $afterParts = explode(' ', substr($str, $lineWidth + $substrStart), 2);
194 $theLine = $substr . $afterParts[0];
195 }
196 if (!strlen($theLine)) {
197 // prevent endless loop because of empty line
198 break;
199 }
200 } else {
201 $theLine = $substr;
202 }
203 $lines[] = trim($theLine);
204 $substrStart += strlen($theLine);
205 if (trim(substr($str, $substrStart, $lineWidth)) === '') {
206 // no more text
207 break;
208 }
209 }
210 return implode($newlineChar, $lines);
211 }
212
213 /**
214 * Parses mailbox headers and turns them into an array.
215 *
216 * Mailbox headers are a comma separated list of 'name <email@example.org>' combinations
217 * or plain email addresses (or a mix of these).
218 * The resulting array has key-value pairs where the key is either a number
219 * (no display name in the mailbox header) and the value is the email address,
220 * or the key is the email address and the value is the display name.
221 *
222 * @param string $rawAddresses Comma separated list of email addresses (optionally with display name)
223 * @return array Parsed list of addresses.
224 */
225 static public function parseAddresses($rawAddresses) {
226 /** @var $addressParser \TYPO3\CMS\Core\Mail\Rfc822AddressesParser */
227 $addressParser = GeneralUtility::makeInstance(
228 'TYPO3\\CMS\\Core\\Mail\\Rfc822AddressesParser',
229 $rawAddresses
230 );
231 $addresses = $addressParser->parseAddressList();
232 $addressList = array();
233 foreach ($addresses as $address) {
234 if ($address->mailbox === '') {
235 continue;
236 }
237 if ($address->personal) {
238 // item with name found ( name <email@example.org> )
239 $addressList[$address->mailbox . '@' . $address->host] = $address->personal;
240 } else {
241 // item without name found ( email@example.org )
242 $addressList[] = $address->mailbox . '@' . $address->host;
243 }
244 }
245 return $addressList;
246 }
247 }