[BUGFIX] Sending fails on multiple email-addresses 63/19463/2
authorStefan Neufeind <typo3.neufeind@speedpartner.de>
Sun, 13 Jan 2013 13:57:44 +0000 (14:57 +0100)
committerJigal van Hemert <jigal@xs4all.nl>
Sun, 31 Mar 2013 17:05:45 +0000 (19:05 +0200)
Specifying multiple recipients (To or CC) for emails
leads to an error upon form-submit without further explanation.
This patch implements validation for multiple email addresses of
which only the valid ones are then returned.
The sending-API can already handle multiple recipients.

Change-Id: Ia0a947e1ee7b4d9b352a297840b68ff489f71375
Fixes: #44485
Releases: 4.7, 6.0, 6.1
Reviewed-on: https://review.typo3.org/19463
Reviewed-by: Jigal van Hemert
Tested-by: Jigal van Hemert
typo3/sysext/form/Classes/PostProcess/MailPostProcessor.php
typo3/sysext/form/Tests/Unit/PostProcess/MailPostProcessorTest.php [new file with mode: 0644]

index c90c8a0..2b07604 100644 (file)
@@ -145,6 +145,36 @@ class MailPostProcessor implements \TYPO3\CMS\Form\PostProcess\PostProcessorInte
        }
 
        /**
+        * Filter input-string for valid email addresses
+        *
+        * @param string $emails If this is a string, it will be checked for one or more valid email addresses.
+        * @return array List of valid email addresses
+        */
+       protected function filterValidEmails($emails) {
+               if (!is_string($emails)) {
+                       // No valid addresses - empty list
+                       return array();
+               }
+
+               /** @var $addressParser \TYPO3\CMS\Core\Mail\Rfc822AddressesParser */
+               $addressParser = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Mail\\Rfc822AddressesParser', $emails);
+               $addresses = $addressParser->parseAddressList();
+
+               $validEmails = array();
+               foreach ($addresses as $address) {
+                       $fullAddress = $address->mailbox . '@' . $address->host;
+                       if (\TYPO3\CMS\Core\Utility\GeneralUtility::validEmail($fullAddress)) {
+                               if ($address->personal) {
+                                       $validEmails[$fullAddress] = $address->personal;
+                               } else {
+                                       $validEmails[] = $fullAddress;
+                               }
+                       }
+               }
+               return $validEmails;
+       }
+
+       /**
         * Adds the receiver of the mail message when configured
         *
         * Checks the address if it is a valid email address
@@ -152,8 +182,9 @@ class MailPostProcessor implements \TYPO3\CMS\Form\PostProcess\PostProcessorInte
         * @return void
         */
        protected function setTo() {
-               if ($this->typoScript['recipientEmail'] && \TYPO3\CMS\Core\Utility\GeneralUtility::validEmail($this->typoScript['recipientEmail'])) {
-                       $this->mailMessage->setTo($this->typoScript['recipientEmail']);
+               $validEmails = $this->filterValidEmails($this->typoScript['recipientEmail']);
+               if (count($validEmails)) {
+                       $this->mailMessage->setTo($validEmails);
                }
        }
 
@@ -165,8 +196,9 @@ class MailPostProcessor implements \TYPO3\CMS\Form\PostProcess\PostProcessorInte
         * @return void
         */
        protected function setCc() {
-               if ($this->typoScript['ccEmail'] && \TYPO3\CMS\Core\Utility\GeneralUtility::validEmail($this->typoScript['ccEmail'])) {
-                       $this->mailMessage->AddCc(trim($this->typoScript['ccEmail']));
+               $validEmails = $this->filterValidEmails($this->typoScript['ccEmail']);
+               if (count($validEmails)) {
+                       $this->mailMessage->setCc($validEmails);
                }
        }
 
diff --git a/typo3/sysext/form/Tests/Unit/PostProcess/MailPostProcessorTest.php b/typo3/sysext/form/Tests/Unit/PostProcess/MailPostProcessorTest.php
new file mode 100644 (file)
index 0000000..3c85821
--- /dev/null
@@ -0,0 +1,119 @@
+<?php
+namespace TYPO3\CMS\Form\Tests\Unit\PostProcess;
+
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2013 Stefan Neufeind <info (at) speedpartner.de>
+ *
+ *  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.
+ *
+ *  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!
+ ***************************************************************/
+
+/**
+ * Test case
+ */
+class MailPostProcessorTest extends \TYPO3\CMS\Extbase\Tests\Unit\BaseTestCase {
+
+       /**
+        * @var \TYPO3\CMS\Form\PostProcess\MailPostProcessor
+        */
+       protected $mailPostProcessor;
+
+       /**
+        * Set up
+        *
+        * @return void
+        */
+       public function setUp() {
+               $this->mailPostProcessor = $this->getAccessibleMock(
+                       'TYPO3\CMS\Form\PostProcess\MailPostProcessor',
+                       array('dummy'),
+                       array(),
+                       '',
+                       FALSE
+               );
+       }
+
+       /**
+        * Tear down
+        *
+        * @return void
+        */
+       protected function tearDown() {
+               unset($this->mailPostProcessor);
+       }
+
+       /**
+        * Data provider for filterValidEmailsReturnsOnlyValidAddresses
+        *
+        * @return array input string, expected return array
+        * @TODO: Add a umlaut domain test case
+        */
+       public function filterValidEmailsProvider() {
+               return array(
+                       'empty string' => array(
+                               '',
+                               array(),
+                       ),
+                       'string not representing an email' => array(
+                               'notAnAddress',
+                               array(),
+                       ),
+                       'simple single valid address' => array(
+                               'someone@example.com',
+                               array(
+                                       'someone@example.com',
+                               ),
+                       ),
+                       'multiple valid simple addresses' => array(
+                               'someone@example.com, foo@bar.com',
+                               array(
+                                       'someone@example.com',
+                                       'foo@bar.com',
+                               ),
+                       ),
+                       'multiple addresses with personal part' => array(
+                               'Foo <foo@example.com>, <bar@example.com>, "Foo, bar" <foo.bar@example.com>',
+                               array(
+                                       'bar@example.com',
+                                       'foo@example.com' => 'Foo',
+                                       'foo.bar@example.com' => '"Foo, bar"',
+                               ),
+                       ),
+                       'list with invalid addresses is filtered' => array(
+                               'invalid, @invalid, someone@example.com',
+                               array(
+                                       'someone@example.com',
+                               ),
+                       ),
+               );
+       }
+
+       /**
+        * @test
+        * @dataProvider filterValidEmailsProvider
+        */
+       public function filterValidEmailsReturnsOnlyValidAddresses($input, $expected) {
+               $actualResult = $this->mailPostProcessor->_call('filterValidEmails', $input);
+               $this->assertEquals($expected, $actualResult);
+       }
+
+}
+
+?>
\ No newline at end of file