[BUGFIX] Handling file upload fields is broken
[Packages/TYPO3.CMS.git] / typo3 / sysext / form / Classes / System / Postprocessor / Mail.php
1 <?php
2 /***************************************************************
3 * Copyright notice
4 *
5 * (c) 2011 Patrick Broens <patrick@patrickbroens.nl>
6 * All rights reserved
7 *
8 * This script is part of the TYPO3 project. The TYPO3 project is
9 * free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * The GNU General Public License can be found at
15 * http://www.gnu.org/copyleft/gpl.html.
16 *
17 * This script is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * This copyright notice MUST APPEAR in all copies of the script!
23 ***************************************************************/
24
25 /**
26 * The mail post processor
27 *
28 * @author Patrick Broens <patrick@patrickbroens.nl>
29 * @package TYPO3
30 * @subpackage form
31 */
32 class tx_form_System_Postprocessor_Mail {
33 /**
34 * @var tx_form_Domain_Model_Form
35 */
36 protected $form;
37
38 /**
39 * @var array
40 */
41 protected $typoScript;
42
43 /**
44 * @var t3lib_mail_Message
45 */
46 protected $mailMessage;
47
48 /**
49 * @var tx_form_System_Request
50 */
51 protected $requestHandler;
52
53 /**
54 * @var array
55 */
56 protected $dirtyHeaders = array();
57
58 /**
59 * Constructor
60 *
61 * @param $form tx_form_Domain_Model_Form Form domain model
62 * @param $typoscript array Post processor TypoScript settings
63 * @return void
64 */
65 public function __construct(tx_form_Domain_Model_Form $form, array $typoScript) {
66 $this->form = $form;
67 $this->typoScript = $typoScript;
68 $this->mailMessage = t3lib_div::makeInstance('t3lib_mail_Message');
69 $this->requestHandler = t3lib_div::makeInstance('tx_form_System_Request');
70 }
71
72 /**
73 * The main method called by the post processor
74 *
75 * Configures the mail message
76 *
77 * @return string HTML message from this processor
78 */
79 public function process() {
80 $this->setReturnPath();
81 $this->setSubject();
82 $this->setFrom();
83 $this->setTo();
84 $this->setCc();
85 $this->setPriority();
86 $this->setOrganization();
87
88 // @todo The whole content rendering seems to be missing here!
89
90 $this->setHtmlContent();
91 $this->setPlainContent();
92 $this->addAttachmentsFromForm();
93 $this->send();
94
95 return $this->render();
96 }
97
98 /**
99 * Set the return-path (the bounce address) of the mail message
100 *
101 * @return void
102 */
103 protected function setReturnPath() {
104 if ($GLOBALS['TYPO3_CONF_VARS']['SYS']['forceReturnPath']) {
105 $returnPath = $GLOBALS['TYPO3_CONF_VARS']['SYS']['forceReturnPath'];
106 $this->mailMessage->setReturnPath($returnPath);
107 }
108 }
109
110 /**
111 * Sets the subject of the mail message
112 *
113 * If not configured, it will use a default setting
114 *
115 * @return void
116 */
117 protected function setSubject() {
118 if (isset($this->typoScript['subject'])) {
119 $subject = $this->typoScript['subject'];
120 } else {
121 $subject = 'Formmail on ' . t3lib_div::getIndpEnv('HTTP_HOST');
122 }
123 $subject = $this->sanitizeHeaderString($subject);
124 $this->mailMessage->setSubject($subject);
125 }
126
127 /**
128 * Sets the sender of the mail message
129 *
130 * Mostly the sender is a combination of the name and the email address
131 *
132 * @return void
133 */
134 protected function setFrom() {
135 $fromEmail = '';
136 if ($this->typoScript['senderEmail']) {
137 $fromEmail = $this->typoScript['senderEmail'];
138 } elseif ($this->requestHandler->has($this->typoScript['senderEmailField'])) {
139 $fromEmail = $this->requestHandler->get($this->typoScript['senderEmailField']);
140 } else {
141 $fromEmail = $GLOBALS['TYPO3_CONF_VARS']['MAIL']['defaultMailFromAddress'];
142 }
143 if (!t3lib_div::validEmail($fromEmail)) {
144 $fromEmail = t3lib_utility_Mail::getSystemFromAddress();
145 }
146
147 $fromName = '';
148 if ($this->typoScript['senderName']) {
149 $fromName = $this->typoScript['senderName'];
150 } elseif ($this->requestHandler->has($this->typoScript['senderNameField'])) {
151 $fromName = $this->requestHandler->get($this->typoScript['senderNameField']);
152 } else {
153 $fromName = $GLOBALS['TYPO3_CONF_VARS']['MAIL']['defaultMailFromName'];
154 }
155 $fromName = $this->sanitizeHeaderString($fromName);
156 if (preg_match('/\s|,/', $fromName) >= 1) {
157 $fromName = '"' . $fromName . '"';
158 }
159
160 $from = array($fromEmail => $fromName);
161
162 $this->mailMessage->setFrom($from);
163 }
164
165 /**
166 * Adds the receiver of the mail message when configured
167 *
168 * Checks the address if it is a valid email address
169 *
170 * @return void
171 */
172 protected function setTo() {
173 if (
174 $this->typoScript['recipientEmail'] &&
175 t3lib_div::validEmail($this->typoScript['recipientEmail'])
176 ) {
177 $this->mailMessage->setTo($this->typoScript['recipientEmail']);
178 }
179 }
180
181 /**
182 * Adds the carbon copy receiver of the mail message when configured
183 *
184 * Checks the address if it is a valid email address
185 *
186 * @return void
187 */
188 protected function setCc() {
189 if (
190 $this->typoScript['ccEmail'] &&
191 t3lib_div::validEmail($this->typoScript['ccEmail'])
192 ) {
193 $this->mailMessage->AddCc(trim($this->typoScript['ccEmail']));
194 }
195 }
196
197 /**
198 * Set the priority of the mail message
199 *
200 * When not in settings, the value will be 3. If the priority is configured,
201 * but too big, it will be set to 5, which means very low.
202 *
203 * @return void
204 */
205 protected function setPriority() {
206 $priority = 3;
207 if ($this->typoScript['priority']) {
208 $priority = t3lib_utility_Math::forceIntegerInRange($this->typoScript['priority'], 1, 5);
209 }
210 $this->mailMessage->setPriority($priority);
211 }
212
213 /**
214 * Add a text header to the mail header of the type Organization
215 *
216 * Sanitizes the header string when necessary
217 *
218 * @return void
219 */
220 protected function setOrganization() {
221 if ($this->typoScript['organization']) {
222 $organization = $this->typoScript['organization'];
223 $organization = $this->sanitizeHeaderString($organization);
224 $this->mailMessage->getHeaders()->addTextHeader('Organization', $organization);
225 }
226 }
227
228 /**
229 * Set the default character set used
230 *
231 * Respect formMailCharset if it was set, otherwise use metaCharset for mail
232 * if different from renderCharset
233 *
234 * @return void
235 */
236 protected function setCharacterSet() {
237 $characterSet = NULL;
238 if ($GLOBALS['TSFE']->config['config']['formMailCharset']) {
239 $characterSet = $GLOBALS['TSFE']->csConvObj->parse_charset($GLOBALS['TSFE']->config['config']['formMailCharset']);
240 } elseif ($GLOBALS['TSFE']->metaCharset != $GLOBALS['TSFE']->renderCharset) {
241 $characterSet = $GLOBALS['TSFE']->metaCharset;
242 }
243 if ($characterSet) {
244 $this->mailMessage->setCharset($characterSet);
245 }
246 }
247
248 /**
249 * Add the HTML content
250 *
251 * Add a MimePart of the type text/html to the message.
252 *
253 * @return void
254 */
255 protected function setHtmlContent() {
256 /** @var $view tx_form_View_Mail_Html */
257 $view = t3lib_div::makeInstance(
258 'tx_form_View_Mail_Html',
259 $this->form,
260 $this->typoScript
261 );
262 $htmlContent = $view->get();
263 $this->mailMessage->setBody($htmlContent, 'text/html');
264 }
265
266 /**
267 * Add the plain content
268 *
269 * Add a MimePart of the type text/plain to the message.
270 *
271 * @return void
272 */
273 protected function setPlainContent() {
274 /** @var $view tx_form_View_Mail_Plain */
275 $view = t3lib_div::makeInstance(
276 'tx_form_View_Mail_Plain',
277 $this->form
278 );
279 $plainContent = $view->render();
280 $this->mailMessage->addPart($plainContent, 'text/plain');
281 }
282
283 /**
284 * Sends the mail.
285 * Sending the mail requires the recipient and message to be set.
286 *
287 * @return void
288 */
289 protected function send() {
290 if ($this->mailMessage->getTo() && $this->mailMessage->getBody()) {
291 $this->mailMessage->send();
292 }
293 }
294
295 /**
296 * Render the message after trying to send the mail
297 *
298 * @return string HTML message from the mail view
299 */
300 protected function render() {
301 /** @var $view tx_form_View_Mail */
302 $view = t3lib_div::makeInstance(
303 'tx_form_View_Mail',
304 $this->mailMessage,
305 $this->typoScript
306 );
307
308 return $view->render();
309 }
310
311 /**
312 * Checks string for suspicious characters
313 *
314 * @param string String to check
315 * @return string Valid or empty string
316 */
317 protected function sanitizeHeaderString($string) {
318 $pattern = '/[\r\n\f\e]/';
319 if (preg_match($pattern, $string) > 0) {
320 $this->dirtyHeaders[] = $string;
321 $string = '';
322 }
323 return $string;
324 }
325
326 /**
327 * Add attachments when uploaded
328 *
329 * @return void
330 */
331 protected function addAttachmentsFromForm() {
332 $formElements = $this->form->getElements();
333 $values = $this->requestHandler->getByMethod();
334 $this->addAttachmentsFromElements($formElements, $values);
335 }
336
337 /**
338 * Loop through all elements and attach the file when the element
339 * is a fileupload
340 *
341 * @param array $elements
342 * @param array $submittedValues
343 * @return void
344 */
345 protected function addAttachmentsFromElements($elements, $submittedValues) {
346 /** @var $element tx_form_Domain_Model_Element_Abstract */
347 foreach ($elements as $element) {
348 if (is_a($element, 'tx_form_Domain_Model_Element_Container')) {
349 $this->addAttachmentsFromElements($element->getElements(), $submittedValues);
350 continue;
351 }
352 if (is_a($element, 'tx_form_Domain_Model_Element_Fileupload')) {
353 $elementName = $element->getName();
354 if (is_array($submittedValues[$elementName]) && isset($submittedValues[$elementName]['tempFilename'])) {
355 $filename = $submittedValues[$elementName]['tempFilename'];
356 if (is_file($filename) && t3lib_div::isAllowedAbsPath($filename)) {
357 $this->mailMessage->attach(
358 Swift_Attachment::fromPath($filename)->setFilename($submittedValues[$elementName]['originalFilename'])
359 );
360 }
361 }
362 }
363 }
364 }
365 }
366 ?>