Skip to content

Commit

Permalink
[FEATURE] Allow setting a default replyTo-email-address
Browse files Browse the repository at this point in the history
If no other email-address is set as reply-to use this address
as default. This is similar to the existing defaultMailFromAddress.

Change-Id: Iabdf282203c1989036867a6c97b9cbe329e61f60
Resolves: #78332
Releases: master
Reviewed-on: https://review.typo3.org/50263
Tested-by: TYPO3com <no-reply@typo3.com>
Reviewed-by: Mathias Schreiber <mathias.schreiber@typo3.com>
Tested-by: Mathias Schreiber <mathias.schreiber@typo3.com>
Reviewed-by: Benni Mack <benni@typo3.org>
Tested-by: Benni Mack <benni@typo3.org>
  • Loading branch information
neufeind authored and bmack committed Feb 10, 2018
1 parent f8fe8cc commit 0059eed
Show file tree
Hide file tree
Showing 6 changed files with 122 additions and 8 deletions.
6 changes: 6 additions & 0 deletions typo3/sysext/core/Classes/Mail/MailMessage.php
Expand Up @@ -63,6 +63,12 @@ public function send()
if (empty($this->getFrom())) {
$this->setFrom(MailUtility::getSystemFrom());
}
if (empty($this->getReplyTo())) {
$replyTo = MailUtility::getSystemReplyTo();
if (!empty($replyTo)) {
$this->setReplyTo($replyTo);
}
}
$this->initializeMailer();
$this->sent = true;
$this->getHeaders()->addTextHeader('X-Mailer', $this->mailerHeader);
Expand Down
24 changes: 24 additions & 0 deletions typo3/sysext/core/Classes/Utility/MailUtility.php
Expand Up @@ -114,6 +114,30 @@ public static function getSystemFromAddress()
return $address;
}

/**
* Gets a default "reply-to" for mail messages (email and name).
*
* Ready to be passed to $mail->setReplyTo()
*
* @return array List of email-addresses. Specifying a realname can be done in the form of "replyToName <replyTo@example.com>".
*/
public static function getSystemReplyTo(): array
{
$mailConfiguration = $GLOBALS['TYPO3_CONF_VARS']['MAIL'];
$replyToAddress = $mailConfiguration['defaultMailReplyToAddress'];
if (empty($replyToAddress) || !GeneralUtility::validEmail($replyToAddress)) {
return [];
}

if (!empty($mailConfiguration['defaultMailReplyToName'])) {
$replyTo = [$replyToAddress => $mailConfiguration['defaultMailReplyToName']];
} else {
$replyTo = [$replyToAddress];
}

return $replyTo;
}

/**
* Breaks up a single line of text for emails
* Words - longer than $lineWidth - will not be split into parts
Expand Down
4 changes: 3 additions & 1 deletion typo3/sysext/core/Configuration/DefaultConfiguration.php
Expand Up @@ -1055,7 +1055,9 @@
'transport_sendmail_command' => '',
'transport_mbox_file' => '',
'defaultMailFromAddress' => '',
'defaultMailFromName' => ''
'defaultMailFromName' => '',
'defaultMailReplyToAddress' => '',
'defaultMailReplyToName' => '',
],
'HTTP' => [ // HTTP configuration to tune how TYPO3 behaves on HTTP requests made by TYPO3. Have a look at http://docs.guzzlephp.org/en/latest/request-options.html for some background information on those settings.
'allow_redirects' => [ // Mixed, set to false if you want to allow redirects, or use it as an array to add more values,
Expand Down
Expand Up @@ -484,10 +484,16 @@ MAIL:
description: '<em>only with transport=mbox</em>: The file where to write the mails into. This file will be conforming the mbox format described in RFC 4155. It is a simple text file with a concatenation of all mails. Path must be absolute.'
defaultMailFromAddress:
type: text
description: 'This default email address is used when no other "from" address is set for a TYPO3-generated email. You can specify an email address only (ex. info@example.org).'
description: 'This default email address is used when no other "from" address is set for a TYPO3-generated email. You can specify an email address only (eg. info@example.org).'
defaultMailFromName:
type: text
description: 'This default name is used when no other "from" name is set for a TYPO3-generated email.'
defaultMailReplyToAddress:
type: text
description: 'This default email address is used when no other "reply-to" address is set for a TYPO3-generated email. You can specify an email address only (eg. info@example.org).'
defaultMailReplyToName:
type: text
description: 'This default name is used when no other "reply-to" name is set for a TYPO3-generated email.'
HTTP:
type: container
items:
Expand Down
@@ -0,0 +1,36 @@
.. include:: ../../Includes.txt

======================================================================================
Feature: #78332 - Allow setting a default replyTo-email-address for notification-mails
======================================================================================

See :issue:`78332`

Description
===========

Two new LocalConfiguration settings are introduced:

.. code-block:: php
$GLOBALS['TYPO3_CONF_VARS']['MAIL']['defaultMailReplyToAddress']
$GLOBALS['TYPO3_CONF_VARS']['MAIL']['defaultMailReplyToName']
Also a new function to build a mail address for SwiftMailer from these settings is introduced:

.. code-block:: php
MailUtility::getSystemReplyTo()
If no default reply-to address is set this function will return an empty array.

This function is used in :php:`ContentObjectRenderer::sendNotifyEmail()` to set a ReplyTo address in case no address was supplied in the function parameters.
In other places where notifications are sent for e.g. (failed) login attempts, reports and where the notification uses the system from address this function is also used.


Impact
======

It's now possible to set a reply-to address for notification mails from TYPO3. Extensions can also use this system reply-to address by calling :php:`MailUtility::getSystemReplyTo()`.

.. index:: LocalConfiguration, NotScanned
52 changes: 46 additions & 6 deletions typo3/sysext/core/Tests/Unit/Utility/MailUtilityTest.php
Expand Up @@ -14,6 +14,8 @@
* The TYPO3 project - inspiring people to share!
*/

use TYPO3\CMS\Core\Utility\MailUtility;

/**
* Testcase for the \TYPO3\CMS\Core\Utility\MailUtility class.
*/
Expand All @@ -40,7 +42,7 @@ protected function tearDown()
*/
public function breakLinesForEmailReturnsEmptyStringIfEmptryStringIsGiven()
{
$this->assertEmpty(\TYPO3\CMS\Core\Utility\MailUtility::breakLinesForEmail(''));
$this->assertEmpty(MailUtility::breakLinesForEmail(''));
}

/**
Expand All @@ -51,7 +53,7 @@ public function breakLinesForEmailReturnsOneLineIfCharWithIsNotExceeded()
$newlineChar = LF;
$lineWidth = 76;
$str = 'This text is not longer than 76 chars and therefore will not be broken.';
$returnString = \TYPO3\CMS\Core\Utility\MailUtility::breakLinesForEmail($str, $newlineChar, $lineWidth);
$returnString = MailUtility::breakLinesForEmail($str, $newlineChar, $lineWidth);
$this->assertEquals(1, count(explode($newlineChar, $returnString)));
}

Expand All @@ -63,7 +65,7 @@ public function breakLinesForEmailBreaksTextIfCharWithIsExceeded()
$newlineChar = LF;
$lineWidth = 50;
$str = 'This text is longer than 50 chars and therefore will be broken.';
$returnString = \TYPO3\CMS\Core\Utility\MailUtility::breakLinesForEmail($str, $newlineChar, $lineWidth);
$returnString = MailUtility::breakLinesForEmail($str, $newlineChar, $lineWidth);
$this->assertEquals(2, count(explode($newlineChar, $returnString)));
}

Expand All @@ -76,7 +78,7 @@ public function breakLinesForEmailBreaksTextWithNoSpaceFoundBeforeLimit()
$lineWidth = 10;
// first space after 20 chars (more than $lineWidth)
$str = 'abcdefghijklmnopqrst uvwxyz 123456';
$returnString = \TYPO3\CMS\Core\Utility\MailUtility::breakLinesForEmail($str, $newlineChar, $lineWidth);
$returnString = MailUtility::breakLinesForEmail($str, $newlineChar, $lineWidth);
$this->assertEquals($returnString, 'abcdefghijklmnopqrst' . LF . 'uvwxyz' . LF . '123456');
}

Expand All @@ -86,7 +88,7 @@ public function breakLinesForEmailBreaksTextWithNoSpaceFoundBeforeLimit()
public function breakLinesForEmailBreaksTextIfLineIsLongerThanTheLineWidth()
{
$str = 'Mein Link auf eine News (Link: http://zzzzzzzzzzzzz.xxxxxxxxx.de/index.php?id=10&tx_ttnews%5Btt_news%5D=1&cHash=66f5af320da29b7ae1cda49047ca7358)';
$returnString = \TYPO3\CMS\Core\Utility\MailUtility::breakLinesForEmail($str);
$returnString = MailUtility::breakLinesForEmail($str);
$this->assertEquals($returnString, 'Mein Link auf eine News (Link:' . LF . 'http://zzzzzzzzzzzzz.xxxxxxxxx.de/index.php?id=10&tx_ttnews%5Btt_news%5D=1&cHash=66f5af320da29b7ae1cda49047ca7358)');
}

Expand Down Expand Up @@ -123,7 +125,45 @@ public function parseAddressesProvider()
*/
public function parseAddressesTest($source, $addressList)
{
$returnArray = \TYPO3\CMS\Core\Utility\MailUtility::parseAddresses($source);
$returnArray = MailUtility::parseAddresses($source);
$this->assertEquals($addressList, $returnArray);
}

/**
* @return array
*/
public function replyToProvider(): array
{
return [
'only address' => [
['defaultMailReplyToAddress' => 'noreply@example.org', 'defaultMailReplyToName' => ''],
['noreply@example.org'],
],
'name and address' => [
['defaultMailReplyToAddress' => 'noreply@example.org', 'defaultMailReplyToName' => 'John Doe'],
['noreply@example.org' => 'John Doe'],
],
'no address' => [
['defaultMailReplyToAddress' => '', 'defaultMailReplyToName' => ''],
[],
],
'invalid address' => [
['defaultMailReplyToAddress' => 'foo', 'defaultMailReplyToName' => ''],
[],
],
];
}

/**
* @test
* @dataProvider replyToProvider
* @param array $configuration
* @param array $expectedReplyTo
*/
public function getSystemReplyToTest(array $configuration, array $expectedReplyTo)
{
$GLOBALS['TYPO3_CONF_VARS']['MAIL'] = $configuration;
$returnArray = MailUtility::getSystemReplyTo();
$this->assertSame($expectedReplyTo, $returnArray);
}
}

0 comments on commit 0059eed

Please sign in to comment.