diff options
author | Lukas Reschke <lukas@statuscode.ch> | 2017-04-07 14:51:05 +0200 |
---|---|---|
committer | Morris Jobke <hey@morrisjobke.de> | 2017-04-07 12:03:47 -0500 |
commit | 281ad406e88d36c1492c7aefd8ef28762379f9e3 (patch) | |
tree | 91b81364f1a9244455657b86848025c628fd4089 | |
parent | 1be75e8db8f583476f1cd03498afd608fce6408d (diff) | |
download | nextcloud-server-281ad406e88d36c1492c7aefd8ef28762379f9e3.tar.gz nextcloud-server-281ad406e88d36c1492c7aefd8ef28762379f9e3.zip |
Add support for theming
Add support for theming in generated emails and simplify API
Signed-off-by: Lukas Reschke <lukas@statuscode.ch>
-rw-r--r-- | apps/provisioning_api/lib/AppInfo/Application.php | 16 | ||||
-rw-r--r-- | apps/provisioning_api/lib/Controller/UsersController.php | 34 | ||||
-rw-r--r-- | apps/provisioning_api/tests/Controller/UsersControllerTest.php | 238 | ||||
-rw-r--r-- | apps/theming/lib/ThemingDefaults.php | 51 | ||||
-rw-r--r-- | apps/theming/tests/ThemingDefaultsTest.php | 57 | ||||
-rw-r--r-- | lib/private/Mail/EMailTemplate.php | 56 | ||||
-rw-r--r-- | lib/private/Mail/IEMailTemplate.php | 25 | ||||
-rw-r--r-- | lib/private/Server.php | 4 | ||||
-rw-r--r-- | settings/Application.php | 23 | ||||
-rw-r--r-- | settings/Controller/UsersController.php | 102 | ||||
-rw-r--r-- | settings/Mailer/NewUserMailHelper.php | 166 | ||||
-rw-r--r-- | tests/Settings/Controller/UsersControllerTest.php | 210 | ||||
-rw-r--r-- | tests/Settings/Mailer/NewUserMailHelperTest.php | 639 | ||||
-rw-r--r-- | tests/data/emails/new-account-email-custom.html | 187 | ||||
-rw-r--r-- | tests/data/emails/new-account-email-custom.txt | 11 | ||||
-rw-r--r-- | tests/data/emails/new-account-email.html | 9 | ||||
-rw-r--r-- | tests/lib/Mail/EMailTemplateTest.php | 112 |
17 files changed, 1366 insertions, 574 deletions
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 @@ <?php /** * @copyright Copyright (c) 2016 Bjoern Schiessle <bjoern@schiessle.org> + * @copyright Copyright (c) 2017 Lukas Reschke <lukas@statuscode.ch> * * @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'); } /** @@ -175,6 +191,15 @@ class ThemingDefaults extends \OC_Defaults { } /** + * Gets the current cache buster count + * + * @return string + */ + public function getCacheBusterCounter() { + return $this->config->getAppValue('theming', 'cachebuster', '0'); + } + + /** * Increases the cache buster key */ private function increaseCacheBuster() { 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 @@ <?php /** * @copyright 2017, Morris Jobke <hey@morrisjobke.de> + * @copyright 2017, Lukas Reschke <lukas@statuscode.ch> * * @author Morris Jobke <hey@morrisjobke.de> + * @author Lukas Reschke <lukas@statuscode.ch> * * @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; <table class="row collapse" style="border-collapse:collapse;border-spacing:0;display:table;padding:0;position:relative;text-align:left;vertical-align:top;width:100%%"> <tbody> <tr style="padding:0;text-align:left;vertical-align:top"> - <center data-parsed="" style="min-width:580px;width:100%%"><!-- TODO --> + <center data-parsed="" style="min-width:580px;width:100%%"> <img class="logo float-center" src="%s" alt="logo" align="center" style="-ms-interpolation-mode:bicubic;Margin:0 auto;clear:both;display:block;float:none;margin:0 auto;max-height:100%%;max-width:100px;outline:0;text-align:center;text-decoration:none;width:auto"> </center> </tr> @@ -240,8 +248,7 @@ EOF; <table align="center" class="wrapper footer float-center" style="Margin:0 auto;border-collapse:collapse;border-spacing:0;float:none;margin:0 auto;padding:0;text-align:center;vertical-align:top;width:100%%"> <tr style="padding:0;text-align:left;vertical-align:top"> <td class="wrapper-inner" style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;hyphens:auto;line-height:1.3;margin:0;padding:0;text-align:left;vertical-align:top;word-wrap:break-word"> - <center data-parsed="" style="min-width:580px;width:100%%"><!-- TODO --> - <img class="logo float-center" src="%s" alt="logo" align="center" style="-ms-interpolation-mode:bicubic;Margin:0 auto;clear:both;display:block;float:none;margin:0 auto;max-height:100%%;max-width:75px;outline:0;text-align:center;text-decoration:none;width:auto"> + <center data-parsed="" style="min-width:580px;width:100%%"> <table class="spacer float-center" style="Margin:0 auto;border-collapse:collapse;border-spacing:0;float:none;margin:0 auto;padding:0;text-align:center;vertical-align:top;width:100%%"> <tbody> <tr style="padding:0;text-align:left;vertical-align:top"> @@ -249,32 +256,38 @@ EOF; </tr> </tbody> </table> - <p class="text-center float-center" align="center" style="Margin:0;Margin-bottom:10px;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:12px;font-weight:400;line-height:16px;margin:0;margin-bottom:10px;padding:0;text-align:center">%s</p> + <p class="text-center float-center" align="center" style="Margin:0;Margin-bottom:10px;color:#C8C8C8;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:12px;font-weight:400;line-height:16px;margin:0;margin-bottom:10px;padding:0;text-align:center">%s</p> </center> </td> </tr> </table> 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. <br> 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() . '<br>' . $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('<br>', 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 <br>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. <br> 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() . '<br>' . $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 @@ +<?php +/** + * @copyright Copyright (c) 2017 Lukas Reschke <lukas@statuscode.ch> + * + * @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 <http://www.gnu.org/licenses/>. + * + */ + +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<br>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<br>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 @@ +<?php +/** + * @copyright Copyright (c) 2017 Lukas Reschke <lukas@statuscode.ch> + * + * @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 <http://www.gnu.org/licenses/>. + * + */ + +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 = <<<EOF +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en" style="-webkit-font-smoothing:antialiased;background:#f3f3f3!important"> +<head> + <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> + <meta name="viewport" content="width=device-width"> + <title></title> + <style type="text/css">@media only screen{html{min-height:100%;background:#F5F5F5}}@media only screen and (max-width:610px){table.body img{width:auto;height:auto}table.body center{min-width:0!important}table.body .container{width:95%!important}table.body .columns{height:auto!important;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box;padding-left:30px!important;padding-right:30px!important}th.small-12{display:inline-block!important;width:100%!important}table.menu{width:100%!important}table.menu td,table.menu th{width:auto!important;display:inline-block!important}table.menu.vertical td,table.menu.vertical th{display:block!important}table.menu[align=center]{width:auto!important}}</style> +</head> +<body style="-moz-box-sizing:border-box;-ms-text-size-adjust:100%;-webkit-box-sizing:border-box;-webkit-font-smoothing:antialiased;-webkit-text-size-adjust:100%;Margin:0;background:#f3f3f3!important;box-sizing:border-box;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;line-height:1.3;margin:0;min-width:100%;padding:0;text-align:left;width:100%!important"> + <span class="preheader" style="color:#F5F5F5;display:none!important;font-size:1px;line-height:1px;max-height:0;max-width:0;mso-hide:all!important;opacity:0;overflow:hidden;visibility:hidden"> + </span> + <table class="body" style="-webkit-font-smoothing:antialiased;Margin:0;background:#f3f3f3!important;border-collapse:collapse;border-spacing:0;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;height:100%;line-height:1.3;margin:0;padding:0;text-align:left;vertical-align:top;width:100%"> + <tr style="padding:0;text-align:left;vertical-align:top"> + <td class="center" align="center" valign="top" style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;hyphens:auto;line-height:1.3;margin:0;padding:0;text-align:left;vertical-align:top;word-wrap:break-word"> + <center data-parsed="" style="min-width:580px;width:100%"><table align="center" class="wrapper header float-center" style="Margin:0 auto;background:#8a8a8a;background-color:;border-collapse:collapse;border-spacing:0;float:none;margin:0 auto;padding:0;text-align:center;vertical-align:top;width:100%"> + <tr style="padding:0;text-align:left;vertical-align:top"> + <td class="wrapper-inner" style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;hyphens:auto;line-height:1.3;margin:0;padding:20px;text-align:left;vertical-align:top;word-wrap:break-word"> + <table align="center" class="container" style="Margin:0 auto;background:0 0;border-collapse:collapse;border-spacing:0;margin:0 auto;padding:0;text-align:inherit;vertical-align:top;width:580px"> + <tbody> + <tr style="padding:0;text-align:left;vertical-align:top"> + <td style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;hyphens:auto;line-height:1.3;margin:0;padding:0;text-align:left;vertical-align:top;word-wrap:break-word"> + <table class="row collapse" style="border-collapse:collapse;border-spacing:0;display:table;padding:0;position:relative;text-align:left;vertical-align:top;width:100%"> + <tbody> + <tr style="padding:0;text-align:left;vertical-align:top"> + <center data-parsed="" style="min-width:580px;width:100%"> + <img class="logo float-center" src="?v=" alt="logo" align="center" style="-ms-interpolation-mode:bicubic;Margin:0 auto;clear:both;display:block;float:none;margin:0 auto;max-height:100%;max-width:100px;outline:0;text-align:center;text-decoration:none;width:auto"> + </center> + </tr> + </tbody> + </table> + </td> + </tr> + </tbody> + </table> + </td> + </tr> +</table> +<table class="spacer float-center" style="Margin:0 auto;border-collapse:collapse;border-spacing:0;float:none;margin:0 auto;padding:0;text-align:center;vertical-align:top;width:100%"> + <tbody> + <tr style="padding:0;text-align:left;vertical-align:top"> + <td height="80px" style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:80px;font-weight:400;hyphens:auto;line-height:80px;margin:0;mso-line-height-rule:exactly;padding:0;text-align:left;vertical-align:top;word-wrap:break-word"> </td> + </tr> + </tbody> +</table><table align="center" class="container main-heading float-center" style="Margin:0 auto;background:0 0!important;border-collapse:collapse;border-spacing:0;float:none;margin:0 auto;padding:0;text-align:center;vertical-align:top;width:580px"> + <tbody> + <tr style="padding:0;text-align:left;vertical-align:top"> + <td style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;hyphens:auto;line-height:1.3;margin:0;padding:0;text-align:left;vertical-align:top;word-wrap:break-word"> + <h1 class="text-center" style="Margin:0;Margin-bottom:10px;color:inherit;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:24px;font-weight:400;line-height:1.3;margin:0;margin-bottom:10px;padding:0;text-align:center;word-wrap:normal">Welcome aboard</h1> + </td> + </tr> + </tbody> +</table> +<table class="spacer float-center" style="Margin:0 auto;border-collapse:collapse;border-spacing:0;float:none;margin:0 auto;padding:0;text-align:center;vertical-align:top;width:100%"> + <tbody> + <tr style="padding:0;text-align:left;vertical-align:top"> + <td height="40px" style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:40px;font-weight:400;hyphens:auto;line-height:40px;margin:0;mso-line-height-rule:exactly;padding:0;text-align:left;vertical-align:top;word-wrap:break-word"> </td> + </tr> + </tbody> +</table><table align="center" class="wrapper content float-center" style="Margin:0 auto;border-collapse:collapse;border-spacing:0;float:none;margin:0 auto;padding:0;text-align:center;vertical-align:top;width:100%"> + <tr style="padding:0;text-align:left;vertical-align:top"> + <td class="wrapper-inner" style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;hyphens:auto;line-height:1.3;margin:0;padding:0;text-align:left;vertical-align:top;word-wrap:break-word"> + <table align="center" class="container has-shadow" style="Margin:0 auto;background:#fefefe;border-collapse:collapse;border-spacing:0;box-shadow:0 1px 2px 0 rgba(0,0,0,.2),0 1px 3px 0 rgba(0,0,0,.1);margin:0 auto;padding:0;text-align:inherit;vertical-align:top;width:580px"> + <tbody> + <tr style="padding:0;text-align:left;vertical-align:top"> + <td style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;hyphens:auto;line-height:1.3;margin:0;padding:0;text-align:left;vertical-align:top;word-wrap:break-word"> + <table class="spacer" style="border-collapse:collapse;border-spacing:0;padding:0;text-align:left;vertical-align:top;width:100%"> + <tbody> + <tr style="padding:0;text-align:left;vertical-align:top"> + <td height="60px" style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:60px;font-weight:400;hyphens:auto;line-height:60px;margin:0;mso-line-height-rule:exactly;padding:0;text-align:left;vertical-align:top;word-wrap:break-word"> </td> + </tr> + </tbody> + </table><table class="row description" style="border-collapse:collapse;border-spacing:0;display:table;padding:0;position:relative;text-align:left;vertical-align:top;width:100%"> + <tbody> + <tr style="padding:0;text-align:left;vertical-align:top"> + <th class="small-12 large-12 columns first last" style="Margin:0 auto;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;line-height:1.3;margin:0 auto;padding:0;padding-bottom:30px;padding-left:30px;padding-right:30px;text-align:left;width:550px"> + <table style="border-collapse:collapse;border-spacing:0;padding:0;text-align:left;vertical-align:top;width:100%"> + <tr style="padding:0;text-align:left;vertical-align:top"> + <th style="Margin:0;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;line-height:1.3;margin:0;padding:0;text-align:left"> + <p class="text-left" style="Margin:0;Margin-bottom:10px;color:#777;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;line-height:1.3;margin:0;margin-bottom:10px;padding:0;text-align:left">You have now an account, you can add, protect, and share your data.</p> + </th> + <th class="expander" style="Margin:0;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;line-height:1.3;margin:0;padding:0!important;text-align:left;visibility:hidden;width:0"></th> + </tr> + </table> + </th> + </tr> + </tbody> +</table><table class="row description" style="border-collapse:collapse;border-spacing:0;display:table;padding:0;position:relative;text-align:left;vertical-align:top;width:100%"> + <tbody> + <tr style="padding:0;text-align:left;vertical-align:top"> + <th class="small-12 large-12 columns first last" style="Margin:0 auto;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;line-height:1.3;margin:0 auto;padding:0;padding-bottom:30px;padding-left:30px;padding-right:30px;text-align:left;width:550px"> + <table style="border-collapse:collapse;border-spacing:0;padding:0;text-align:left;vertical-align:top;width:100%"> + <tr style="padding:0;text-align:left;vertical-align:top"> + <th style="Margin:0;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;line-height:1.3;margin:0;padding:0;text-align:left"> + <p class="text-left" style="Margin:0;Margin-bottom:10px;color:#777;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;line-height:1.3;margin:0;margin-bottom:10px;padding:0;text-align:left">Your username is: john</p> + </th> + <th class="expander" style="Margin:0;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;line-height:1.3;margin:0;padding:0!important;text-align:left;visibility:hidden;width:0"></th> + </tr> + </table> + </th> + </tr> + </tbody> +</table><table class="spacer" style="border-collapse:collapse;border-spacing:0;padding:0;text-align:left;vertical-align:top;width:100%"> + <tbody> + <tr style="padding:0;text-align:left;vertical-align:top"> + <td height="50px" style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:50px;font-weight:400;hyphens:auto;line-height:50px;margin:0;mso-line-height-rule:exactly;padding:0;text-align:left;vertical-align:top;word-wrap:break-word"> </td> + </tr> + </tbody> +</table> +<table align="center" class="row btn-group" style="border-collapse:collapse;border-spacing:0;display:table;padding:0;position:relative;text-align:left;vertical-align:top;width:100%"> + <tbody> + <tr style="padding:0;text-align:left;vertical-align:top"> + <th class="small-12 large-12 columns first last" style="Margin:0 auto;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;line-height:1.3;margin:0 auto;padding:0;padding-bottom:30px;padding-left:30px;padding-right:30px;text-align:left;width:550px"> + <table style="border-collapse:collapse;border-spacing:0;padding:0;text-align:left;vertical-align:top;width:100%"> + <tr style="padding:0;text-align:left;vertical-align:top"> + <th style="Margin:0;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;line-height:1.3;margin:0;padding:0;text-align:left"> + <center data-parsed="" style="min-width:490px;width:100%"> + <table class="button btn default primary float-center" style="Margin:0 0 30px 0;border-collapse:collapse;border-spacing:0;display:inline-block;float:none;margin:0 0 30px 0;margin-right:15px;max-height:40px;max-width:200px;padding:0;text-align:center;vertical-align:top;width:auto"> + <tr style="padding:0;text-align:left;vertical-align:top"> + <td style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;hyphens:auto;line-height:1.3;margin:0;padding:0;text-align:left;vertical-align:top;word-wrap:break-word"> + <table style="border-collapse:collapse;border-spacing:0;padding:0;text-align:left;vertical-align:top;width:100%"> + <tr style="padding:0;text-align:left;vertical-align:top"> + <td style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;background:;border:0 solid ;border-collapse:collapse!important;color:#fefefe;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;hyphens:auto;line-height:1.3;margin:0;padding:0;text-align:left;vertical-align:top;word-wrap:break-word"> + <a href="https://example.com/resetPassword/MySuperLongSecureRandomToken" style="Margin:0;border:0 solid ;border-radius:2px;color:#fefefe;display:inline-block;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:regular;line-height:1.3;margin:0;padding:10px 25px 10px 25px;text-align:left;text-decoration:none">Set your password</a> + </td> + </tr> + </table> + </td> + </tr> + </table> + <table class="button btn default secondary float-center" style="Margin:0 0 30px 0;border-collapse:collapse;border-spacing:0;display:inline-block;float:none;margin:0 0 30px 0;max-height:40px;max-width:200px;padding:0;text-align:center;vertical-align:top;width:auto"> + <tr style="padding:0;text-align:left;vertical-align:top"> + <td style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;hyphens:auto;line-height:1.3;margin:0;padding:0;text-align:left;vertical-align:top;word-wrap:break-word"> + <table style="border-collapse:collapse;border-spacing:0;padding:0;text-align:left;vertical-align:top;width:100%"> + <tr style="padding:0;text-align:left;vertical-align:top"> + <td style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;background:#777;border:0 solid #777;border-collapse:collapse!important;color:#fefefe;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;hyphens:auto;line-height:1.3;margin:0;padding:0;text-align:left;vertical-align:top;word-wrap:break-word"> + <a href="https://nextcloud.com/install/#install-clients" style="Margin:0;background-color:#fff;border:0 solid #777;border-radius:2px;color:#6C6C6C!important;display:inline-block;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:regular;line-height:1.3;margin:0;outline:1px solid #CBCBCB;padding:10px 25px 10px 25px;text-align:left;text-decoration:none">Install Client</a> + </td> + </tr> + </table> + </td> + </tr> + </table> + </center> + </th> + <th class="expander" style="Margin:0;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;line-height:1.3;margin:0;padding:0!important;text-align:left;visibility:hidden;width:0"></th> + </tr> + </table> + </th> + </tr> + </tbody> +</table> + </td> + </tr> + </tbody> + </table> + </td> + </tr> +</table><table class="spacer float-center" style="Margin:0 auto;border-collapse:collapse;border-spacing:0;float:none;margin:0 auto;padding:0;text-align:center;vertical-align:top;width:100%"> + <tbody> + <tr style="padding:0;text-align:left;vertical-align:top"> + <td height="60px" style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:60px;font-weight:400;hyphens:auto;line-height:60px;margin:0;mso-line-height-rule:exactly;padding:0;text-align:left;vertical-align:top;word-wrap:break-word"> </td> + </tr> + </tbody> +</table> +<table align="center" class="wrapper footer float-center" style="Margin:0 auto;border-collapse:collapse;border-spacing:0;float:none;margin:0 auto;padding:0;text-align:center;vertical-align:top;width:100%"> + <tr style="padding:0;text-align:left;vertical-align:top"> + <td class="wrapper-inner" style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;hyphens:auto;line-height:1.3;margin:0;padding:0;text-align:left;vertical-align:top;word-wrap:break-word"> + <center data-parsed="" style="min-width:580px;width:100%"> + <table class="spacer float-center" style="Margin:0 auto;border-collapse:collapse;border-spacing:0;float:none;margin:0 auto;padding:0;text-align:center;vertical-align:top;width:100%"> + <tbody> + <tr style="padding:0;text-align:left;vertical-align:top"> + <td height="15px" style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:15px;font-weight:400;hyphens:auto;line-height:15px;margin:0;mso-line-height-rule:exactly;padding:0;text-align:left;vertical-align:top;word-wrap:break-word"> </td> + </tr> + </tbody> + </table> + <p class="text-center float-center" align="center" style="Margin:0;Margin-bottom:10px;color:#C8C8C8;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:12px;font-weight:400;line-height:16px;margin:0;margin-bottom:10px;padding:0;text-align:center"> - <br>This is an automatically generated email, please do not reply.</p> + </center> + </td> + </tr> +</table> </center> + </td> + </tr> + </table> + <!-- prevent Gmail on iOS font size manipulation --> + <div style="display:none;white-space:nowrap;font:15px courier;line-height:0"> </div> + </body> +</html> +EOF; + $expectedTextBody = <<<EOF +Welcome aboard + +You have now an account, you can add, protect, and share your data. + +Your username is: john + +Set your password: https://example.com/resetPassword/MySuperLongSecureRandomToken +Install Client: https://nextcloud.com/install/#install-clients + +-- + - +This is an automatically generated email, please do not reply. +EOF; + + $result = $this->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 = <<<EOF +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en" style="-webkit-font-smoothing:antialiased;background:#f3f3f3!important"> +<head> + <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> + <meta name="viewport" content="width=device-width"> + <title></title> + <style type="text/css">@media only screen{html{min-height:100%;background:#F5F5F5}}@media only screen and (max-width:610px){table.body img{width:auto;height:auto}table.body center{min-width:0!important}table.body .container{width:95%!important}table.body .columns{height:auto!important;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box;padding-left:30px!important;padding-right:30px!important}th.small-12{display:inline-block!important;width:100%!important}table.menu{width:100%!important}table.menu td,table.menu th{width:auto!important;display:inline-block!important}table.menu.vertical td,table.menu.vertical th{display:block!important}table.menu[align=center]{width:auto!important}}</style> +</head> +<body style="-moz-box-sizing:border-box;-ms-text-size-adjust:100%;-webkit-box-sizing:border-box;-webkit-font-smoothing:antialiased;-webkit-text-size-adjust:100%;Margin:0;background:#f3f3f3!important;box-sizing:border-box;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;line-height:1.3;margin:0;min-width:100%;padding:0;text-align:left;width:100%!important"> + <span class="preheader" style="color:#F5F5F5;display:none!important;font-size:1px;line-height:1px;max-height:0;max-width:0;mso-hide:all!important;opacity:0;overflow:hidden;visibility:hidden"> + </span> + <table class="body" style="-webkit-font-smoothing:antialiased;Margin:0;background:#f3f3f3!important;border-collapse:collapse;border-spacing:0;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;height:100%;line-height:1.3;margin:0;padding:0;text-align:left;vertical-align:top;width:100%"> + <tr style="padding:0;text-align:left;vertical-align:top"> + <td class="center" align="center" valign="top" style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;hyphens:auto;line-height:1.3;margin:0;padding:0;text-align:left;vertical-align:top;word-wrap:break-word"> + <center data-parsed="" style="min-width:580px;width:100%"><table align="center" class="wrapper header float-center" style="Margin:0 auto;background:#8a8a8a;background-color:;border-collapse:collapse;border-spacing:0;float:none;margin:0 auto;padding:0;text-align:center;vertical-align:top;width:100%"> + <tr style="padding:0;text-align:left;vertical-align:top"> + <td class="wrapper-inner" style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;hyphens:auto;line-height:1.3;margin:0;padding:20px;text-align:left;vertical-align:top;word-wrap:break-word"> + <table align="center" class="container" style="Margin:0 auto;background:0 0;border-collapse:collapse;border-spacing:0;margin:0 auto;padding:0;text-align:inherit;vertical-align:top;width:580px"> + <tbody> + <tr style="padding:0;text-align:left;vertical-align:top"> + <td style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;hyphens:auto;line-height:1.3;margin:0;padding:0;text-align:left;vertical-align:top;word-wrap:break-word"> + <table class="row collapse" style="border-collapse:collapse;border-spacing:0;display:table;padding:0;position:relative;text-align:left;vertical-align:top;width:100%"> + <tbody> + <tr style="padding:0;text-align:left;vertical-align:top"> + <center data-parsed="" style="min-width:580px;width:100%"> + <img class="logo float-center" src="?v=" alt="logo" align="center" style="-ms-interpolation-mode:bicubic;Margin:0 auto;clear:both;display:block;float:none;margin:0 auto;max-height:100%;max-width:100px;outline:0;text-align:center;text-decoration:none;width:auto"> + </center> + </tr> + </tbody> + </table> + </td> + </tr> + </tbody> + </table> + </td> + </tr> +</table> +<table class="spacer float-center" style="Margin:0 auto;border-collapse:collapse;border-spacing:0;float:none;margin:0 auto;padding:0;text-align:center;vertical-align:top;width:100%"> + <tbody> + <tr style="padding:0;text-align:left;vertical-align:top"> + <td height="80px" style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:80px;font-weight:400;hyphens:auto;line-height:80px;margin:0;mso-line-height-rule:exactly;padding:0;text-align:left;vertical-align:top;word-wrap:break-word"> </td> + </tr> + </tbody> +</table><table align="center" class="container main-heading float-center" style="Margin:0 auto;background:0 0!important;border-collapse:collapse;border-spacing:0;float:none;margin:0 auto;padding:0;text-align:center;vertical-align:top;width:580px"> + <tbody> + <tr style="padding:0;text-align:left;vertical-align:top"> + <td style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;hyphens:auto;line-height:1.3;margin:0;padding:0;text-align:left;vertical-align:top;word-wrap:break-word"> + <h1 class="text-center" style="Margin:0;Margin-bottom:10px;color:inherit;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:24px;font-weight:400;line-height:1.3;margin:0;margin-bottom:10px;padding:0;text-align:center;word-wrap:normal">Welcome aboard John Doe</h1> + </td> + </tr> + </tbody> +</table> +<table class="spacer float-center" style="Margin:0 auto;border-collapse:collapse;border-spacing:0;float:none;margin:0 auto;padding:0;text-align:center;vertical-align:top;width:100%"> + <tbody> + <tr style="padding:0;text-align:left;vertical-align:top"> + <td height="40px" style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:40px;font-weight:400;hyphens:auto;line-height:40px;margin:0;mso-line-height-rule:exactly;padding:0;text-align:left;vertical-align:top;word-wrap:break-word"> </td> + </tr> + </tbody> +</table><table align="center" class="wrapper content float-center" style="Margin:0 auto;border-collapse:collapse;border-spacing:0;float:none;margin:0 auto;padding:0;text-align:center;vertical-align:top;width:100%"> + <tr style="padding:0;text-align:left;vertical-align:top"> + <td class="wrapper-inner" style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;hyphens:auto;line-height:1.3;margin:0;padding:0;text-align:left;vertical-align:top;word-wrap:break-word"> + <table align="center" class="container has-shadow" style="Margin:0 auto;background:#fefefe;border-collapse:collapse;border-spacing:0;box-shadow:0 1px 2px 0 rgba(0,0,0,.2),0 1px 3px 0 rgba(0,0,0,.1);margin:0 auto;padding:0;text-align:inherit;vertical-align:top;width:580px"> + <tbody> + <tr style="padding:0;text-align:left;vertical-align:top"> + <td style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;hyphens:auto;line-height:1.3;margin:0;padding:0;text-align:left;vertical-align:top;word-wrap:break-word"> + <table class="spacer" style="border-collapse:collapse;border-spacing:0;padding:0;text-align:left;vertical-align:top;width:100%"> + <tbody> + <tr style="padding:0;text-align:left;vertical-align:top"> + <td height="60px" style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:60px;font-weight:400;hyphens:auto;line-height:60px;margin:0;mso-line-height-rule:exactly;padding:0;text-align:left;vertical-align:top;word-wrap:break-word"> </td> + </tr> + </tbody> + </table><table class="row description" style="border-collapse:collapse;border-spacing:0;display:table;padding:0;position:relative;text-align:left;vertical-align:top;width:100%"> + <tbody> + <tr style="padding:0;text-align:left;vertical-align:top"> + <th class="small-12 large-12 columns first last" style="Margin:0 auto;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;line-height:1.3;margin:0 auto;padding:0;padding-bottom:30px;padding-left:30px;padding-right:30px;text-align:left;width:550px"> + <table style="border-collapse:collapse;border-spacing:0;padding:0;text-align:left;vertical-align:top;width:100%"> + <tr style="padding:0;text-align:left;vertical-align:top"> + <th style="Margin:0;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;line-height:1.3;margin:0;padding:0;text-align:left"> + <p class="text-left" style="Margin:0;Margin-bottom:10px;color:#777;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;line-height:1.3;margin:0;margin-bottom:10px;padding:0;text-align:left">You have now an TestCloud account, you can add, protect, and share your data.</p> + </th> + <th class="expander" style="Margin:0;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;line-height:1.3;margin:0;padding:0!important;text-align:left;visibility:hidden;width:0"></th> + </tr> + </table> + </th> + </tr> + </tbody> +</table><table class="row description" style="border-collapse:collapse;border-spacing:0;display:table;padding:0;position:relative;text-align:left;vertical-align:top;width:100%"> + <tbody> + <tr style="padding:0;text-align:left;vertical-align:top"> + <th class="small-12 large-12 columns first last" style="Margin:0 auto;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;line-height:1.3;margin:0 auto;padding:0;padding-bottom:30px;padding-left:30px;padding-right:30px;text-align:left;width:550px"> + <table style="border-collapse:collapse;border-spacing:0;padding:0;text-align:left;vertical-align:top;width:100%"> + <tr style="padding:0;text-align:left;vertical-align:top"> + <th style="Margin:0;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;line-height:1.3;margin:0;padding:0;text-align:left"> + <p class="text-left" style="Margin:0;Margin-bottom:10px;color:#777;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;line-height:1.3;margin:0;margin-bottom:10px;padding:0;text-align:left">Your username is: john</p> + </th> + <th class="expander" style="Margin:0;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;line-height:1.3;margin:0;padding:0!important;text-align:left;visibility:hidden;width:0"></th> + </tr> + </table> + </th> + </tr> + </tbody> +</table><table class="spacer" style="border-collapse:collapse;border-spacing:0;padding:0;text-align:left;vertical-align:top;width:100%"> + <tbody> + <tr style="padding:0;text-align:left;vertical-align:top"> + <td height="50px" style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:50px;font-weight:400;hyphens:auto;line-height:50px;margin:0;mso-line-height-rule:exactly;padding:0;text-align:left;vertical-align:top;word-wrap:break-word"> </td> + </tr> + </tbody> +</table> +<table align="center" class="row btn-group" style="border-collapse:collapse;border-spacing:0;display:table;padding:0;position:relative;text-align:left;vertical-align:top;width:100%"> + <tbody> + <tr style="padding:0;text-align:left;vertical-align:top"> + <th class="small-12 large-12 columns first last" style="Margin:0 auto;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;line-height:1.3;margin:0 auto;padding:0;padding-bottom:30px;padding-left:30px;padding-right:30px;text-align:left;width:550px"> + <table style="border-collapse:collapse;border-spacing:0;padding:0;text-align:left;vertical-align:top;width:100%"> + <tr style="padding:0;text-align:left;vertical-align:top"> + <th style="Margin:0;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;line-height:1.3;margin:0;padding:0;text-align:left"> + <center data-parsed="" style="min-width:490px;width:100%"> + <table class="button btn default primary float-center" style="Margin:0 0 30px 0;border-collapse:collapse;border-spacing:0;display:inline-block;float:none;margin:0 0 30px 0;margin-right:15px;max-height:40px;max-width:200px;padding:0;text-align:center;vertical-align:top;width:auto"> + <tr style="padding:0;text-align:left;vertical-align:top"> + <td style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;hyphens:auto;line-height:1.3;margin:0;padding:0;text-align:left;vertical-align:top;word-wrap:break-word"> + <table style="border-collapse:collapse;border-spacing:0;padding:0;text-align:left;vertical-align:top;width:100%"> + <tr style="padding:0;text-align:left;vertical-align:top"> + <td style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;background:;border:0 solid ;border-collapse:collapse!important;color:#fefefe;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;hyphens:auto;line-height:1.3;margin:0;padding:0;text-align:left;vertical-align:top;word-wrap:break-word"> + <a href="https://example.com/" style="Margin:0;border:0 solid ;border-radius:2px;color:#fefefe;display:inline-block;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:regular;line-height:1.3;margin:0;padding:10px 25px 10px 25px;text-align:left;text-decoration:none">Go to TestCloud</a> + </td> + </tr> + </table> + </td> + </tr> + </table> + <table class="button btn default secondary float-center" style="Margin:0 0 30px 0;border-collapse:collapse;border-spacing:0;display:inline-block;float:none;margin:0 0 30px 0;max-height:40px;max-width:200px;padding:0;text-align:center;vertical-align:top;width:auto"> + <tr style="padding:0;text-align:left;vertical-align:top"> + <td style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;hyphens:auto;line-height:1.3;margin:0;padding:0;text-align:left;vertical-align:top;word-wrap:break-word"> + <table style="border-collapse:collapse;border-spacing:0;padding:0;text-align:left;vertical-align:top;width:100%"> + <tr style="padding:0;text-align:left;vertical-align:top"> + <td style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;background:#777;border:0 solid #777;border-collapse:collapse!important;color:#fefefe;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;hyphens:auto;line-height:1.3;margin:0;padding:0;text-align:left;vertical-align:top;word-wrap:break-word"> + <a href="https://nextcloud.com/install/#install-clients" style="Margin:0;background-color:#fff;border:0 solid #777;border-radius:2px;color:#6C6C6C!important;display:inline-block;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:regular;line-height:1.3;margin:0;outline:1px solid #CBCBCB;padding:10px 25px 10px 25px;text-align:left;text-decoration:none">Install Client</a> + </td> + </tr> + </table> + </td> + </tr> + </table> + </center> + </th> + <th class="expander" style="Margin:0;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;line-height:1.3;margin:0;padding:0!important;text-align:left;visibility:hidden;width:0"></th> + </tr> + </table> + </th> + </tr> + </tbody> +</table> + </td> + </tr> + </tbody> + </table> + </td> + </tr> +</table><table class="spacer float-center" style="Margin:0 auto;border-collapse:collapse;border-spacing:0;float:none;margin:0 auto;padding:0;text-align:center;vertical-align:top;width:100%"> + <tbody> + <tr style="padding:0;text-align:left;vertical-align:top"> + <td height="60px" style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:60px;font-weight:400;hyphens:auto;line-height:60px;margin:0;mso-line-height-rule:exactly;padding:0;text-align:left;vertical-align:top;word-wrap:break-word"> </td> + </tr> + </tbody> +</table> +<table align="center" class="wrapper footer float-center" style="Margin:0 auto;border-collapse:collapse;border-spacing:0;float:none;margin:0 auto;padding:0;text-align:center;vertical-align:top;width:100%"> + <tr style="padding:0;text-align:left;vertical-align:top"> + <td class="wrapper-inner" style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;hyphens:auto;line-height:1.3;margin:0;padding:0;text-align:left;vertical-align:top;word-wrap:break-word"> + <center data-parsed="" style="min-width:580px;width:100%"> + <table class="spacer float-center" style="Margin:0 auto;border-collapse:collapse;border-spacing:0;float:none;margin:0 auto;padding:0;text-align:center;vertical-align:top;width:100%"> + <tbody> + <tr style="padding:0;text-align:left;vertical-align:top"> + <td height="15px" style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:15px;font-weight:400;hyphens:auto;line-height:15px;margin:0;mso-line-height-rule:exactly;padding:0;text-align:left;vertical-align:top;word-wrap:break-word"> </td> + </tr> + </tbody> + </table> + <p class="text-center float-center" align="center" style="Margin:0;Margin-bottom:10px;color:#C8C8C8;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:12px;font-weight:400;line-height:16px;margin:0;margin-bottom:10px;padding:0;text-align:center">TestCloud - <br>This is an automatically generated email, please do not reply.</p> + </center> + </td> + </tr> +</table> </center> + </td> + </tr> + </table> + <!-- prevent Gmail on iOS font size manipulation --> + <div style="display:none;white-space:nowrap;font:15px courier;line-height:0"> </div> + </body> +</html> +EOF; + $expectedTextBody = <<<EOF +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: https://example.com/ +Install Client: https://nextcloud.com/install/#install-clients + +-- +TestCloud - +This is an automatically generated email, please do not reply. +EOF; + + $result = $this->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 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en" style="-webkit-font-smoothing:antialiased;background:#f3f3f3!important"> +<head> + <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> + <meta name="viewport" content="width=device-width"> + <title></title> + <style type="text/css">@media only screen{html{min-height:100%;background:#F5F5F5}}@media only screen and (max-width:610px){table.body img{width:auto;height:auto}table.body center{min-width:0!important}table.body .container{width:95%!important}table.body .columns{height:auto!important;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box;padding-left:30px!important;padding-right:30px!important}th.small-12{display:inline-block!important;width:100%!important}table.menu{width:100%!important}table.menu td,table.menu th{width:auto!important;display:inline-block!important}table.menu.vertical td,table.menu.vertical th{display:block!important}table.menu[align=center]{width:auto!important}}</style> +</head> +<body style="-moz-box-sizing:border-box;-ms-text-size-adjust:100%;-webkit-box-sizing:border-box;-webkit-font-smoothing:antialiased;-webkit-text-size-adjust:100%;Margin:0;background:#f3f3f3!important;box-sizing:border-box;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;line-height:1.3;margin:0;min-width:100%;padding:0;text-align:left;width:100%!important"> + <span class="preheader" style="color:#F5F5F5;display:none!important;font-size:1px;line-height:1px;max-height:0;max-width:0;mso-hide:all!important;opacity:0;overflow:hidden;visibility:hidden"> + </span> + <table class="body" style="-webkit-font-smoothing:antialiased;Margin:0;background:#f3f3f3!important;border-collapse:collapse;border-spacing:0;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;height:100%;line-height:1.3;margin:0;padding:0;text-align:left;vertical-align:top;width:100%"> + <tr style="padding:0;text-align:left;vertical-align:top"> + <td class="center" align="center" valign="top" style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;hyphens:auto;line-height:1.3;margin:0;padding:0;text-align:left;vertical-align:top;word-wrap:break-word"> + <center data-parsed="" style="min-width:580px;width:100%"><table align="center" class="wrapper header float-center" style="Margin:0 auto;background:#8a8a8a;background-color:#0082c9;border-collapse:collapse;border-spacing:0;float:none;margin:0 auto;padding:0;text-align:center;vertical-align:top;width:100%"> + <tr style="padding:0;text-align:left;vertical-align:top"> + <td class="wrapper-inner" style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;hyphens:auto;line-height:1.3;margin:0;padding:20px;text-align:left;vertical-align:top;word-wrap:break-word"> + <table align="center" class="container" style="Margin:0 auto;background:0 0;border-collapse:collapse;border-spacing:0;margin:0 auto;padding:0;text-align:inherit;vertical-align:top;width:580px"> + <tbody> + <tr style="padding:0;text-align:left;vertical-align:top"> + <td style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;hyphens:auto;line-height:1.3;margin:0;padding:0;text-align:left;vertical-align:top;word-wrap:break-word"> + <table class="row collapse" style="border-collapse:collapse;border-spacing:0;display:table;padding:0;position:relative;text-align:left;vertical-align:top;width:100%"> + <tbody> + <tr style="padding:0;text-align:left;vertical-align:top"> + <center data-parsed="" style="min-width:580px;width:100%"> + <img class="logo float-center" src="https://example.org/img/logo-mail-header.png?v=48" alt="logo" align="center" style="-ms-interpolation-mode:bicubic;Margin:0 auto;clear:both;display:block;float:none;margin:0 auto;max-height:100%;max-width:100px;outline:0;text-align:center;text-decoration:none;width:auto"> + </center> + </tr> + </tbody> + </table> + </td> + </tr> + </tbody> + </table> + </td> + </tr> +</table> +<table class="spacer float-center" style="Margin:0 auto;border-collapse:collapse;border-spacing:0;float:none;margin:0 auto;padding:0;text-align:center;vertical-align:top;width:100%"> + <tbody> + <tr style="padding:0;text-align:left;vertical-align:top"> + <td height="80px" style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:80px;font-weight:400;hyphens:auto;line-height:80px;margin:0;mso-line-height-rule:exactly;padding:0;text-align:left;vertical-align:top;word-wrap:break-word"> </td> + </tr> + </tbody> +</table><table align="center" class="container main-heading float-center" style="Margin:0 auto;background:0 0!important;border-collapse:collapse;border-spacing:0;float:none;margin:0 auto;padding:0;text-align:center;vertical-align:top;width:580px"> + <tbody> + <tr style="padding:0;text-align:left;vertical-align:top"> + <td style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;hyphens:auto;line-height:1.3;margin:0;padding:0;text-align:left;vertical-align:top;word-wrap:break-word"> + <h1 class="text-center" style="Margin:0;Margin-bottom:10px;color:inherit;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:24px;font-weight:400;line-height:1.3;margin:0;margin-bottom:10px;padding:0;text-align:center;word-wrap:normal">Welcome aboard</h1> + </td> + </tr> + </tbody> +</table> +<table class="spacer float-center" style="Margin:0 auto;border-collapse:collapse;border-spacing:0;float:none;margin:0 auto;padding:0;text-align:center;vertical-align:top;width:100%"> + <tbody> + <tr style="padding:0;text-align:left;vertical-align:top"> + <td height="40px" style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:40px;font-weight:400;hyphens:auto;line-height:40px;margin:0;mso-line-height-rule:exactly;padding:0;text-align:left;vertical-align:top;word-wrap:break-word"> </td> + </tr> + </tbody> +</table><table align="center" class="wrapper content float-center" style="Margin:0 auto;border-collapse:collapse;border-spacing:0;float:none;margin:0 auto;padding:0;text-align:center;vertical-align:top;width:100%"> + <tr style="padding:0;text-align:left;vertical-align:top"> + <td class="wrapper-inner" style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;hyphens:auto;line-height:1.3;margin:0;padding:0;text-align:left;vertical-align:top;word-wrap:break-word"> + <table align="center" class="container has-shadow" style="Margin:0 auto;background:#fefefe;border-collapse:collapse;border-spacing:0;box-shadow:0 1px 2px 0 rgba(0,0,0,.2),0 1px 3px 0 rgba(0,0,0,.1);margin:0 auto;padding:0;text-align:inherit;vertical-align:top;width:580px"> + <tbody> + <tr style="padding:0;text-align:left;vertical-align:top"> + <td style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;hyphens:auto;line-height:1.3;margin:0;padding:0;text-align:left;vertical-align:top;word-wrap:break-word"> + <table class="spacer" style="border-collapse:collapse;border-spacing:0;padding:0;text-align:left;vertical-align:top;width:100%"> + <tbody> + <tr style="padding:0;text-align:left;vertical-align:top"> + <td height="60px" style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:60px;font-weight:400;hyphens:auto;line-height:60px;margin:0;mso-line-height-rule:exactly;padding:0;text-align:left;vertical-align:top;word-wrap:break-word"> </td> + </tr> + </tbody> + </table><table class="row description" style="border-collapse:collapse;border-spacing:0;display:table;padding:0;position:relative;text-align:left;vertical-align:top;width:100%"> + <tbody> + <tr style="padding:0;text-align:left;vertical-align:top"> + <th class="small-12 large-12 columns first last" style="Margin:0 auto;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;line-height:1.3;margin:0 auto;padding:0;padding-bottom:30px;padding-left:30px;padding-right:30px;text-align:left;width:550px"> + <table style="border-collapse:collapse;border-spacing:0;padding:0;text-align:left;vertical-align:top;width:100%"> + <tr style="padding:0;text-align:left;vertical-align:top"> + <th style="Margin:0;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;line-height:1.3;margin:0;padding:0;text-align:left"> + <p class="text-left" style="Margin:0;Margin-bottom:10px;color:#777;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;line-height:1.3;margin:0;margin-bottom:10px;padding:0;text-align:left">You have now an Nextcloud account, you can add, protect, and share your data.</p> + </th> + <th class="expander" style="Margin:0;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;line-height:1.3;margin:0;padding:0!important;text-align:left;visibility:hidden;width:0"></th> + </tr> + </table> + </th> + </tr> + </tbody> +</table><table class="row description" style="border-collapse:collapse;border-spacing:0;display:table;padding:0;position:relative;text-align:left;vertical-align:top;width:100%"> + <tbody> + <tr style="padding:0;text-align:left;vertical-align:top"> + <th class="small-12 large-12 columns first last" style="Margin:0 auto;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;line-height:1.3;margin:0 auto;padding:0;padding-bottom:30px;padding-left:30px;padding-right:30px;text-align:left;width:550px"> + <table style="border-collapse:collapse;border-spacing:0;padding:0;text-align:left;vertical-align:top;width:100%"> + <tr style="padding:0;text-align:left;vertical-align:top"> + <th style="Margin:0;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;line-height:1.3;margin:0;padding:0;text-align:left"> + <p class="text-left" style="Margin:0;Margin-bottom:10px;color:#777;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;line-height:1.3;margin:0;margin-bottom:10px;padding:0;text-align:left">Your username is: abc</p> + </th> + <th class="expander" style="Margin:0;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;line-height:1.3;margin:0;padding:0!important;text-align:left;visibility:hidden;width:0"></th> + </tr> + </table> + </th> + </tr> + </tbody> +</table><table class="spacer" style="border-collapse:collapse;border-spacing:0;padding:0;text-align:left;vertical-align:top;width:100%"> + <tbody> + <tr style="padding:0;text-align:left;vertical-align:top"> + <td height="50px" style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:50px;font-weight:400;hyphens:auto;line-height:50px;margin:0;mso-line-height-rule:exactly;padding:0;text-align:left;vertical-align:top;word-wrap:break-word"> </td> + </tr> + </tbody> +</table> +<table align="center" class="row btn-group" style="border-collapse:collapse;border-spacing:0;display:table;padding:0;position:relative;text-align:left;vertical-align:top;width:100%"> + <tbody> + <tr style="padding:0;text-align:left;vertical-align:top"> + <th class="small-12 large-12 columns first last" style="Margin:0 auto;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;line-height:1.3;margin:0 auto;padding:0;padding-bottom:30px;padding-left:30px;padding-right:30px;text-align:left;width:550px"> + <table style="border-collapse:collapse;border-spacing:0;padding:0;text-align:left;vertical-align:top;width:100%"> + <tr style="padding:0;text-align:left;vertical-align:top"> + <th style="Margin:0;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;line-height:1.3;margin:0;padding:0;text-align:left"> + <center data-parsed="" style="min-width:490px;width:100%"> + <table class="button btn default primary float-center" style="Margin:0 0 30px 0;border-collapse:collapse;border-spacing:0;display:inline-block;float:none;margin:0 0 30px 0;margin-right:15px;max-height:40px;max-width:200px;padding:0;text-align:center;vertical-align:top;width:auto"> + <tr style="padding:0;text-align:left;vertical-align:top"> + <td style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;hyphens:auto;line-height:1.3;margin:0;padding:0;text-align:left;vertical-align:top;word-wrap:break-word"> + <table style="border-collapse:collapse;border-spacing:0;padding:0;text-align:left;vertical-align:top;width:100%"> + <tr style="padding:0;text-align:left;vertical-align:top"> + <td style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;background:#0082c9;border:0 solid #0082c9;border-collapse:collapse!important;color:#fefefe;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;hyphens:auto;line-height:1.3;margin:0;padding:0;text-align:left;vertical-align:top;word-wrap:break-word"> + <a href="https://example.org/resetPassword/123" style="Margin:0;border:0 solid #0082c9;border-radius:2px;color:#fefefe;display:inline-block;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:regular;line-height:1.3;margin:0;padding:10px 25px 10px 25px;text-align:left;text-decoration:none">Set your password</a> + </td> + </tr> + </table> + </td> + </tr> + </table> + <table class="button btn default secondary float-center" style="Margin:0 0 30px 0;border-collapse:collapse;border-spacing:0;display:inline-block;float:none;margin:0 0 30px 0;max-height:40px;max-width:200px;padding:0;text-align:center;vertical-align:top;width:auto"> + <tr style="padding:0;text-align:left;vertical-align:top"> + <td style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;hyphens:auto;line-height:1.3;margin:0;padding:0;text-align:left;vertical-align:top;word-wrap:break-word"> + <table style="border-collapse:collapse;border-spacing:0;padding:0;text-align:left;vertical-align:top;width:100%"> + <tr style="padding:0;text-align:left;vertical-align:top"> + <td style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;background:#777;border:0 solid #777;border-collapse:collapse!important;color:#fefefe;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;hyphens:auto;line-height:1.3;margin:0;padding:0;text-align:left;vertical-align:top;word-wrap:break-word"> + <a href="https://nextcloud.com/install/#install-clients" style="Margin:0;background-color:#fff;border:0 solid #777;border-radius:2px;color:#6C6C6C!important;display:inline-block;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:regular;line-height:1.3;margin:0;outline:1px solid #CBCBCB;padding:10px 25px 10px 25px;text-align:left;text-decoration:none">Install Client</a> + </td> + </tr> + </table> + </td> + </tr> + </table> + </center> + </th> + <th class="expander" style="Margin:0;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;line-height:1.3;margin:0;padding:0!important;text-align:left;visibility:hidden;width:0"></th> + </tr> + </table> + </th> + </tr> + </tbody> +</table> + </td> + </tr> + </tbody> + </table> + </td> + </tr> +</table><table class="spacer float-center" style="Margin:0 auto;border-collapse:collapse;border-spacing:0;float:none;margin:0 auto;padding:0;text-align:center;vertical-align:top;width:100%"> + <tbody> + <tr style="padding:0;text-align:left;vertical-align:top"> + <td height="60px" style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:60px;font-weight:400;hyphens:auto;line-height:60px;margin:0;mso-line-height-rule:exactly;padding:0;text-align:left;vertical-align:top;word-wrap:break-word"> </td> + </tr> + </tbody> +</table> +<table align="center" class="wrapper footer float-center" style="Margin:0 auto;border-collapse:collapse;border-spacing:0;float:none;margin:0 auto;padding:0;text-align:center;vertical-align:top;width:100%"> + <tr style="padding:0;text-align:left;vertical-align:top"> + <td class="wrapper-inner" style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;hyphens:auto;line-height:1.3;margin:0;padding:0;text-align:left;vertical-align:top;word-wrap:break-word"> + <center data-parsed="" style="min-width:580px;width:100%"> + <table class="spacer float-center" style="Margin:0 auto;border-collapse:collapse;border-spacing:0;float:none;margin:0 auto;padding:0;text-align:center;vertical-align:top;width:100%"> + <tbody> + <tr style="padding:0;text-align:left;vertical-align:top"> + <td height="15px" style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:15px;font-weight:400;hyphens:auto;line-height:15px;margin:0;mso-line-height-rule:exactly;padding:0;text-align:left;vertical-align:top;word-wrap:break-word"> </td> + </tr> + </tbody> + </table> + <p class="text-center float-center" align="center" style="Margin:0;Margin-bottom:10px;color:#C8C8C8;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:12px;font-weight:400;line-height:16px;margin:0;margin-bottom:10px;padding:0;text-align:center">TestCloud - A safe home for your data<br></p> + </center> + </td> + </tr> +</table> </center> + </td> + </tr> + </table> + <!-- prevent Gmail on iOS font size manipulation --> + <div style="display:none;white-space:nowrap;font:15px courier;line-height:0"> </div> + </body> +</html>
\ 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 @@ <table class="row collapse" style="border-collapse:collapse;border-spacing:0;display:table;padding:0;position:relative;text-align:left;vertical-align:top;width:100%"> <tbody> <tr style="padding:0;text-align:left;vertical-align:top"> - <center data-parsed="" style="min-width:580px;width:100%"><!-- TODO --> - <img class="logo float-center" src="https://example.org/img/logo-mail-header.png" alt="logo" align="center" style="-ms-interpolation-mode:bicubic;Margin:0 auto;clear:both;display:block;float:none;margin:0 auto;max-height:100%;max-width:100px;outline:0;text-align:center;text-decoration:none;width:auto"> + <center data-parsed="" style="min-width:580px;width:100%"> + <img class="logo float-center" src="https://example.org/img/logo-mail-header.png?v=48" alt="logo" align="center" style="-ms-interpolation-mode:bicubic;Margin:0 auto;clear:both;display:block;float:none;margin:0 auto;max-height:100%;max-width:100px;outline:0;text-align:center;text-decoration:none;width:auto"> </center> </tr> </tbody> @@ -165,8 +165,7 @@ <table align="center" class="wrapper footer float-center" style="Margin:0 auto;border-collapse:collapse;border-spacing:0;float:none;margin:0 auto;padding:0;text-align:center;vertical-align:top;width:100%"> <tr style="padding:0;text-align:left;vertical-align:top"> <td class="wrapper-inner" style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;hyphens:auto;line-height:1.3;margin:0;padding:0;text-align:left;vertical-align:top;word-wrap:break-word"> - <center data-parsed="" style="min-width:580px;width:100%"><!-- TODO --> - <img class="logo float-center" src="https://example.org/img/logo-mail-footer.png" alt="logo" align="center" style="-ms-interpolation-mode:bicubic;Margin:0 auto;clear:both;display:block;float:none;margin:0 auto;max-height:100%;max-width:75px;outline:0;text-align:center;text-decoration:none;width:auto"> + <center data-parsed="" style="min-width:580px;width:100%"> <table class="spacer float-center" style="Margin:0 auto;border-collapse:collapse;border-spacing:0;float:none;margin:0 auto;padding:0;text-align:center;vertical-align:top;width:100%"> <tbody> <tr style="padding:0;text-align:left;vertical-align:top"> @@ -174,7 +173,7 @@ </tr> </tbody> </table> - <p class="text-center float-center" align="center" style="Margin:0;Margin-bottom:10px;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:12px;font-weight:400;line-height:16px;margin:0;margin-bottom:10px;padding:0;text-align:center">TestCloud - A safe home for your data<br>This is an automatically generated email, please do not reply.</p> + <p class="text-center float-center" align="center" style="Margin:0;Margin-bottom:10px;color:#C8C8C8;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:12px;font-weight:400;line-height:16px;margin:0;margin-bottom:10px;padding:0;text-align:center">TestCloud - A safe home for your data<br>This is an automatically generated email, please do not reply.</p> </center> </td> </tr> 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<br>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()); } |