From 281ad406e88d36c1492c7aefd8ef28762379f9e3 Mon Sep 17 00:00:00 2001 From: Lukas Reschke Date: Fri, 7 Apr 2017 14:51:05 +0200 Subject: [PATCH] Add support for theming Add support for theming in generated emails and simplify API Signed-off-by: Lukas Reschke --- .../lib/AppInfo/Application.php | 16 + .../lib/Controller/UsersController.php | 34 +- .../tests/Controller/UsersControllerTest.php | 238 ++----- apps/theming/lib/ThemingDefaults.php | 51 +- apps/theming/tests/ThemingDefaultsTest.php | 57 +- lib/private/Mail/EMailTemplate.php | 56 +- lib/private/Mail/IEMailTemplate.php | 25 +- lib/private/Server.php | 4 +- settings/Application.php | 23 +- settings/Controller/UsersController.php | 102 +-- settings/Mailer/NewUserMailHelper.php | 166 +++++ .../Controller/UsersControllerTest.php | 210 +----- .../Settings/Mailer/NewUserMailHelperTest.php | 639 ++++++++++++++++++ .../data/emails/new-account-email-custom.html | 187 +++++ .../data/emails/new-account-email-custom.txt | 11 + tests/data/emails/new-account-email.html | 9 +- tests/lib/Mail/EMailTemplateTest.php | 112 ++- 17 files changed, 1366 insertions(+), 574 deletions(-) create mode 100644 settings/Mailer/NewUserMailHelper.php create mode 100644 tests/Settings/Mailer/NewUserMailHelperTest.php create mode 100644 tests/data/emails/new-account-email-custom.html create mode 100644 tests/data/emails/new-account-email-custom.txt diff --git a/apps/provisioning_api/lib/AppInfo/Application.php b/apps/provisioning_api/lib/AppInfo/Application.php index 2d6a82e2ff9..fd03fd41e16 100644 --- a/apps/provisioning_api/lib/AppInfo/Application.php +++ b/apps/provisioning_api/lib/AppInfo/Application.php @@ -3,8 +3,11 @@ namespace OCA\Provisioning_API\AppInfo; use OC\AppFramework\Utility\SimpleContainer; +use OC\AppFramework\Utility\TimeFactory; +use OC\Settings\Mailer\NewUserMailHelper; use OCA\Provisioning_API\Middleware\ProvisioningApiMiddleware; use OCP\AppFramework\App; +use OCP\Util; class Application extends App { public function __construct(array $urlParams = array()) { @@ -13,6 +16,19 @@ class Application extends App { $container = $this->getContainer(); $server = $container->getServer(); + $container->registerService(NewUserMailHelper::class, function(SimpleContainer $c) use ($server) { + return new NewUserMailHelper( + $server->getThemingDefaults(), + $server->getURLGenerator(), + $server->getL10N('settings'), + $server->getMailer(), + $server->getSecureRandom(), + new TimeFactory(), + $server->getConfig(), + $server->getCrypto(), + Util::getDefaultEmailAddress('no-reply') + ); + }); $container->registerService('ProvisioningApiMiddleware', function(SimpleContainer $c) use ($server) { $user = $server->getUserManager()->get($c['UserId']); $isAdmin = $user !== null ? $server->getGroupManager()->isAdmin($user->getUID()) : false; diff --git a/apps/provisioning_api/lib/Controller/UsersController.php b/apps/provisioning_api/lib/Controller/UsersController.php index 9155d34276b..0ccbc978a69 100644 --- a/apps/provisioning_api/lib/Controller/UsersController.php +++ b/apps/provisioning_api/lib/Controller/UsersController.php @@ -30,6 +30,7 @@ namespace OCA\Provisioning_API\Controller; use OC\Accounts\AccountManager; +use OC\Settings\Mailer\NewUserMailHelper; use \OC_Helper; use OCP\AppFramework\Http\DataResponse; use OCP\AppFramework\Http\TemplateResponse; @@ -72,6 +73,8 @@ class UsersController extends OCSController { private $defaults; /** @var IFactory */ private $l10nFactory; + /** @var NewUserMailHelper */ + private $newUserMailHelper; /** * @param string $appName @@ -87,6 +90,7 @@ class UsersController extends OCSController { * @param IMailer $mailer * @param \OC_Defaults $defaults * @param IFactory $l10nFactory + * @param NewUserMailHelper $newUserMailHelper */ public function __construct($appName, IRequest $request, @@ -100,7 +104,8 @@ class UsersController extends OCSController { IURLGenerator $urlGenerator, IMailer $mailer, \OC_Defaults $defaults, - IFactory $l10nFactory) { + IFactory $l10nFactory, + NewUserMailHelper $newUserMailHelper) { parent::__construct($appName, $request); $this->userManager = $userManager; @@ -114,6 +119,7 @@ class UsersController extends OCSController { $this->mailer = $mailer; $this->defaults = $defaults; $this->l10nFactory = $l10nFactory; + $this->newUserMailHelper = $newUserMailHelper; } /** @@ -786,30 +792,10 @@ class UsersController extends OCSController { $l10n = $this->l10nFactory->get('settings', $lang); - // data for the mail template - $mailData = [ - 'username' => $username, - 'url' => $this->urlGenerator->getAbsoluteURL('/') - ]; - - // FIXME: set users language in email - $mail = new TemplateResponse('settings', 'email.new_user', $mailData, 'blank'); - $mailContent = $mail->render(); - - // FIXME: set users language in email - $mail = new TemplateResponse('settings', 'email.new_user_plain_text', $mailData, 'blank'); - $plainTextMailContent = $mail->render(); - - $subject = $l10n->t('Your %s account was created', [$this->defaults->getName()]); - try { - $message = $this->mailer->createMessage(); - $message->setTo([$email => $username]); - $message->setSubject($subject); - $message->setHtmlBody($mailContent); - $message->setPlainBody($plainTextMailContent); - $message->setFrom([$this->fromMailAddress => $this->defaults->getName()]); - $this->mailer->send($message); + $this->newUserMailHelper->setL10N($l10n); + $emailTemplate = $this->newUserMailHelper->generateTemplate($targetUser, false); + $this->newUserMailHelper->sendMail($targetUser, $emailTemplate); } catch(\Exception $e) { $this->logger->error("Can't send new user mail to $email: " . $e->getMessage(), array('app' => 'settings')); throw new OCSException('Sending email failed', 102); diff --git a/apps/provisioning_api/tests/Controller/UsersControllerTest.php b/apps/provisioning_api/tests/Controller/UsersControllerTest.php index b5b63319d35..0cbcccebf6f 100644 --- a/apps/provisioning_api/tests/Controller/UsersControllerTest.php +++ b/apps/provisioning_api/tests/Controller/UsersControllerTest.php @@ -32,6 +32,8 @@ namespace OCA\Provisioning_API\Tests\Controller; use Exception; use OC\Accounts\AccountManager; use OC\Group\Manager; +use OC\Mail\IEMailTemplate; +use OC\Settings\Mailer\NewUserMailHelper; use OC\SubAdmin; use OCA\Provisioning_API\Controller\UsersController; use OCP\AppFramework\Http\DataResponse; @@ -54,39 +56,30 @@ class UsersControllerTest extends TestCase { /** @var IUserManager|PHPUnit_Framework_MockObject_MockObject */ protected $userManager; - /** @var IConfig|PHPUnit_Framework_MockObject_MockObject */ protected $config; - /** @var Manager|PHPUnit_Framework_MockObject_MockObject */ protected $groupManager; - /** @var IUserSession|PHPUnit_Framework_MockObject_MockObject */ protected $userSession; - /** @var ILogger|PHPUnit_Framework_MockObject_MockObject */ protected $logger; - /** @var UsersController|PHPUnit_Framework_MockObject_MockObject */ protected $api; - /** @var AccountManager|PHPUnit_Framework_MockObject_MockObject */ protected $accountManager; - /** @var IRequest|PHPUnit_Framework_MockObject_MockObject */ protected $request; - - /** @var IURLGenerator | PHPUnit_Framework_MockObject_MockObject */ + /** @var IURLGenerator|PHPUnit_Framework_MockObject_MockObject */ private $urlGenerator; - - /** @var IMailer | PHPUnit_Framework_MockObject_MockObject */ + /** @var IMailer|PHPUnit_Framework_MockObject_MockObject */ private $mailer; - - /** @var \OC_Defaults | PHPUnit_Framework_MockObject_MockObject */ + /** @var \OC_Defaults|PHPUnit_Framework_MockObject_MockObject */ private $defaults; - - /** @var IFactory | PHPUnit_Framework_MockObject_MockObject */ + /** @var IFactory|PHPUnit_Framework_MockObject_MockObject */ private $l10nFactory; + /** @var NewUserMailHelper|PHPUnit_Framework_MockObject_MockObject */ + private $newUserMailHelper; protected function setUp() { parent::setUp(); @@ -102,6 +95,7 @@ class UsersControllerTest extends TestCase { $this->mailer = $this->createMock(IMailer::class); $this->defaults = $this->createMock(\OC_Defaults::class); $this->l10nFactory = $this->createMock(IFactory::class); + $this->newUserMailHelper = $this->createMock(NewUserMailHelper::class); $this->api = $this->getMockBuilder(UsersController::class) ->setConstructorArgs([ @@ -117,7 +111,8 @@ class UsersControllerTest extends TestCase { $this->urlGenerator, $this->mailer, $this->defaults, - $this->l10nFactory + $this->l10nFactory, + $this->newUserMailHelper ]) ->setMethods(['fillStorageInfo']) ->getMock(); @@ -2621,7 +2616,8 @@ class UsersControllerTest extends TestCase { $this->urlGenerator, $this->mailer, $this->defaults, - $this->l10nFactory + $this->l10nFactory, + $this->newUserMailHelper ]) ->setMethods(['getUserData']) ->getMock(); @@ -2684,7 +2680,8 @@ class UsersControllerTest extends TestCase { $this->urlGenerator, $this->mailer, $this->defaults, - $this->l10nFactory + $this->l10nFactory, + $this->newUserMailHelper ]) ->setMethods(['getUserData']) ->getMock(); @@ -2884,56 +2881,6 @@ class UsersControllerTest extends TestCase { ->expects($this->once()) ->method('getEmailAddress') ->will($this->returnValue('abc@example.org')); - $message = $this->getMockBuilder('\OC\Mail\Message') - ->disableOriginalConstructor()->getMock(); - $message - ->expects($this->at(0)) - ->method('setTo') - ->with(['abc@example.org' => 'user-id']); - $message - ->expects($this->at(1)) - ->method('setSubject') - ->with('Your account was created'); - $htmlBody = new TemplateResponse( - 'settings', - 'email.new_user', - [ - 'username' => 'user-id', - 'url' => null, - ], - 'blank' - ); - $message - ->expects($this->at(2)) - ->method('setHtmlBody') - ->with($htmlBody->render()); - $plainBody = new TemplateResponse( - 'settings', - 'email.new_user_plain_text', - [ - 'username' => 'user-id', - 'url' => null, - ], - 'blank' - ); - $message - ->expects($this->at(3)) - ->method('setPlainBody') - ->with($plainBody->render()); - $message - ->expects($this->at(4)) - ->method('setFrom') - ->with(['test@example.org' => null]); - - $this->mailer - ->expects($this->at(0)) - ->method('createMessage') - ->will($this->returnValue($message)); - $this->mailer - ->expects($this->at(1)) - ->method('send') - ->with($message); - $this->config ->expects($this->at(0)) ->method('getUserValue') @@ -2942,11 +2889,6 @@ class UsersControllerTest extends TestCase { $l10n = $this->getMockBuilder(IL10N::class) ->disableOriginalConstructor() ->getMock(); - $l10n - ->expects($this->at(0)) - ->method('t') - ->with('Your %s account was created', [null]) - ->willReturn('Your account was created'); $this->l10nFactory ->expects($this->at(0)) ->method('languageExists') @@ -2957,6 +2899,19 @@ class UsersControllerTest extends TestCase { ->method('get') ->with('settings', 'es') ->willReturn($l10n); + $emailTemplate = $this->createMock(IEMailTemplate::class); + $this->newUserMailHelper + ->expects($this->at(0)) + ->method('setL10N') + ->willReturn($l10n); + $this->newUserMailHelper + ->expects($this->at(1)) + ->method('generateTemplate') + ->willReturn($emailTemplate); + $this->newUserMailHelper + ->expects($this->at(2)) + ->method('sendMail') + ->with($targetUser, $emailTemplate); $this->api->resendWelcomeMessage('UserToGet'); } @@ -2996,56 +2951,6 @@ class UsersControllerTest extends TestCase { ->expects($this->once()) ->method('getEmailAddress') ->will($this->returnValue('abc@example.org')); - $message = $this->getMockBuilder('\OC\Mail\Message') - ->disableOriginalConstructor()->getMock(); - $message - ->expects($this->at(0)) - ->method('setTo') - ->with(['abc@example.org' => 'user-id']); - $message - ->expects($this->at(1)) - ->method('setSubject') - ->with('Your account was created'); - $htmlBody = new TemplateResponse( - 'settings', - 'email.new_user', - [ - 'username' => 'user-id', - 'url' => null, - ], - 'blank' - ); - $message - ->expects($this->at(2)) - ->method('setHtmlBody') - ->with($htmlBody->render()); - $plainBody = new TemplateResponse( - 'settings', - 'email.new_user_plain_text', - [ - 'username' => 'user-id', - 'url' => null, - ], - 'blank' - ); - $message - ->expects($this->at(3)) - ->method('setPlainBody') - ->with($plainBody->render()); - $message - ->expects($this->at(4)) - ->method('setFrom') - ->with(['test@example.org' => null]); - - $this->mailer - ->expects($this->at(0)) - ->method('createMessage') - ->will($this->returnValue($message)); - $this->mailer - ->expects($this->at(1)) - ->method('send') - ->with($message); - $this->config ->expects($this->at(0)) ->method('getUserValue') @@ -3054,11 +2959,6 @@ class UsersControllerTest extends TestCase { $l10n = $this->getMockBuilder(IL10N::class) ->disableOriginalConstructor() ->getMock(); - $l10n - ->expects($this->at(0)) - ->method('t') - ->with('Your %s account was created', [null]) - ->willReturn('Your account was created'); $this->l10nFactory ->expects($this->at(0)) ->method('languageExists') @@ -3069,6 +2969,19 @@ class UsersControllerTest extends TestCase { ->method('get') ->with('settings', 'en') ->willReturn($l10n); + $emailTemplate = $this->createMock(IEMailTemplate::class); + $this->newUserMailHelper + ->expects($this->at(0)) + ->method('setL10N') + ->willReturn($l10n); + $this->newUserMailHelper + ->expects($this->at(1)) + ->method('generateTemplate') + ->willReturn($emailTemplate); + $this->newUserMailHelper + ->expects($this->at(2)) + ->method('sendMail') + ->with($targetUser, $emailTemplate); $this->api->resendWelcomeMessage('UserToGet'); } @@ -3113,56 +3026,6 @@ class UsersControllerTest extends TestCase { ->expects($this->once()) ->method('getEmailAddress') ->will($this->returnValue('abc@example.org')); - $message = $this->getMockBuilder('\OC\Mail\Message') - ->disableOriginalConstructor()->getMock(); - $message - ->expects($this->at(0)) - ->method('setTo') - ->with(['abc@example.org' => 'user-id']); - $message - ->expects($this->at(1)) - ->method('setSubject') - ->with('Your account was created'); - $htmlBody = new TemplateResponse( - 'settings', - 'email.new_user', - [ - 'username' => 'user-id', - 'url' => null, - ], - 'blank' - ); - $message - ->expects($this->at(2)) - ->method('setHtmlBody') - ->with($htmlBody->render()); - $plainBody = new TemplateResponse( - 'settings', - 'email.new_user_plain_text', - [ - 'username' => 'user-id', - 'url' => null, - ], - 'blank' - ); - $message - ->expects($this->at(3)) - ->method('setPlainBody') - ->with($plainBody->render()); - $message - ->expects($this->at(4)) - ->method('setFrom') - ->with(['test@example.org' => null]); - - $this->mailer - ->expects($this->at(0)) - ->method('createMessage') - ->will($this->returnValue($message)); - $this->mailer - ->expects($this->at(1)) - ->method('send') - ->will($this->throwException(new \Exception())); - $this->config ->expects($this->at(0)) ->method('getUserValue') @@ -3171,11 +3034,6 @@ class UsersControllerTest extends TestCase { $l10n = $this->getMockBuilder(IL10N::class) ->disableOriginalConstructor() ->getMock(); - $l10n - ->expects($this->at(0)) - ->method('t') - ->with('Your %s account was created', [null]) - ->willReturn('Your account was created'); $this->l10nFactory ->expects($this->at(0)) ->method('languageExists') @@ -3186,6 +3044,20 @@ class UsersControllerTest extends TestCase { ->method('get') ->with('settings', 'es') ->willReturn($l10n); + $emailTemplate = $this->createMock(IEMailTemplate::class); + $this->newUserMailHelper + ->expects($this->at(0)) + ->method('setL10N') + ->willReturn($l10n); + $this->newUserMailHelper + ->expects($this->at(1)) + ->method('generateTemplate') + ->willReturn($emailTemplate); + $this->newUserMailHelper + ->expects($this->at(2)) + ->method('sendMail') + ->with($targetUser, $emailTemplate) + ->willThrowException(new \Exception()); $this->api->resendWelcomeMessage('UserToGet'); } diff --git a/apps/theming/lib/ThemingDefaults.php b/apps/theming/lib/ThemingDefaults.php index 5a863b1eb22..d4dc56d3ba9 100644 --- a/apps/theming/lib/ThemingDefaults.php +++ b/apps/theming/lib/ThemingDefaults.php @@ -1,6 +1,7 @@ + * @copyright Copyright (c) 2017 Lukas Reschke * * @license GNU AGPL version 3 or any later version * @@ -19,15 +20,14 @@ * */ - namespace OCA\Theming; +use OCP\Files\IAppData; use OCP\ICacheFactory; use OCP\IConfig; use OCP\IL10N; use OCP\IURLGenerator; -use OCP\Files\IRootFolder; use OCP\Util; class ThemingDefaults extends \OC_Defaults { @@ -38,8 +38,8 @@ class ThemingDefaults extends \OC_Defaults { private $l; /** @var IURLGenerator */ private $urlGenerator; - /** @var IRootFolder */ - private $rootFolder; + /** @var IAppData */ + private $appData; /** @var ICacheFactory */ private $cacheFactory; /** @var string */ @@ -58,21 +58,21 @@ class ThemingDefaults extends \OC_Defaults { * @param IL10N $l * @param IURLGenerator $urlGenerator * @param \OC_Defaults $defaults - * @param IRootFolder $rootFolder + * @param IAppData $appData * @param ICacheFactory $cacheFactory */ public function __construct(IConfig $config, IL10N $l, IURLGenerator $urlGenerator, \OC_Defaults $defaults, - IRootFolder $rootFolder, + IAppData $appData, ICacheFactory $cacheFactory ) { parent::__construct(); $this->config = $config; $this->l = $l; $this->urlGenerator = $urlGenerator; - $this->rootFolder = $rootFolder; + $this->appData = $appData; $this->cacheFactory = $cacheFactory; $this->name = $defaults->getName(); @@ -130,11 +130,19 @@ class ThemingDefaults extends \OC_Defaults { */ public function getLogo() { $logo = $this->config->getAppValue('theming', 'logoMime'); - if(!$logo || !$this->rootFolder->nodeExists('/themedinstancelogo')) { + + $logoExists = true; + try { + $this->appData->getFolder('images')->getFile('logo'); + } catch (\Exception $e) { + $logoExists = false; + } + + if(!$logo || !$logoExists) { return $this->urlGenerator->imagePath('core','logo.svg'); - } else { - return $this->urlGenerator->linkToRoute('theming.Theming.getLogo'); } + + return $this->urlGenerator->linkToRoute('theming.Theming.getLogo'); } /** @@ -144,11 +152,19 @@ class ThemingDefaults extends \OC_Defaults { */ public function getBackground() { $backgroundLogo = $this->config->getAppValue('theming', 'backgroundMime'); - if(!$backgroundLogo || !$this->rootFolder->nodeExists('/themedbackgroundlogo')) { + + $backgroundExists = true; + try { + $this->appData->getFolder('images')->getFile('background'); + } catch (\Exception $e) { + $backgroundExists = false; + } + + if(!$backgroundLogo || !$backgroundExists) { return $this->urlGenerator->imagePath('core','background.jpg'); - } else { - return $this->urlGenerator->linkToRoute('theming.Theming.getLoginBackground'); } + + return $this->urlGenerator->linkToRoute('theming.Theming.getLoginBackground'); } /** @@ -174,6 +190,15 @@ class ThemingDefaults extends \OC_Defaults { return $value; } + /** + * Gets the current cache buster count + * + * @return string + */ + public function getCacheBusterCounter() { + return $this->config->getAppValue('theming', 'cachebuster', '0'); + } + /** * Increases the cache buster key */ diff --git a/apps/theming/tests/ThemingDefaultsTest.php b/apps/theming/tests/ThemingDefaultsTest.php index 72ccaa57d77..986b2f34267 100644 --- a/apps/theming/tests/ThemingDefaultsTest.php +++ b/apps/theming/tests/ThemingDefaultsTest.php @@ -24,37 +24,36 @@ namespace OCA\Theming\Tests; use OCA\Theming\ThemingDefaults; +use OCP\Files\IAppData; +use OCP\Files\SimpleFS\ISimpleFolder; use OCP\ICacheFactory; use OCP\IConfig; use OCP\IL10N; use OCP\IURLGenerator; -use OCP\Files\IRootFolder; use Test\TestCase; class ThemingDefaultsTest extends TestCase { - /** @var IConfig */ + /** @var IConfig|\PHPUnit_Framework_MockObject_MockObject */ private $config; - /** @var IL10N */ + /** @var IL10N|\PHPUnit_Framework_MockObject_MockObject */ private $l10n; - /** @var IURLGenerator */ + /** @var IURLGenerator|\PHPUnit_Framework_MockObject_MockObject */ private $urlGenerator; - /** @var \OC_Defaults */ + /** @var \OC_Defaults|\PHPUnit_Framework_MockObject_MockObject */ private $defaults; + /** @var IAppData|\PHPUnit_Framework_MockObject_MockObject */ + private $appData; + /** @var ICacheFactory|\PHPUnit_Framework_MockObject_MockObject */ + private $cacheFactory; /** @var ThemingDefaults */ private $template; - /** @var IRootFolder */ - private $rootFolder; - /** @var ICacheFactory */ - private $cacheFactory; public function setUp() { parent::setUp(); $this->config = $this->getMockBuilder(IConfig::class)->getMock(); $this->l10n = $this->getMockBuilder(IL10N::class)->getMock(); $this->urlGenerator = $this->getMockBuilder(IURLGenerator::class)->getMock(); - $this->rootFolder = $this->getMockBuilder(IRootFolder::class) - ->disableOriginalConstructor() - ->getMock(); + $this->appData = $this->createMock(IAppData::class); $this->cacheFactory = $this->getMockBuilder(ICacheFactory::class)->getMock(); $this->defaults = $this->getMockBuilder(\OC_Defaults::class) ->disableOriginalConstructor() @@ -80,7 +79,7 @@ class ThemingDefaultsTest extends TestCase { $this->l10n, $this->urlGenerator, $this->defaults, - $this->rootFolder, + $this->appData, $this->cacheFactory ); } @@ -386,6 +385,11 @@ class ThemingDefaultsTest extends TestCase { ->method('getAppValue') ->with('theming', 'backgroundMime') ->willReturn(''); + $this->appData + ->expects($this->once()) + ->method('getFolder') + ->with('images') + ->willThrowException(new \Exception()); $expected = $this->urlGenerator->imagePath('core','background.jpg'); $this->assertEquals($expected, $this->template->getBackground()); } @@ -396,6 +400,17 @@ class ThemingDefaultsTest extends TestCase { ->method('getAppValue') ->with('theming', 'backgroundMime') ->willReturn('image/svg+xml'); + $simpleFolder = $this->createMock(ISimpleFolder::class); + $this->appData + ->expects($this->once()) + ->method('getFolder') + ->with('images') + ->willReturn($simpleFolder); + $simpleFolder + ->expects($this->once()) + ->method('getFile') + ->with('background') + ->willReturn(''); $expected = $this->urlGenerator->linkToRoute('theming.Theming.getLoginBackground'); $this->assertEquals($expected, $this->template->getBackground()); } @@ -406,6 +421,11 @@ class ThemingDefaultsTest extends TestCase { ->method('getAppValue') ->with('theming', 'logoMime') ->willReturn(''); + $this->appData + ->expects($this->once()) + ->method('getFolder') + ->with('images') + ->willThrowException(new \Exception()); $expected = $this->urlGenerator->imagePath('core','logo.svg'); $this->assertEquals($expected, $this->template->getLogo()); } @@ -416,6 +436,17 @@ class ThemingDefaultsTest extends TestCase { ->method('getAppValue') ->with('theming', 'logoMime') ->willReturn('image/svg+xml'); + $simpleFolder = $this->createMock(ISimpleFolder::class); + $this->appData + ->expects($this->once()) + ->method('getFolder') + ->with('images') + ->willReturn($simpleFolder); + $simpleFolder + ->expects($this->once()) + ->method('getFile') + ->with('logo') + ->willReturn(''); $expected = $this->urlGenerator->linkToRoute('theming.Theming.getLogo'); $this->assertEquals($expected, $this->template->getLogo()); } diff --git a/lib/private/Mail/EMailTemplate.php b/lib/private/Mail/EMailTemplate.php index 7a884dd928c..7d3ca51c50e 100644 --- a/lib/private/Mail/EMailTemplate.php +++ b/lib/private/Mail/EMailTemplate.php @@ -1,8 +1,10 @@ + * @copyright 2017, Lukas Reschke * * @author Morris Jobke + * @author Lukas Reschke * * @license GNU AGPL version 3 or any later version * @@ -23,6 +25,9 @@ namespace OC\Mail; +use OCA\Theming\ThemingDefaults; +use OCP\IL10N; +use OCP\IURLGenerator; /** * Class EMailTemplate @@ -33,9 +38,12 @@ namespace OC\Mail; * @package OC\Mail */ class EMailTemplate implements IEMailTemplate { - - /** @var \OC_Defaults */ - protected $defaults; + /** @var ThemingDefaults */ + protected $themingDefaults; + /** @var IURLGenerator */ + protected $urlGenerator; + /** @var IL10N */ + protected $l10n; /** @var string */ protected $htmlBody = ''; @@ -88,7 +96,7 @@ EOF; -
+
@@ -240,8 +248,7 @@ EOF;
EOF; - - public function __construct(\OC_Defaults $defaults) { - $this->defaults = $defaults; - + /** + * @param ThemingDefaults $themingDefaults + * @param IURLGenerator $urlGenerator + * @param IL10N $l10n + */ + public function __construct(ThemingDefaults $themingDefaults, + IURLGenerator $urlGenerator, + IL10N $l10n) { + $this->themingDefaults = $themingDefaults; + $this->urlGenerator = $urlGenerator; + $this->l10n = $l10n; $this->htmlBody .= $this->head; } /** * Adds a header to the email - * - * @param string $logoUrl */ - public function addHeader($logoUrl) { + public function addHeader() { if ($this->headerAdded) { return; } $this->headerAdded = true; - $this->htmlBody .= vsprintf($this->header, [$this->defaults->getColorPrimary(), $logoUrl]); + $logoUrl = $this->urlGenerator->getAbsoluteURL($this->themingDefaults->getLogo()) . '?v='. $this->themingDefaults->getCacheBusterCounter(); + $this->htmlBody .= vsprintf($this->header, [$this->themingDefaults->getColorPrimary(), $logoUrl]); } /** @@ -328,7 +341,7 @@ EOF; $this->bodyOpened = true; } - $color = $this->defaults->getColorPrimary(); + $color = $this->themingDefaults->getColorPrimary(); $this->htmlBody .= vsprintf($this->buttonGroup, [$color, $color, $urlLeft, $color, $textLeft, $urlRight, $textRight]); $this->plainBody .= $textLeft . ': ' . $urlLeft . PHP_EOL; $this->plainBody .= $textRight . ': ' . $urlRight . PHP_EOL . PHP_EOL; @@ -338,10 +351,13 @@ EOF; /** * Adds a logo and a text to the footer.
in the text will be replaced by new lines in the plain text email * - * @param string $logoUrl * @param string $text */ - public function addFooter($logoUrl, $text) { + public function addFooter($text = '') { + if($text === '') { + $text = $this->themingDefaults->getName() . ' - ' . $this->themingDefaults->getSlogan() . '
' . $this->l10n->t('This is an automatically generated email, please do not reply.'); + } + if ($this->footerAdded) { return; } @@ -351,7 +367,8 @@ EOF; $this->htmlBody .= $this->bodyEnd; $this->bodyOpened = false; } - $this->htmlBody .= vsprintf($this->footer, [$logoUrl, $text]); + + $this->htmlBody .= vsprintf($this->footer, [$text]); $this->htmlBody .= $this->tail; $this->plainBody .= '--' . PHP_EOL; $this->plainBody .= str_replace('
', PHP_EOL, $text); @@ -389,4 +406,3 @@ EOF; return $this->plainBody; } } - diff --git a/lib/private/Mail/IEMailTemplate.php b/lib/private/Mail/IEMailTemplate.php index 5bf2b8e4394..0d660a35516 100644 --- a/lib/private/Mail/IEMailTemplate.php +++ b/lib/private/Mail/IEMailTemplate.php @@ -34,7 +34,7 @@ namespace OC\Mail; * * $emailTemplate = new EMailTemplate($this->defaults); * - * $emailTemplate->addHeader('https://example.org/img/logo-mail-header.png'); + * $emailTemplate->addHeader(); * $emailTemplate->addHeading('Welcome aboard'); * $emailTemplate->addBodyText('You have now an Nextcloud account, you can add, protect, and share your data.'); * @@ -43,21 +43,25 @@ namespace OC\Mail; * 'Install Client', 'https://nextcloud.com/install/#install-clients' * ); * - * $emailTemplate->addFooter( - * 'https://example.org/img/logo-mail-footer.png', - * 'Nextcloud - a safe home for your data
This is an automatically generated email, please do not reply.' - * ); + * $emailTemplate->addFooter('Optional footer text'); * * $htmlContent = $emailTemplate->renderHTML(); * $plainContent = $emailTemplate->renderText(); */ interface IEMailTemplate { + /** + * @param \OCA\Theming\ThemingDefaults $themingDefaults + * @param \OCP\IURLGenerator $urlGenerator + * @param \OCP\IL10N $l10n + */ + public function __construct(\OCA\Theming\ThemingDefaults $themingDefaults, + \OCP\IURLGenerator $urlGenerator, + \OCP\IL10N $l10n); + /** * Adds a header to the email - * - * @param string $logoUrl */ - public function addHeader($logoUrl); + public function addHeader(); /** * Adds a heading to the email @@ -86,10 +90,9 @@ interface IEMailTemplate { /** * Adds a logo and a text to the footer.
in the text will be replaced by new lines in the plain text email * - * @param string $logoUrl * @param string $text */ - public function addFooter($logoUrl, $text); + public function addFooter($text = ''); /** * Returns the rendered HTML email as string @@ -104,4 +107,4 @@ interface IEMailTemplate { * @return string */ public function renderText(); -} \ No newline at end of file +} diff --git a/lib/private/Server.php b/lib/private/Server.php index 98910b097b7..0d05bfe0dc8 100644 --- a/lib/private/Server.php +++ b/lib/private/Server.php @@ -823,7 +823,7 @@ class Server extends ServerContainer implements IServerContainer { $c->getL10N('theming'), $c->getURLGenerator(), new \OC_Defaults(), - $c->getLazyRootFolder(), + $c->getAppDataDir('theming'), $c->getMemCacheFactory() ); } @@ -1572,7 +1572,7 @@ class Server extends ServerContainer implements IServerContainer { } /** - * @return \OC_Defaults + * @return \OCA\Theming\ThemingDefaults */ public function getThemingDefaults() { return $this->query('ThemingDefaults'); diff --git a/settings/Application.php b/settings/Application.php index 44747c2f681..bf149def94d 100644 --- a/settings/Application.php +++ b/settings/Application.php @@ -35,7 +35,10 @@ use OC\App\AppStore\Fetcher\CategoryFetcher; use OC\AppFramework\Utility\TimeFactory; use OC\Authentication\Token\IProvider; use OC\Server; +use OC\ServerContainer; +use OC\Settings\Mailer\NewUserMailHelper; use OC\Settings\Middleware\SubadminMiddleware; +use OCA\Theming\ThemingDefaults; use OCP\AppFramework\App; use OCP\IContainer; use OCP\Settings\IManager; @@ -75,9 +78,6 @@ class Application extends App { } return $isSubAdmin; }); - $container->registerService('fromMailAddress', function() { - return Util::getDefaultEmailAddress('no-reply'); - }); $container->registerService('userCertificateManager', function(IContainer $c) { return $c->query('ServerContainer')->getCertificateManager(); }, false); @@ -90,6 +90,23 @@ class Application extends App { $container->registerService(IManager::class, function (IContainer $c) { return $c->query('ServerContainer')->getSettingsManager(); }); + + $container->registerService(NewUserMailHelper::class, function (IContainer $c) { + /** @var Server $server */ + $server = $c->query('ServerContainer'); + + return new NewUserMailHelper( + $server->getThemingDefaults(), + $server->getURLGenerator(), + $server->getL10N('settings'), + $server->getMailer(), + $server->getSecureRandom(), + new TimeFactory(), + $server->getConfig(), + $server->getCrypto(), + Util::getDefaultEmailAddress('no-reply') + ); + }); $container->registerService(AppFetcher::class, function (IContainer $c) { /** @var Server $server */ $server = $c->query('ServerContainer'); diff --git a/settings/Controller/UsersController.php b/settings/Controller/UsersController.php index c7b2c2537da..b42d4faa569 100644 --- a/settings/Controller/UsersController.php +++ b/settings/Controller/UsersController.php @@ -33,12 +33,10 @@ namespace OC\Settings\Controller; use OC\Accounts\AccountManager; use OC\AppFramework\Http; use OC\ForbiddenException; -use OC\Mail\EMailTemplate; -use OC\User\User; +use OC\Settings\Mailer\NewUserMailHelper; use OCP\App\IAppManager; use OCP\AppFramework\Controller; use OCP\AppFramework\Http\DataResponse; -use OCP\AppFramework\Http\TemplateResponse; use OCP\IConfig; use OCP\IGroupManager; use OCP\IL10N; @@ -50,9 +48,7 @@ use OCP\IUserManager; use OCP\IUserSession; use OCP\Mail\IMailer; use OCP\IAvatarManager; -use OCP\Security\ICrypto; use OCP\Security\ISecureRandom; -use OCP\AppFramework\Utility\ITimeFactory; /** * @package OC\Settings\Controller @@ -72,14 +68,8 @@ class UsersController extends Controller { private $config; /** @var ILogger */ private $log; - /** @var \OC_Defaults */ - private $defaults; /** @var IMailer */ private $mailer; - /** @var string */ - private $fromMailAddress; - /** @var IURLGenerator */ - private $urlGenerator; /** @var bool contains the state of the encryption app */ private $isEncryptionAppEnabled; /** @var bool contains the state of the admin recovery setting */ @@ -90,11 +80,8 @@ class UsersController extends Controller { private $accountManager; /** @var ISecureRandom */ private $secureRandom; - /** @var ITimeFactory */ - private $timeFactory; - /** @var ICrypto */ - private $crypto; - + /** @var NewUserMailHelper */ + private $newUserMailHelper; /** * @param string $appName @@ -106,16 +93,13 @@ class UsersController extends Controller { * @param bool $isAdmin * @param IL10N $l10n * @param ILogger $log - * @param \OC_Defaults $defaults * @param IMailer $mailer - * @param string $fromMailAddress * @param IURLGenerator $urlGenerator * @param IAppManager $appManager * @param IAvatarManager $avatarManager * @param AccountManager $accountManager * @param ISecureRandom $secureRandom - * @param ITimeFactory $timeFactory - * @param ICrypto $crypto + * @param NewUserMailHelper $newUserMailHelper */ public function __construct($appName, IRequest $request, @@ -126,16 +110,13 @@ class UsersController extends Controller { $isAdmin, IL10N $l10n, ILogger $log, - \OC_Defaults $defaults, IMailer $mailer, - $fromMailAddress, IURLGenerator $urlGenerator, IAppManager $appManager, IAvatarManager $avatarManager, AccountManager $accountManager, ISecureRandom $secureRandom, - ITimeFactory $timeFactory, - ICrypto $crypto) { + NewUserMailHelper $newUserMailHelper) { parent::__construct($appName, $request); $this->userManager = $userManager; $this->groupManager = $groupManager; @@ -144,15 +125,11 @@ class UsersController extends Controller { $this->isAdmin = $isAdmin; $this->l10n = $l10n; $this->log = $log; - $this->defaults = $defaults; $this->mailer = $mailer; - $this->fromMailAddress = $fromMailAddress; - $this->urlGenerator = $urlGenerator; $this->avatarManager = $avatarManager; $this->accountManager = $accountManager; $this->secureRandom = $secureRandom; - $this->timeFactory = $timeFactory; - $this->crypto = $crypto; + $this->newUserMailHelper = $newUserMailHelper; // check for encryption state - TODO see formatUserForIndex $this->isEncryptionAppEnabled = $appManager->isEnabledForUser('encryption'); @@ -380,7 +357,7 @@ class UsersController extends Controller { ); } - $generatedPassword = false; + $generatePasswordResetToken = false; if ($password === '') { if ($email === '') { return new DataResponse( @@ -392,7 +369,7 @@ class UsersController extends Controller { } $password = $this->secureRandom->generate(32); - $generatedPassword = true; + $generatePasswordResetToken = true; } try { @@ -426,68 +403,9 @@ class UsersController extends Controller { */ if($email !== '') { $user->setEMailAddress($email); - - if ($generatedPassword) { - $token = $this->secureRandom->generate( - 21, - ISecureRandom::CHAR_DIGITS . - ISecureRandom::CHAR_LOWER . - ISecureRandom::CHAR_UPPER - ); - $tokenValue = $this->timeFactory->getTime() . ':' . $token; - $mailAddress = !is_null($user->getEMailAddress()) ? $user->getEMailAddress() : ''; - $encryptedValue = $this->crypto->encrypt($tokenValue, $mailAddress . $this->config->getSystemValue('secret')); - $this->config->setUserValue($username, 'core', 'lostpassword', $encryptedValue); - - $link = $this->urlGenerator->linkToRouteAbsolute('core.lost.resetform', ['userId' => $username, 'token' => $token]); - } else { - $link = $this->urlGenerator->getAbsoluteURL('/'); - } - - $emailTemplate = new EMailTemplate($this->defaults); - - $emailTemplate->addHeader($this->urlGenerator->getAbsoluteURL($this->urlGenerator->imagePath('', 'logo-mail-header.png'))); - - $displayName = $user->getDisplayName(); - if ($displayName === $username) { - $emailTemplate->addHeading($this->l10n->t('Welcome aboard')); - } else { - $emailTemplate->addHeading($this->l10n->t('Welcome aboard %s', [$displayName])); - } - $emailTemplate->addBodyText($this->l10n->t('You have now an %s account, you can add, protect, and share your data.', [$this->defaults->getName()])); - $emailTemplate->addBodyText($this->l10n->t('Your username is: %s', [$username])); - - if ($generatedPassword) { - $leftButtonText = $this->l10n->t('Set your password'); - } else { - $leftButtonText = $this->l10n->t('Go to %s', [$this->defaults->getName()]); - } - - $emailTemplate->addBodyButtonGroup( - $leftButtonText, - $link, - $this->l10n->t('Install Client'), - 'https://nextcloud.com/install/#install-clients' - ); - - $emailTemplate->addFooter( - $this->urlGenerator->getAbsoluteURL($this->urlGenerator->imagePath('', 'logo-mail-footer.png')), - $this->defaults->getName() . ' - ' . $this->defaults->getSlogan() . '
' . $this->l10n->t('This is an automatically generated email, please do not reply.') - ); - - $mailContent = $emailTemplate->renderHTML(); - $plainTextMailContent = $emailTemplate->renderText(); - - $subject = $this->l10n->t('Your %s account was created', [$this->defaults->getName()]); - try { - $message = $this->mailer->createMessage(); - $message->setTo([$email => $username]); - $message->setSubject($subject); - $message->setHtmlBody($mailContent); - $message->setPlainBody($plainTextMailContent); - $message->setFrom([$this->fromMailAddress => $this->defaults->getName()]); - $this->mailer->send($message); + $emailTemplate = $this->newUserMailHelper->generateTemplate($user, $generatePasswordResetToken); + $this->newUserMailHelper->sendMail($user, $emailTemplate); } catch(\Exception $e) { $this->log->error("Can't send new user mail to $email: " . $e->getMessage(), array('app' => 'settings')); } diff --git a/settings/Mailer/NewUserMailHelper.php b/settings/Mailer/NewUserMailHelper.php new file mode 100644 index 00000000000..15b912f803a --- /dev/null +++ b/settings/Mailer/NewUserMailHelper.php @@ -0,0 +1,166 @@ + + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +namespace OC\Settings\Mailer; + +use OC\Mail\EMailTemplate; +use OC\Mail\IEMailTemplate; +use OCA\Theming\ThemingDefaults; +use OCP\AppFramework\Utility\ITimeFactory; +use OCP\IConfig; +use OCP\IL10N; +use OCP\IURLGenerator; +use OCP\IUser; +use OCP\Mail\IMailer; +use OCP\Security\ICrypto; +use OCP\Security\ISecureRandom; + +class NewUserMailHelper { + /** @var ThemingDefaults */ + private $themingDefaults; + /** @var IURLGenerator */ + private $urlGenerator; + /** @var IL10N */ + private $l10n; + /** @var IMailer */ + private $mailer; + /** @var ISecureRandom */ + private $secureRandom; + /** @var ITimeFactory */ + private $timeFactory; + /** @var IConfig */ + private $config; + /** @var ICrypto */ + private $crypto; + /** @var string */ + private $fromAddress; + + /** + * @param ThemingDefaults $themingDefaults + * @param IURLGenerator $urlGenerator + * @param IL10N $l10n + * @param IMailer $mailer + * @param ISecureRandom $secureRandom + * @param ITimeFactory $timeFactory + * @param IConfig $config + * @param ICrypto $crypto + * @param string $fromAddress + */ + public function __construct(ThemingDefaults $themingDefaults, + IURLGenerator $urlGenerator, + IL10N $l10n, + IMailer $mailer, + ISecureRandom $secureRandom, + ITimeFactory $timeFactory, + IConfig $config, + ICrypto $crypto, + $fromAddress) { + $this->themingDefaults = $themingDefaults; + $this->urlGenerator = $urlGenerator; + $this->l10n = $l10n; + $this->mailer = $mailer; + $this->secureRandom = $secureRandom; + $this->timeFactory = $timeFactory; + $this->config = $config; + $this->crypto = $crypto; + $this->fromAddress = $fromAddress; + } + + /** + * Set the IL10N object + * + * @param IL10N $l10n + */ + public function setL10N(IL10N $l10n) { + $this->l10n = $l10n; + } + + /** + * @param IUser $user + * @param bool $generatePasswordResetToken + * @return EMailTemplate + */ + public function generateTemplate(IUser $user, $generatePasswordResetToken = false) { + if ($generatePasswordResetToken) { + $token = $this->secureRandom->generate( + 21, + ISecureRandom::CHAR_DIGITS . + ISecureRandom::CHAR_LOWER . + ISecureRandom::CHAR_UPPER + ); + $tokenValue = $this->timeFactory->getTime() . ':' . $token; + $mailAddress = (null !== $user->getEMailAddress()) ? $user->getEMailAddress() : ''; + $encryptedValue = $this->crypto->encrypt($tokenValue, $mailAddress . $this->config->getSystemValue('secret')); + $this->config->setUserValue($user->getUID(), 'core', 'lostpassword', $encryptedValue); + $link = $this->urlGenerator->linkToRouteAbsolute('core.lost.resetform', ['userId' => $user->getUID(), 'token' => $token]); + } else { + $link = $this->urlGenerator->getAbsoluteURL('/'); + } + + $emailTemplate = new EMailTemplate( + $this->themingDefaults, + $this->urlGenerator, + $this->l10n + ); + $emailTemplate->addHeader(); + $displayName = $user->getDisplayName(); + $userName = $user->getUID(); + if ($displayName === $userName) { + $emailTemplate->addHeading($this->l10n->t('Welcome aboard')); + } else { + $emailTemplate->addHeading($this->l10n->t('Welcome aboard %s', [$displayName])); + } + $emailTemplate->addBodyText($this->l10n->t('You have now an %s account, you can add, protect, and share your data.', [$this->themingDefaults->getName()])); + $emailTemplate->addBodyText($this->l10n->t('Your username is: %s', [$userName])); + if ($generatePasswordResetToken) { + $leftButtonText = $this->l10n->t('Set your password'); + } else { + $leftButtonText = $this->l10n->t('Go to %s', [$this->themingDefaults->getName()]); + } + $emailTemplate->addBodyButtonGroup( + $leftButtonText, + $link, + $this->l10n->t('Install Client'), + 'https://nextcloud.com/install/#install-clients' + ); + $emailTemplate->addFooter(); + + return $emailTemplate; + } + + /** + * Sends a welcome mail to $user + * + * @param IUser $user + * @param IEmailTemplate $emailTemplate + * @throws \Exception If mail could not be sent + */ + public function sendMail(IUser $user, + IEMailTemplate $emailTemplate) { + $message = $this->mailer->createMessage(); + $message->setTo([$user->getEMailAddress() => $user->getDisplayName()]); + $message->setSubject($this->l10n->t('Your %s account was created', [$this->themingDefaults->getName()])); + $message->setHtmlBody($emailTemplate->renderHTML()); + $message->setPlainBody($emailTemplate->renderText()); + $message->setFrom([$this->fromAddress => $this->themingDefaults->getName()]); + $this->mailer->send($message); + } +} diff --git a/tests/Settings/Controller/UsersControllerTest.php b/tests/Settings/Controller/UsersControllerTest.php index 52a9a1cc844..d7961e2332b 100644 --- a/tests/Settings/Controller/UsersControllerTest.php +++ b/tests/Settings/Controller/UsersControllerTest.php @@ -12,8 +12,9 @@ namespace Tests\Settings\Controller; use OC\Accounts\AccountManager; use OC\Group\Manager; -use OC\Mail\EMailTemplate; +use OC\Mail\IEMailTemplate; use OC\Settings\Controller\UsersController; +use OC\Settings\Mailer\NewUserMailHelper; use OCP\App\IAppManager; use OCP\AppFramework\Http; use OCP\AppFramework\Http\DataResponse; @@ -69,6 +70,8 @@ class UsersControllerTest extends \Test\TestCase { private $secureRandom; /** @var ITimeFactory | \PHPUnit_Framework_MockObject_MockObject */ private $timeFactory; + /** @var NewUserMailHelper|\PHPUnit_Framework_MockObject_MockObject */ + private $newUserMailHelper; /** @var ICrypto | \PHPUnit_Framework_MockObject_MockObject */ private $crypto; @@ -80,7 +83,6 @@ class UsersControllerTest extends \Test\TestCase { $this->userSession = $this->createMock(IUserSession::class); $this->config = $this->createMock(IConfig::class); $this->logger = $this->createMock(ILogger::class); - $this->defaults = $this->createMock(\OC_Defaults::class); $this->mailer = $this->createMock(IMailer::class); $this->urlGenerator = $this->createMock(IURLGenerator::class); $this->appManager = $this->createMock(IAppManager::class); @@ -89,6 +91,7 @@ class UsersControllerTest extends \Test\TestCase { $this->secureRandom = $this->createMock(ISecureRandom::class); $this->timeFactory = $this->createMock(ITimeFactory::class); $this->crypto = $this->createMock(ICrypto::class); + $this->newUserMailHelper = $this->createMock(NewUserMailHelper::class); $this->l = $this->createMock(IL10N::class); $this->l->method('t') ->will($this->returnCallback(function ($text, $parameters = []) { @@ -127,16 +130,13 @@ class UsersControllerTest extends \Test\TestCase { $isAdmin, $this->l, $this->logger, - $this->defaults, $this->mailer, - 'no-reply@nextcloud.com', $this->urlGenerator, $this->appManager, $this->avatarManager, $this->accountManager, $this->secureRandom, - $this->timeFactory, - $this->crypto + $this->newUserMailHelper ); } else { return $this->getMockBuilder(UsersController::class) @@ -151,16 +151,13 @@ class UsersControllerTest extends \Test\TestCase { $isAdmin, $this->l, $this->logger, - $this->defaults, $this->mailer, - 'no-reply@nextcloud.com', $this->urlGenerator, $this->appManager, $this->avatarManager, $this->accountManager, $this->secureRandom, - $this->timeFactory, - $this->crypto + $this->newUserMailHelper ] )->setMethods($mockedMethods)->getMock(); } @@ -1418,91 +1415,11 @@ class UsersControllerTest extends \Test\TestCase { */ public function testCreateSuccessfulWithValidEmailAdmin() { $controller = $this->getController(true); - $message = $this->getMockBuilder('\OC\Mail\Message') - ->disableOriginalConstructor()->getMock(); - $message - ->expects($this->at(0)) - ->method('setTo') - ->with(['validMail@Adre.ss' => 'foo']); - $message - ->expects($this->at(1)) - ->method('setSubject') - ->with('Your Nextcloud account was created'); - - $this->urlGenerator - ->expects($this->at(0)) - ->method('getAbsoluteURL') - ->with('/') - ->willReturn('https://example.org/'); - $this->urlGenerator - ->expects($this->at(1)) - ->method('imagePath') - ->with('', 'logo-mail-header.png') - ->willReturn('/img/logo-mail-header.png'); - $this->urlGenerator - ->expects($this->at(2)) - ->method('getAbsoluteURL') - ->with('/img/logo-mail-header.png') - ->willReturn('https://example.org/img/logo-mail-header.png'); - $this->urlGenerator - ->expects($this->at(3)) - ->method('imagePath') - ->with('', 'logo-mail-footer.png') - ->willReturn('/img/logo-mail-footer.png'); - $this->urlGenerator - ->expects($this->at(4)) - ->method('getAbsoluteURL') - ->with('/img/logo-mail-footer.png') - ->willReturn('https://example.org/img/logo-mail-footer.png'); - $this->defaults - ->expects($this->any()) - ->method('getName') - ->willReturn('Nextcloud'); - $this->defaults - ->expects($this->any()) - ->method('getSlogan') - ->willReturn('A safe home for your data'); - - $emailTemplate = new EMailTemplate($this->defaults); - $emailTemplate->addHeader('https://example.org/img/logo-mail-header.png'); - $emailTemplate->addHeading('Welcome aboard'); - $emailTemplate->addBodyText('You have now an Nextcloud account, you can add, protect, and share your data.'); - $emailTemplate->addBodyText('Your username is: foo'); - $emailTemplate->addBodyButtonGroup( - 'Go to Nextcloud', 'https://example.org/', - 'Install Client', 'https://nextcloud.com/install/#install-clients' - ); - $emailTemplate->addFooter( - 'https://example.org/img/logo-mail-footer.png', - 'Nextcloud - A safe home for your data
This is an automatically generated email, please do not reply.' - ); - - $message - ->expects($this->at(2)) - ->method('setHtmlBody') - ->with($emailTemplate->renderHTML()); - $message - ->expects($this->at(3)) - ->method('setPlainBody') - ->with($emailTemplate->renderText()); - $message - ->expects($this->at(4)) - ->method('setFrom') - ->with(['no-reply@nextcloud.com' => 'Nextcloud']); - $this->mailer ->expects($this->at(0)) ->method('validateMailAddress') ->with('validMail@Adre.ss') ->will($this->returnValue(true)); - $this->mailer - ->expects($this->at(1)) - ->method('createMessage') - ->will($this->returnValue($message)); - $this->mailer - ->expects($this->at(2)) - ->method('send') - ->with($message); $user = $this->getMockBuilder('\OC\User\User') ->disableOriginalConstructor()->getMock(); @@ -1523,6 +1440,17 @@ class UsersControllerTest extends \Test\TestCase { ->method('getBackendClassName') ->will($this->returnValue('bar')); + $emailTemplate = $this->createMock(IEMailTemplate::class); + $this->newUserMailHelper + ->expects($this->at(0)) + ->method('generateTemplate') + ->with($user, false) + ->willReturn($emailTemplate); + $this->newUserMailHelper + ->expects($this->at(1)) + ->method('sendMail') + ->with($user, $emailTemplate); + $this->userManager ->expects($this->once()) ->method('createUser') @@ -2334,106 +2262,22 @@ class UsersControllerTest extends \Test\TestCase { ->method('getSubAdmin') ->will($this->returnValue($subadmin)); - $this->secureRandom - ->expects($this->at(0)) - ->method('generate') - ->with(32) - ->will($this->returnValue('abc123')); - $this->secureRandom - ->expects($this->at(1)) - ->method('generate') - ->with(21, - ISecureRandom::CHAR_DIGITS . - ISecureRandom::CHAR_LOWER . - ISecureRandom::CHAR_UPPER) - ->will($this->returnValue('mytoken')); - $controller = $this->getController(true); - $message = $this->getMockBuilder('\OC\Mail\Message') - ->disableOriginalConstructor()->getMock(); - $message - ->expects($this->at(0)) - ->method('setTo') - ->with(['abc@example.org' => 'foo']); - $message - ->expects($this->at(1)) - ->method('setSubject') - ->with('Your Nextcloud account was created'); - - $this->urlGenerator - ->expects($this->at(0)) - ->method('linkToRouteAbsolute') - ->with('core.lost.resetform', ['userId' => 'foo', 'token' => 'mytoken']) - ->will($this->returnValue('https://example.org/resetPassword/123')); - $this->urlGenerator - ->expects($this->at(1)) - ->method('imagePath') - ->with('', 'logo-mail-header.png') - ->willReturn('/img/logo-mail-header.png'); - $this->urlGenerator - ->expects($this->at(2)) - ->method('getAbsoluteURL') - ->with('/img/logo-mail-header.png') - ->willReturn('https://example.org/img/logo-mail-header.png'); - $this->urlGenerator - ->expects($this->at(3)) - ->method('imagePath') - ->with('', 'logo-mail-footer.png') - ->willReturn('/img/logo-mail-footer.png'); - $this->urlGenerator - ->expects($this->at(4)) - ->method('getAbsoluteURL') - ->with('/img/logo-mail-footer.png') - ->willReturn('https://example.org/img/logo-mail-footer.png'); - $this->defaults - ->expects($this->any()) - ->method('getName') - ->willReturn('Nextcloud'); - $this->defaults - ->expects($this->any()) - ->method('getSlogan') - ->willReturn('A safe home for your data'); - - $emailTemplate = new EMailTemplate($this->defaults); - $emailTemplate->addHeader('https://example.org/img/logo-mail-header.png'); - $emailTemplate->addHeading('Welcome aboard John Doe'); - $emailTemplate->addBodyText('You have now an Nextcloud account, you can add, protect, and share your data.'); - $emailTemplate->addBodyText('Your username is: foo'); - $emailTemplate->addBodyButtonGroup( - 'Set your password', 'https://example.org/resetPassword/123', - 'Install Client', 'https://nextcloud.com/install/#install-clients' - ); - $emailTemplate->addFooter( - 'https://example.org/img/logo-mail-footer.png', - 'Nextcloud - A safe home for your data
This is an automatically generated email, please do not reply.' - ); - - $message - ->expects($this->at(2)) - ->method('setHtmlBody') - ->with($emailTemplate->renderHTML()); - $message - ->expects($this->at(3)) - ->method('setPlainBody') - ->with($emailTemplate->renderText()); - $message - ->expects($this->at(4)) - ->method('setFrom') - ->with(['no-reply@nextcloud.com' => 'Nextcloud']); - $this->mailer ->expects($this->at(0)) ->method('validateMailAddress') ->with('abc@example.org') ->will($this->returnValue(true)); - $this->mailer + $emailTemplate = $this->createMock(IEMailTemplate::class); + $this->newUserMailHelper + ->expects($this->at(0)) + ->method('generateTemplate') + ->with($user, true) + ->willReturn($emailTemplate); + $this->newUserMailHelper ->expects($this->at(1)) - ->method('createMessage') - ->will($this->returnValue($message)); - $this->mailer - ->expects($this->at(2)) - ->method('send') - ->with($message); + ->method('sendMail') + ->with($user, $emailTemplate); $expectedResponse = new DataResponse( [ diff --git a/tests/Settings/Mailer/NewUserMailHelperTest.php b/tests/Settings/Mailer/NewUserMailHelperTest.php new file mode 100644 index 00000000000..e77e8e197b8 --- /dev/null +++ b/tests/Settings/Mailer/NewUserMailHelperTest.php @@ -0,0 +1,639 @@ + + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +namespace Tests\Settings\Mailer; + +use OC\Mail\EMailTemplate; +use OC\Mail\IEMailTemplate; +use OC\Mail\Message; +use OC\Settings\Mailer\NewUserMailHelper; +use OCA\Theming\ThemingDefaults; +use OCP\AppFramework\Utility\ITimeFactory; +use OCP\IConfig; +use OCP\IL10N; +use OCP\IURLGenerator; +use OCP\IUser; +use OCP\Mail\IMailer; +use OCP\Security\ICrypto; +use OCP\Security\ISecureRandom; +use Test\TestCase; + +class NewUserMailHelperTest extends TestCase { + /** @var ThemingDefaults|\PHPUnit_Framework_MockObject_MockObject */ + private $themingDefaults; + /** @var IURLGenerator|\PHPUnit_Framework_MockObject_MockObject */ + private $urlGenerator; + /** @var IL10N|\PHPUnit_Framework_MockObject_MockObject */ + private $l10n; + /** @var IMailer|\PHPUnit_Framework_MockObject_MockObject */ + private $mailer; + /** @var ISecureRandom|\PHPUnit_Framework_MockObject_MockObject */ + private $secureRandom; + /** @var ITimeFactory|\PHPUnit_Framework_MockObject_MockObject */ + private $timeFactory; + /** @var IConfig|\PHPUnit_Framework_MockObject_MockObject */ + private $config; + /** @var ICrypto|\PHPUnit_Framework_MockObject_MockObject */ + private $crypto; + /** @var NewUserMailHelper */ + private $newUserMailHelper; + + public function setUp() { + parent::setUp(); + + $this->themingDefaults = $this->createMock(ThemingDefaults::class); + $this->urlGenerator = $this->createMock(IURLGenerator::class); + $this->l10n = $this->createMock(IL10N::class); + $this->mailer = $this->createMock(IMailer::class); + $this->secureRandom = $this->createMock(ISecureRandom::class); + $this->timeFactory = $this->createMock(ITimeFactory::class); + $this->config = $this->createMock(IConfig::class); + $this->crypto = $this->createMock(ICrypto::class); + $this->l10n->method('t') + ->will($this->returnCallback(function ($text, $parameters = []) { + return vsprintf($text, $parameters); + })); + + $this->newUserMailHelper = new NewUserMailHelper( + $this->themingDefaults, + $this->urlGenerator, + $this->l10n, + $this->mailer, + $this->secureRandom, + $this->timeFactory, + $this->config, + $this->crypto, + 'no-reply@nextcloud.com' + ); + } + + public function testGenerateTemplateWithPasswordResetToken() { + $this->secureRandom + ->expects($this->once()) + ->method('generate') + ->with(21, + ISecureRandom::CHAR_DIGITS . + ISecureRandom::CHAR_LOWER . + ISecureRandom::CHAR_UPPER + ) + ->willReturn('MySuperLongSecureRandomToken'); + $this->timeFactory + ->expects($this->once()) + ->method('getTime') + ->willReturn('12345'); + /** @var IUser|\PHPUnit_Framework_MockObject_MockObject $user */ + $user = $this->createMock(IUser::class); + $user + ->expects($this->at(0)) + ->method('getEmailAddress') + ->willReturn('recipient@example.com'); + $user + ->expects($this->at(1)) + ->method('getEmailAddress') + ->willReturn('recipient@example.com'); + $this->config + ->expects($this->at(0)) + ->method('getSystemValue') + ->with('secret') + ->willReturn('MyInstanceWideSecret'); + $this->crypto + ->expects($this->once()) + ->method('encrypt') + ->with('12345:MySuperLongSecureRandomToken', 'recipient@example.comMyInstanceWideSecret') + ->willReturn('TokenCiphertext'); + $user + ->expects($this->at(2)) + ->method('getUID') + ->willReturn('john'); + $this->config + ->expects($this->at(1)) + ->method('setUserValue') + ->with('john', 'core', 'lostpassword', 'TokenCiphertext'); + $user + ->expects($this->at(3)) + ->method('getUID') + ->willReturn('john'); + $this->urlGenerator + ->expects($this->at(0)) + ->method('linkToRouteAbsolute') + ->with('core.lost.resetform', ['userId' => 'john', 'token' => 'MySuperLongSecureRandomToken']) + ->willReturn('https://example.com/resetPassword/MySuperLongSecureRandomToken'); + $user + ->expects($this->at(4)) + ->method('getDisplayName') + ->willReturn('john'); + $user + ->expects($this->at(5)) + ->method('getUID') + ->willReturn('john'); + $this->themingDefaults + ->expects($this->at(0)) + ->method('getName') + ->willReturn('TestCloud'); + + $expectedHtmlBody = << + + + + + + + + + + + + + +
+
+ + + +
+ + + + + + +
+ + + +
+ +
+ + +
+
+
+ + + + + + +
 
+ + + + + +
+

Welcome aboard

+
+ + + + + + +
 
+ + + +
+ + + + + + +
+ + + + + + +
 
+ + + + + +
+ + + + + +
+

You have now an account, you can add, protect, and share your data.

+
+
+ + + + + +
+ + + + + +
+

Your username is: john

+
+
+ + + + + +
 
+ + + + + + +
+ + + + + +
+
+ + + + +
+ + + + +
+ Set your password +
+
+ + + + +
+ + + + +
+ Install Client +
+
+
+
+
+
+
+ + + + + +
 
+ + + + +
+
+ +
                                                           
+ + +EOF; + $expectedTextBody = <<newUserMailHelper->generateTemplate($user, true); + $this->assertEquals($expectedHtmlBody, $result->renderHTML()); + $this->assertEquals($expectedTextBody, $result->renderText()); + $this->assertSame('OC\Mail\EMailTemplate', get_class($result)); + } + + public function testGenerateTemplateWithoutPasswordResetToken() { + $this->urlGenerator + ->expects($this->at(0)) + ->method('getAbsoluteURL') + ->with('/') + ->willReturn('https://example.com/'); + + /** @var IUser|\PHPUnit_Framework_MockObject_MockObject $user */ + $user = $this->createMock(IUser::class); + $user + ->expects($this->at(0)) + ->method('getDisplayName') + ->willReturn('John Doe'); + $user + ->expects($this->at(1)) + ->method('getUID') + ->willReturn('john'); + $this->themingDefaults + ->expects($this->any()) + ->method('getName') + ->willReturn('TestCloud'); + + $expectedHtmlBody = << + + + + + + + + + + + + + +
+
+ + + +
+ + + + + + +
+ + + +
+ +
+ + +
+
+
+ + + + + + +
 
+ + + + + +
+

Welcome aboard John Doe

+
+ + + + + + +
 
+ + + +
+ + + + + + +
+ + + + + + +
 
+ + + + + +
+ + + + + +
+

You have now an TestCloud account, you can add, protect, and share your data.

+
+
+ + + + + +
+ + + + + +
+

Your username is: john

+
+
+ + + + + +
 
+ + + + + + +
+ + + + + +
+
+ + + + +
+ + + + +
+ Go to TestCloud +
+
+ + + + +
+ + + + +
+ Install Client +
+
+
+
+
+
+
+ + + + + +
 
+ + + + +
+
+ +
                                                           
+ + +EOF; + $expectedTextBody = <<newUserMailHelper->generateTemplate($user, false); + $this->assertEquals($expectedHtmlBody, $result->renderHTML()); + $this->assertEquals($expectedTextBody, $result->renderText()); + $this->assertSame('OC\Mail\EMailTemplate', get_class($result)); + } + + public function testSendMail() { + /** @var IUser|\PHPUnit_Framework_MockObject_MockObject $user */ + $user = $this->createMock(IUser::class); + $user + ->expects($this->at(0)) + ->method('getEMailAddress') + ->willReturn('recipient@example.com'); + $user + ->expects($this->at(1)) + ->method('getDisplayName') + ->willReturn('John Doe'); + /** @var IEMailTemplate|\PHPUnit_Framework_MockObject_MockObject $emailTemplate */ + $emailTemplate = $this->createMock(IEMailTemplate::class); + $message = $this->createMock(Message::class); + $message + ->expects($this->at(0)) + ->method('setTo') + ->with(['recipient@example.com' => 'John Doe']); + $this->themingDefaults + ->expects($this->exactly(2)) + ->method('getName') + ->willReturn('TestCloud'); + $message + ->expects($this->at(1)) + ->method('setSubject') + ->with('Your TestCloud account was created'); + $message + ->expects($this->at(2)) + ->method('setHtmlBody') + ->with($emailTemplate->renderHTML()); + $message + ->expects($this->at(3)) + ->method('setPlainBody') + ->with($emailTemplate->renderText()); + $message + ->expects($this->at(4)) + ->method('setFrom') + ->with(['no-reply@nextcloud.com' => 'TestCloud']); + $this->mailer + ->expects($this->once()) + ->method('createMessage') + ->willReturn($message); + + $this->newUserMailHelper->sendMail($user, $emailTemplate); + } +} diff --git a/tests/data/emails/new-account-email-custom.html b/tests/data/emails/new-account-email-custom.html new file mode 100644 index 00000000000..10d3330604d --- /dev/null +++ b/tests/data/emails/new-account-email-custom.html @@ -0,0 +1,187 @@ + + + + + + + + + + + + + + +
+
+ + + +
+ + + + + + +
+ + + +
+ +
+ + +
+
+
+ + + + + + +
 
+ + + + + +
+

Welcome aboard

+
+ + + + + + +
 
+ + + +
+ + + + + + +
+ + + + + + +
 
+ + + + + +
+ + + + + +
+

You have now an Nextcloud account, you can add, protect, and share your data.

+
+
+ + + + + +
+ + + + + +
+

Your username is: abc

+
+
+ + + + + +
 
+ + + + + + +
+ + + + + +
+
+ + + + +
+ + + + +
+ Set your password +
+
+ + + + +
+ + + + +
+ Install Client +
+
+
+
+
+
+
+ + + + + +
 
+ + + + +
+
+ +
                                                           
+ + \ No newline at end of file diff --git a/tests/data/emails/new-account-email-custom.txt b/tests/data/emails/new-account-email-custom.txt new file mode 100644 index 00000000000..962128980e0 --- /dev/null +++ b/tests/data/emails/new-account-email-custom.txt @@ -0,0 +1,11 @@ +Welcome aboard + +You have now an Nextcloud account, you can add, protect, and share your data. + +Your username is: abc + +Set your password: https://example.org/resetPassword/123 +Install Client: https://nextcloud.com/install/#install-clients + +-- +TestCloud - A safe home for your data diff --git a/tests/data/emails/new-account-email.html b/tests/data/emails/new-account-email.html index 9b9155fa1d9..a32ad61c49c 100644 --- a/tests/data/emails/new-account-email.html +++ b/tests/data/emails/new-account-email.html @@ -22,8 +22,8 @@ -
- +
+
@@ -165,8 +165,7 @@
diff --git a/tests/lib/Mail/EMailTemplateTest.php b/tests/lib/Mail/EMailTemplateTest.php index 3acb742aeca..47fe09aabbb 100644 --- a/tests/lib/Mail/EMailTemplateTest.php +++ b/tests/lib/Mail/EMailTemplateTest.php @@ -24,51 +24,113 @@ namespace Test\Mail; use OC\Mail\EMailTemplate; -use OC_Defaults; +use OCA\Theming\ThemingDefaults; +use OCP\IL10N; +use OCP\IURLGenerator; use Test\TestCase; class EMailTemplateTest extends TestCase { - /** @var OC_Defaults */ + /** @var ThemingDefaults|\PHPUnit_Framework_MockObject_MockObject */ private $defaults; - - function setUp() { + /** @var IURLGenerator|\PHPUnit_Framework_MockObject_MockObject */ + private $urlGenerator; + /** @var IL10N|\PHPUnit_Framework_MockObject_MockObject */ + private $l10n; + /** @var EMailTemplate */ + private $emailTemplate; + + public function setUp() { parent::setUp(); - $this->defaults = $this->getMockBuilder('\OC_Defaults') - ->disableOriginalConstructor()->getMock(); + $this->defaults = $this->createMock(ThemingDefaults::class); + $this->urlGenerator = $this->createMock(IURLGenerator::class); + $this->l10n = $this->createMock(IL10N::class); + $this->emailTemplate = new EMailTemplate( + $this->defaults, + $this->urlGenerator, + $this->l10n + ); + } + + public function testEMailTemplateCustomFooter() { $this->defaults ->expects($this->any()) ->method('getColorPrimary') ->willReturn('#0082c9'); - } - - public function testEMailTemplate() { - $emailTemplate = new EMailTemplate($this->defaults); - - $emailTemplate->addHeader('https://example.org/img/logo-mail-header.png'); - - $emailTemplate->addHeading('Welcome aboard'); - $emailTemplate->addBodyText('You have now an Nextcloud account, you can add, protect, and share your data.'); - $emailTemplate->addBodyText('Your username is: abc'); - - - $emailTemplate->addBodyButtonGroup( + $this->defaults + ->expects($this->any()) + ->method('getLogo') + ->willReturn('/img/logo-mail-header.png'); + $this->defaults + ->expects($this->any()) + ->method('getCacheBusterCounter') + ->willReturn('48'); + $this->urlGenerator + ->expects($this->once()) + ->method('getAbsoluteURL') + ->with('/img/logo-mail-header.png') + ->willReturn('https://example.org/img/logo-mail-header.png'); + + $this->emailTemplate->addHeader(); + $this->emailTemplate->addHeading('Welcome aboard'); + $this->emailTemplate->addBodyText('You have now an Nextcloud account, you can add, protect, and share your data.'); + $this->emailTemplate->addBodyText('Your username is: abc'); + $this->emailTemplate->addBodyButtonGroup( 'Set your password', 'https://example.org/resetPassword/123', 'Install Client', 'https://nextcloud.com/install/#install-clients' ); - - $emailTemplate->addFooter( - 'https://example.org/img/logo-mail-footer.png', + $this->emailTemplate->addFooter( 'TestCloud - A safe home for your data
This is an automatically generated email, please do not reply.' ); $expectedHTML = file_get_contents(\OC::$SERVERROOT . '/tests/data/emails/new-account-email.html'); - $this->assertSame($expectedHTML, $emailTemplate->renderHTML()); + $this->assertSame($expectedHTML, $this->emailTemplate->renderHTML()); + $expectedTXT = file_get_contents(\OC::$SERVERROOT . '/tests/data/emails/new-account-email.txt'); + $this->assertSame($expectedTXT, $this->emailTemplate->renderText()); + } + public function testEMailTemplateDefaultFooter() { + $this->defaults + ->expects($this->any()) + ->method('getColorPrimary') + ->willReturn('#0082c9'); + $this->defaults + ->expects($this->any()) + ->method('getName') + ->willReturn('TestCloud'); + $this->defaults + ->expects($this->any()) + ->method('getSlogan') + ->willReturn('A safe home for your data'); + $this->defaults + ->expects($this->any()) + ->method('getLogo') + ->willReturn('/img/logo-mail-header.png'); + $this->defaults + ->expects($this->any()) + ->method('getCacheBusterCounter') + ->willReturn('48'); + $this->urlGenerator + ->expects($this->once()) + ->method('getAbsoluteURL') + ->with('/img/logo-mail-header.png') + ->willReturn('https://example.org/img/logo-mail-header.png'); + + $this->emailTemplate->addHeader(); + $this->emailTemplate->addHeading('Welcome aboard'); + $this->emailTemplate->addBodyText('You have now an Nextcloud account, you can add, protect, and share your data.'); + $this->emailTemplate->addBodyText('Your username is: abc'); + $this->emailTemplate->addBodyButtonGroup( + 'Set your password', 'https://example.org/resetPassword/123', + 'Install Client', 'https://nextcloud.com/install/#install-clients' + ); + $this->emailTemplate->addFooter(); - $expectedTXT = file_get_contents(\OC::$SERVERROOT . '/tests/data/emails/new-account-email.txt'); - $this->assertSame($expectedTXT, $emailTemplate->renderText()); + $expectedHTML = file_get_contents(\OC::$SERVERROOT . '/tests/data/emails/new-account-email-custom.html'); + $this->assertSame($expectedHTML, $this->emailTemplate->renderHTML()); + $expectedTXT = file_get_contents(\OC::$SERVERROOT . '/tests/data/emails/new-account-email-custom.txt'); + $this->assertSame($expectedTXT, $this->emailTemplate->renderText()); } -- 2.39.5