From 0560e6991323c156e548792c5fb1f82791868d90 Mon Sep 17 00:00:00 2001 From: Morris Jobke Date: Thu, 6 Apr 2017 13:20:47 -0500 Subject: [PATCH 1/4] New layout for welcome email * thanks to @espina2 for make this nice design * the button says "Set password" if the admin didn't specified a password Signed-off-by: Morris Jobke --- lib/private/Mail/EMailTemplate.php | 392 ++++++++++++++++++ lib/private/Mail/IEMailTemplate.php | 107 +++++ settings/Controller/UsersController.php | 39 +- settings/templates/email.new_user.php | 35 -- .../templates/email.new_user_plain_text.php | 10 - .../Controller/UsersControllerTest.php | 79 ++-- tests/data/emails/new-account-email.html | 188 +++++++++ tests/data/emails/new-account-email.txt | 12 + tests/lib/Mail/EMailTemplateTest.php | 75 ++++ 9 files changed, 846 insertions(+), 91 deletions(-) create mode 100644 lib/private/Mail/EMailTemplate.php create mode 100644 lib/private/Mail/IEMailTemplate.php delete mode 100644 settings/templates/email.new_user.php delete mode 100644 settings/templates/email.new_user_plain_text.php create mode 100644 tests/data/emails/new-account-email.html create mode 100644 tests/data/emails/new-account-email.txt create mode 100644 tests/lib/Mail/EMailTemplateTest.php diff --git a/lib/private/Mail/EMailTemplate.php b/lib/private/Mail/EMailTemplate.php new file mode 100644 index 0000000000..7a884dd928 --- /dev/null +++ b/lib/private/Mail/EMailTemplate.php @@ -0,0 +1,392 @@ + + * + * @author Morris Jobke + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +namespace OC\Mail; + + +/** + * Class EMailTemplate + * + * addBodyText and addBodyButtonGroup automatically opens the body + * addFooter, renderHTML, renderText automatically closes the body and the HTML if opened + * + * @package OC\Mail + */ +class EMailTemplate implements IEMailTemplate { + + /** @var \OC_Defaults */ + protected $defaults; + + /** @var string */ + protected $htmlBody = ''; + /** @var string */ + protected $plainBody = ''; + /** @var bool indicated if the footer is added */ + protected $headerAdded = false; + /** @var bool indicated if the body is already opened */ + protected $bodyOpened = false; + /** @var bool indicated if the footer is added */ + protected $footerAdded = false; + + protected $head = << + + + + + + + + + + + + + +
+
+EOF; + + protected $tail = << +
+ +
                                                           
+ + +EOF; + + protected $header = << + + + + + + + + +
+ + + +
+ +
+ + +
+
+ + + + + + + + + +
 
+EOF; + + protected $heading = << + + + +

%s

+ + + + + + + + + + +
 
+EOF; + + protected $bodyBegin = << + + + + + + + + + + +
+ + + + + + +
 
+EOF; + + protected $bodyText = << +
+ + + + + +
+

%s

+
+
+EOF; + + protected $buttonGroup = << + + +   + + + + + + + + + +
+ + + + + +
+
+ + + + +
+ + + + +
+ %s +
+
+ + + + +
+ + + + +
+ %s +
+
+
+
+
+EOF; + + protected $bodyEnd = << + + + + + + +EOF; + + protected $footer = << + + +   + + + + + + + + +EOF; + + + public function __construct(\OC_Defaults $defaults) { + $this->defaults = $defaults; + + $this->htmlBody .= $this->head; + } + + /** + * Adds a header to the email + * + * @param string $logoUrl + */ + public function addHeader($logoUrl) { + if ($this->headerAdded) { + return; + } + $this->headerAdded = true; + + $this->htmlBody .= vsprintf($this->header, [$this->defaults->getColorPrimary(), $logoUrl]); + } + + /** + * Adds a heading to the email + * + * @param string $title + */ + public function addHeading($title) { + if ($this->footerAdded) { + return; + } + + $this->htmlBody .= vsprintf($this->heading, [$title]); + $this->plainBody .= $title . PHP_EOL . PHP_EOL; + } + + /** + * Adds a paragraph to the body of the email + * + * @param string $text + */ + public function addBodyText($text) { + if ($this->footerAdded) { + return; + } + + if (!$this->bodyOpened) { + $this->htmlBody .= $this->bodyBegin; + $this->bodyOpened = true; + } + + $this->htmlBody .= vsprintf($this->bodyText, [$text]); + $this->plainBody .= $text . PHP_EOL . PHP_EOL; + } + + /** + * Adds a button group of two buttons to the body of the email + * + * @param string $textLeft Text of left button + * @param string $urlLeft URL of left button + * @param string $textRight Text of right button + * @param string $urlRight URL of right button + */ + public function addBodyButtonGroup($textLeft, $urlLeft, $textRight, $urlRight) { + if ($this->footerAdded) { + return; + } + + if (!$this->bodyOpened) { + $this->htmlBody .= $this->bodyBegin; + $this->bodyOpened = true; + } + + $color = $this->defaults->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; + + } + + /** + * Adds a logo and a text to the footer.
in the text will be replaced by new lines in the plain text email + * + * @param string $logoUrl + * @param string $text + */ + public function addFooter($logoUrl, $text) { + if ($this->footerAdded) { + return; + } + $this->footerAdded = true; + + if ($this->bodyOpened) { + $this->htmlBody .= $this->bodyEnd; + $this->bodyOpened = false; + } + $this->htmlBody .= vsprintf($this->footer, [$logoUrl, $text]); + $this->htmlBody .= $this->tail; + $this->plainBody .= '--' . PHP_EOL; + $this->plainBody .= str_replace('
', PHP_EOL, $text); + } + + /** + * Returns the rendered HTML email as string + * + * @return string + */ + public function renderHTML() { + if (!$this->footerAdded) { + $this->footerAdded = true; + if ($this->bodyOpened) { + $this->htmlBody .= $this->bodyEnd; + } + $this->htmlBody .= $this->tail; + } + return $this->htmlBody; + } + + /** + * Returns the rendered plain text email as string + * + * @return string + */ + public function renderText() { + if (!$this->footerAdded) { + $this->footerAdded = true; + if ($this->bodyOpened) { + $this->htmlBody .= $this->bodyEnd; + } + $this->htmlBody .= $this->tail; + } + return $this->plainBody; + } +} + diff --git a/lib/private/Mail/IEMailTemplate.php b/lib/private/Mail/IEMailTemplate.php new file mode 100644 index 0000000000..5bf2b8e439 --- /dev/null +++ b/lib/private/Mail/IEMailTemplate.php @@ -0,0 +1,107 @@ + + * + * @author Morris Jobke + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +namespace OC\Mail; + +/** + * Interface IEMailTemplate + * + * Interface to a class that allows to build HTML emails + * + * Example: + * + * 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->addBodyButtonGroup( + * 'Set your password', 'https://example.org/resetPassword/q1234567890qwertz', + * 'Install Client', 'https://nextcloud.com/install/#install-clients' + * ); + * + * $emailTemplate->addFooter( + * 'https://example.org/img/logo-mail-footer.png', + * 'Nextcloud - a safe home for your data
This is an automatically generated email, please do not reply.' + * ); + * + * $htmlContent = $emailTemplate->renderHTML(); + * $plainContent = $emailTemplate->renderText(); + */ +interface IEMailTemplate { + /** + * Adds a header to the email + * + * @param string $logoUrl + */ + public function addHeader($logoUrl); + + /** + * Adds a heading to the email + * + * @param string $title + */ + public function addHeading($title); + + /** + * Adds a paragraph to the body of the email + * + * @param string $text + */ + public function addBodyText($text); + + /** + * Adds a button group of two buttons to the body of the email + * + * @param string $textLeft Text of left button + * @param string $urlLeft URL of left button + * @param string $textRight Text of right button + * @param string $urlRight URL of right button + */ + public function addBodyButtonGroup($textLeft, $urlLeft, $textRight, $urlRight); + + /** + * Adds a logo and a text to the footer.
in the text will be replaced by new lines in the plain text email + * + * @param string $logoUrl + * @param string $text + */ + public function addFooter($logoUrl, $text); + + /** + * Returns the rendered HTML email as string + * + * @return string + */ + public function renderHTML(); + + /** + * Returns the rendered plain text email as string + * + * @return string + */ + public function renderText(); +} \ No newline at end of file diff --git a/settings/Controller/UsersController.php b/settings/Controller/UsersController.php index 19c5b06816..3688cb7b7e 100644 --- a/settings/Controller/UsersController.php +++ b/settings/Controller/UsersController.php @@ -33,6 +33,7 @@ namespace OC\Settings\Controller; use OC\Accounts\AccountManager; use OC\AppFramework\Http; use OC\ForbiddenException; +use OC\Mail\EMailTemplate; use OC\User\User; use OCP\App\IAppManager; use OCP\AppFramework\Controller; @@ -443,17 +444,39 @@ class UsersController extends Controller { $link = $this->urlGenerator->getAbsoluteURL('/'); } - // data for the mail template - $mailData = array( - 'username' => $username, - 'url' => $link + + + $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 Nextcloud account, you can add, protect, and share your data.')); + $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' ); - $mail = new TemplateResponse('settings', 'email.new_user', $mailData, 'blank'); - $mailContent = $mail->render(); + $emailTemplate->addFooter( + $this->urlGenerator->getAbsoluteURL($this->urlGenerator->imagePath('', 'logo-mail-footer.png')), + $this->defaults->getName() . ' - ' . $this->defaults->getSlogan() . '
' . $this->l10n->t('This is an automatically generated email, please do not reply.') + ); - $mail = new TemplateResponse('settings', 'email.new_user_plain_text', $mailData, 'blank'); - $plainTextMailContent = $mail->render(); + $mailContent = $emailTemplate->renderHTML(); + $plainTextMailContent = $emailTemplate->renderText(); $subject = $this->l10n->t('Your %s account was created', [$this->defaults->getName()]); diff --git a/settings/templates/email.new_user.php b/settings/templates/email.new_user.php deleted file mode 100644 index 9418c21c6c..0000000000 --- a/settings/templates/email.new_user.php +++ /dev/null @@ -1,35 +0,0 @@ - - -
- - - - - - - - - - - - - - - - - -
- <?php p($theme->getName()); ?> -
 
  - t('Hey there,

just letting you know that you now have a %s account.

Your username: %s
Access it: %s

', array($theme->getName(), $_['username'], $_['url'], $_['url']))); - - // TRANSLATORS term at the end of a mail - p($l->t('Cheers!')); - ?> -
 
 --
- getName()); ?> - - getSlogan()); ?> -
getBaseUrl());?> -
 
-
diff --git a/settings/templates/email.new_user_plain_text.php b/settings/templates/email.new_user_plain_text.php deleted file mode 100644 index 2cc70ddfa2..0000000000 --- a/settings/templates/email.new_user_plain_text.php +++ /dev/null @@ -1,10 +0,0 @@ -t("Hey there,\n\njust letting you know that you now have a %s account.\n\nYour username: %s\nAccess it: %s\n\n", array($theme->getName(), $_['username'], $_['url']))); - -// TRANSLATORS term at the end of a mail -p($l->t("Cheers!")); -?> - - -- -getName() . ' - ' . $theme->getSlogan()); ?> -getBaseUrl()); diff --git a/tests/Settings/Controller/UsersControllerTest.php b/tests/Settings/Controller/UsersControllerTest.php index 3cdde1b2d2..2ed298df2d 100644 --- a/tests/Settings/Controller/UsersControllerTest.php +++ b/tests/Settings/Controller/UsersControllerTest.php @@ -12,6 +12,7 @@ namespace Tests\Settings\Controller; use OC\Accounts\AccountManager; use OC\Group\Manager; +use OC\Mail\EMailTemplate; use OC\Settings\Controller\UsersController; use OCP\App\IAppManager; use OCP\AppFramework\Http; @@ -1427,32 +1428,33 @@ class UsersControllerTest extends \Test\TestCase { ->expects($this->at(1)) ->method('setSubject') ->with('Your account was created'); - $htmlBody = new Http\TemplateResponse( - 'settings', - 'email.new_user', - [ - 'username' => 'foo', - 'url' => '', - ], - 'blank' + + $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/resetPassword/123', + 'Install Client', 'https://nextcloud.com/install/#install-clients' + ); + + $emailTemplate->addFooter( + 'https://example.org/img/logo-mail-footer.png', + 'TestCloud - A safe home for your data
This is an automatically generated email, please do not reply.' ); $message ->expects($this->at(2)) ->method('setHtmlBody') - ->with($htmlBody->render()); - $plainBody = new Http\TemplateResponse( - 'settings', - 'email.new_user_plain_text', - [ - 'username' => 'foo', - 'url' => '', - ], - 'blank' - ); + ->with($emailTemplate->renderHTML()); $message ->expects($this->at(3)) ->method('setPlainBody') - ->with($plainBody->render()); + ->with($emailTemplate->renderText()); $message ->expects($this->at(4)) ->method('setFrom') @@ -2325,32 +2327,33 @@ class UsersControllerTest extends \Test\TestCase { ->expects($this->at(1)) ->method('setSubject') ->with('Your account was created'); - $htmlBody = new Http\TemplateResponse( - 'settings', - 'email.new_user', - [ - 'username' => 'foo', - 'url' => 'link-with-my-token', - ], - 'blank' + + $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/resetPassword/123', + 'Install Client', 'https://nextcloud.com/install/#install-clients' + ); + + $emailTemplate->addFooter( + 'https://example.org/img/logo-mail-footer.png', + 'TestCloud - A safe home for your data
This is an automatically generated email, please do not reply.' ); $message ->expects($this->at(2)) ->method('setHtmlBody') - ->with($htmlBody->render()); - $plainBody = new Http\TemplateResponse( - 'settings', - 'email.new_user_plain_text', - [ - 'username' => 'foo', - 'url' => 'link-with-my-token', - ], - 'blank' - ); + ->with($emailTemplate->renderHTML()); $message ->expects($this->at(3)) ->method('setPlainBody') - ->with($plainBody->render()); + ->with($emailTemplate->renderText()); $message ->expects($this->at(4)) ->method('setFrom') diff --git a/tests/data/emails/new-account-email.html b/tests/data/emails/new-account-email.html new file mode 100644 index 0000000000..9b9155fa1d --- /dev/null +++ b/tests/data/emails/new-account-email.html @@ -0,0 +1,188 @@ + + + + + + + + + + + + + + +
+
+ + + +
+ + + + + + +
+ + + +
+ +
+ + +
+
+
+ + + + + + +
 
+ + + + + +
+

Welcome aboard

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

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

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

Your username is: abc

+
+
+ + + + + +
 
+ + + + + + +
+ + + + + +
+
+ + + + +
+ + + + +
+ Set your password +
+
+ + + + +
+ + + + +
+ Install Client +
+
+
+
+
+
+
+ + + + + +
 
+ + + + +
+
+ +
                                                           
+ + \ No newline at end of file diff --git a/tests/data/emails/new-account-email.txt b/tests/data/emails/new-account-email.txt new file mode 100644 index 0000000000..6732d806d7 --- /dev/null +++ b/tests/data/emails/new-account-email.txt @@ -0,0 +1,12 @@ +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 +This is an automatically generated email, please do not reply. \ No newline at end of file diff --git a/tests/lib/Mail/EMailTemplateTest.php b/tests/lib/Mail/EMailTemplateTest.php new file mode 100644 index 0000000000..3acb742aec --- /dev/null +++ b/tests/lib/Mail/EMailTemplateTest.php @@ -0,0 +1,75 @@ + + * + * @author Morris Jobke + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +namespace Test\Mail; + +use OC\Mail\EMailTemplate; +use OC_Defaults; +use Test\TestCase; + +class EMailTemplateTest extends TestCase { + /** @var OC_Defaults */ + private $defaults; + + function setUp() { + parent::setUp(); + + $this->defaults = $this->getMockBuilder('\OC_Defaults') + ->disableOriginalConstructor()->getMock(); + + $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( + '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', + 'TestCloud - A safe home for your data
This is an automatically generated email, please do not reply.' + ); + + $expectedHTML = file_get_contents(\OC::$SERVERROOT . '/tests/data/emails/new-account-email.html'); + $this->assertSame($expectedHTML, $emailTemplate->renderHTML()); + + + $expectedTXT = file_get_contents(\OC::$SERVERROOT . '/tests/data/emails/new-account-email.txt'); + $this->assertSame($expectedTXT, $emailTemplate->renderText()); + } + + +} From 1be75e8db8f583476f1cd03498afd608fce6408d Mon Sep 17 00:00:00 2001 From: Lukas Reschke Date: Fri, 7 Apr 2017 10:48:47 +0200 Subject: [PATCH 2/4] Fix tests Signed-off-by: Lukas Reschke --- settings/Controller/UsersController.php | 16 +-- .../Controller/UsersControllerTest.php | 134 +++++++++++++----- 2 files changed, 106 insertions(+), 44 deletions(-) diff --git a/settings/Controller/UsersController.php b/settings/Controller/UsersController.php index 3688cb7b7e..c7b2c2537d 100644 --- a/settings/Controller/UsersController.php +++ b/settings/Controller/UsersController.php @@ -444,19 +444,17 @@ class UsersController extends Controller { $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) { + $displayName = $user->getDisplayName(); + if ($displayName === $username) { $emailTemplate->addHeading($this->l10n->t('Welcome aboard')); } else { - $emailTemplate->addHeading($this->l10n->t('Welcome aboard %s', $displayname)); + $emailTemplate->addHeading($this->l10n->t('Welcome aboard %s', [$displayName])); } - $emailTemplate->addBodyText($this->l10n->t('You have now an Nextcloud account, you can add, protect, and share your data.')); + $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) { @@ -466,8 +464,10 @@ class UsersController extends Controller { } $emailTemplate->addBodyButtonGroup( - $leftButtonText, $link, - $this->l10n->t('Install Client'), 'https://nextcloud.com/install/#install-clients' + $leftButtonText, + $link, + $this->l10n->t('Install Client'), + 'https://nextcloud.com/install/#install-clients' ); $emailTemplate->addFooter( diff --git a/tests/Settings/Controller/UsersControllerTest.php b/tests/Settings/Controller/UsersControllerTest.php index 2ed298df2d..52a9a1cc84 100644 --- a/tests/Settings/Controller/UsersControllerTest.php +++ b/tests/Settings/Controller/UsersControllerTest.php @@ -129,7 +129,7 @@ class UsersControllerTest extends \Test\TestCase { $this->logger, $this->defaults, $this->mailer, - 'no-reply@owncloud.com', + 'no-reply@nextcloud.com', $this->urlGenerator, $this->appManager, $this->avatarManager, @@ -153,7 +153,7 @@ class UsersControllerTest extends \Test\TestCase { $this->logger, $this->defaults, $this->mailer, - 'no-reply@owncloud.com', + 'no-reply@nextcloud.com', $this->urlGenerator, $this->appManager, $this->avatarManager, @@ -1427,26 +1427,56 @@ class UsersControllerTest extends \Test\TestCase { $message ->expects($this->at(1)) ->method('setSubject') - ->with('Your account was created'); + ->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/resetPassword/123', + 'Go to Nextcloud', 'https://example.org/', 'Install Client', 'https://nextcloud.com/install/#install-clients' ); - $emailTemplate->addFooter( 'https://example.org/img/logo-mail-footer.png', - 'TestCloud - A safe home for your data
This is an automatically generated email, please do not reply.' + 'Nextcloud - A safe home for your data
This is an automatically generated email, please do not reply.' ); + $message ->expects($this->at(2)) ->method('setHtmlBody') @@ -1458,7 +1488,7 @@ class UsersControllerTest extends \Test\TestCase { $message ->expects($this->at(4)) ->method('setFrom') - ->with(['no-reply@owncloud.com' => null]); + ->with(['no-reply@nextcloud.com' => 'Nextcloud']); $this->mailer ->expects($this->at(0)) @@ -1485,6 +1515,9 @@ class UsersControllerTest extends \Test\TestCase { $user ->method('getUID') ->will($this->returnValue('foo')); + $user + ->method('getDisplayName') + ->will($this->returnValue('foo')); $user ->expects($this->once()) ->method('getBackendClassName') @@ -2264,20 +2297,24 @@ class UsersControllerTest extends \Test\TestCase { public function testCreateSuccessfulWithoutPasswordAndWithEmail() { - $controller = $this->getController(true); - $user = $this->getMockBuilder('\OC\User\User') ->disableOriginalConstructor()->getMock(); $user ->method('getHome') - ->will($this->returnValue('/home/user')); + ->willReturn('/home/user'); $user ->method('getUID') - ->will($this->returnValue('foo')); + ->willReturn('foo'); + $user + ->method('getDisplayName') + ->willReturn('John Doe'); + $user + ->method('getEmailAddress') + ->willReturn('abc@example.org'); $user ->expects($this->once()) ->method('getBackendClassName') - ->will($this->returnValue('bar')); + ->willReturn('bar'); $this->userManager ->expects($this->once()) @@ -2310,11 +2347,6 @@ class UsersControllerTest extends \Test\TestCase { ISecureRandom::CHAR_LOWER . ISecureRandom::CHAR_UPPER) ->will($this->returnValue('mytoken')); - $this->urlGenerator - ->expects($this->once()) - ->method('linkToRouteAbsolute') - ->with('core.lost.resetform', ['userId' => 'foo', 'token' => 'mytoken']) - ->will($this->returnValue('link-with-my-token')); $controller = $this->getController(true); $message = $this->getMockBuilder('\OC\Mail\Message') @@ -2326,26 +2358,56 @@ class UsersControllerTest extends \Test\TestCase { $message ->expects($this->at(1)) ->method('setSubject') - ->with('Your account was created'); + ->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'); + $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( - 'Go to Nextcloud', 'https://example.org/resetPassword/123', + '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', - 'TestCloud - A safe home for your data
This is an automatically generated email, please do not reply.' + 'Nextcloud - A safe home for your data
This is an automatically generated email, please do not reply.' ); + $message ->expects($this->at(2)) ->method('setHtmlBody') @@ -2357,7 +2419,7 @@ class UsersControllerTest extends \Test\TestCase { $message ->expects($this->at(4)) ->method('setFrom') - ->with(['no-reply@owncloud.com' => null]); + ->with(['no-reply@nextcloud.com' => 'Nextcloud']); $this->mailer ->expects($this->at(0)) @@ -2374,19 +2436,19 @@ class UsersControllerTest extends \Test\TestCase { ->with($message); $expectedResponse = new DataResponse( - array( + [ 'name' => 'foo', 'groups' => null, 'storageLocation' => '/home/user', 'backend' => 'bar', - 'lastLogin' => null, - 'displayname' => null, + 'lastLogin' => 0, + 'displayname' => 'John Doe', 'quota' => null, 'subadmin' => array(), - 'email' => null, + 'email' => 'abc@example.org', 'isRestoreDisabled' => false, 'isAvatarAvailable' => true, - ), + ], Http::STATUS_CREATED ); $response = $controller->create('foo', '', array(), 'abc@example.org'); From 281ad406e88d36c1492c7aefd8ef28762379f9e3 Mon Sep 17 00:00:00 2001 From: Lukas Reschke Date: Fri, 7 Apr 2017 14:51:05 +0200 Subject: [PATCH 3/4] Add support for theming Add support for theming in generated emails and simplify API Signed-off-by: Lukas Reschke --- .../lib/AppInfo/Application.php | 16 + .../lib/Controller/UsersController.php | 34 +- .../tests/Controller/UsersControllerTest.php | 238 ++----- apps/theming/lib/ThemingDefaults.php | 55 +- apps/theming/tests/ThemingDefaultsTest.php | 57 +- lib/private/Mail/EMailTemplate.php | 56 +- lib/private/Mail/IEMailTemplate.php | 27 +- lib/private/Server.php | 4 +- settings/Application.php | 23 +- settings/Controller/UsersController.php | 102 +-- settings/Mailer/NewUserMailHelper.php | 166 +++++ .../Controller/UsersControllerTest.php | 210 +----- .../Settings/Mailer/NewUserMailHelperTest.php | 639 ++++++++++++++++++ .../data/emails/new-account-email-custom.html | 187 +++++ .../data/emails/new-account-email-custom.txt | 11 + tests/data/emails/new-account-email.html | 9 +- tests/lib/Mail/EMailTemplateTest.php | 110 ++- 17 files changed, 1368 insertions(+), 576 deletions(-) create mode 100644 settings/Mailer/NewUserMailHelper.php create mode 100644 tests/Settings/Mailer/NewUserMailHelperTest.php create mode 100644 tests/data/emails/new-account-email-custom.html create mode 100644 tests/data/emails/new-account-email-custom.txt diff --git a/apps/provisioning_api/lib/AppInfo/Application.php b/apps/provisioning_api/lib/AppInfo/Application.php index 2d6a82e2ff..fd03fd41e1 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 9155d34276..0ccbc978a6 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 b5b63319d3..0cbcccebf6 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 5a863b1eb2..d4dc56d3ba 100644 --- a/apps/theming/lib/ThemingDefaults.php +++ b/apps/theming/lib/ThemingDefaults.php @@ -1,6 +1,7 @@ + * @copyright Copyright (c) 2017 Lukas Reschke * * @license GNU AGPL version 3 or any later version * @@ -19,15 +20,14 @@ * */ - namespace OCA\Theming; +use OCP\Files\IAppData; use OCP\ICacheFactory; use OCP\IConfig; use OCP\IL10N; use OCP\IURLGenerator; -use OCP\Files\IRootFolder; use OCP\Util; class ThemingDefaults extends \OC_Defaults { @@ -38,8 +38,8 @@ class ThemingDefaults extends \OC_Defaults { private $l; /** @var IURLGenerator */ private $urlGenerator; - /** @var IRootFolder */ - private $rootFolder; + /** @var IAppData */ + private $appData; /** @var ICacheFactory */ private $cacheFactory; /** @var string */ @@ -58,21 +58,21 @@ class ThemingDefaults extends \OC_Defaults { * @param IL10N $l * @param IURLGenerator $urlGenerator * @param \OC_Defaults $defaults - * @param IRootFolder $rootFolder + * @param IAppData $appData * @param ICacheFactory $cacheFactory */ public function __construct(IConfig $config, IL10N $l, IURLGenerator $urlGenerator, \OC_Defaults $defaults, - IRootFolder $rootFolder, + IAppData $appData, ICacheFactory $cacheFactory ) { parent::__construct(); $this->config = $config; $this->l = $l; $this->urlGenerator = $urlGenerator; - $this->rootFolder = $rootFolder; + $this->appData = $appData; $this->cacheFactory = $cacheFactory; $this->name = $defaults->getName(); @@ -130,11 +130,19 @@ class ThemingDefaults extends \OC_Defaults { */ public function getLogo() { $logo = $this->config->getAppValue('theming', 'logoMime'); - if(!$logo || !$this->rootFolder->nodeExists('/themedinstancelogo')) { - return $this->urlGenerator->imagePath('core','logo.svg'); - } else { - return $this->urlGenerator->linkToRoute('theming.Theming.getLogo'); + + $logoExists = true; + try { + $this->appData->getFolder('images')->getFile('logo'); + } catch (\Exception $e) { + $logoExists = false; } + + if(!$logo || !$logoExists) { + return $this->urlGenerator->imagePath('core','logo.svg'); + } + + 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')) { - return $this->urlGenerator->imagePath('core','background.jpg'); - } else { - return $this->urlGenerator->linkToRoute('theming.Theming.getLoginBackground'); + + $backgroundExists = true; + try { + $this->appData->getFolder('images')->getFile('background'); + } catch (\Exception $e) { + $backgroundExists = false; } + + if(!$backgroundLogo || !$backgroundExists) { + return $this->urlGenerator->imagePath('core','background.jpg'); + } + + return $this->urlGenerator->linkToRoute('theming.Theming.getLoginBackground'); } /** @@ -174,6 +190,15 @@ class ThemingDefaults extends \OC_Defaults { return $value; } + /** + * Gets the current cache buster count + * + * @return string + */ + public function getCacheBusterCounter() { + return $this->config->getAppValue('theming', 'cachebuster', '0'); + } + /** * Increases the cache buster key */ diff --git a/apps/theming/tests/ThemingDefaultsTest.php b/apps/theming/tests/ThemingDefaultsTest.php index 72ccaa57d7..986b2f3426 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 7a884dd928..7d3ca51c50 100644 --- a/lib/private/Mail/EMailTemplate.php +++ b/lib/private/Mail/EMailTemplate.php @@ -1,8 +1,10 @@ + * @copyright 2017, Lukas Reschke * * @author Morris Jobke + * @author Lukas Reschke * * @license GNU AGPL version 3 or any later version * @@ -23,6 +25,9 @@ namespace OC\Mail; +use OCA\Theming\ThemingDefaults; +use OCP\IL10N; +use OCP\IURLGenerator; /** * Class EMailTemplate @@ -33,9 +38,12 @@ namespace OC\Mail; * @package OC\Mail */ class EMailTemplate implements IEMailTemplate { - - /** @var \OC_Defaults */ - protected $defaults; + /** @var ThemingDefaults */ + protected $themingDefaults; + /** @var IURLGenerator */ + protected $urlGenerator; + /** @var IL10N */ + protected $l10n; /** @var string */ protected $htmlBody = ''; @@ -88,7 +96,7 @@ EOF; -
+
@@ -240,8 +248,7 @@ EOF;
EOF; - - public function __construct(\OC_Defaults $defaults) { - $this->defaults = $defaults; - + /** + * @param ThemingDefaults $themingDefaults + * @param IURLGenerator $urlGenerator + * @param IL10N $l10n + */ + public function __construct(ThemingDefaults $themingDefaults, + IURLGenerator $urlGenerator, + IL10N $l10n) { + $this->themingDefaults = $themingDefaults; + $this->urlGenerator = $urlGenerator; + $this->l10n = $l10n; $this->htmlBody .= $this->head; } /** * Adds a header to the email - * - * @param string $logoUrl */ - public function addHeader($logoUrl) { + public function addHeader() { if ($this->headerAdded) { return; } $this->headerAdded = true; - $this->htmlBody .= vsprintf($this->header, [$this->defaults->getColorPrimary(), $logoUrl]); + $logoUrl = $this->urlGenerator->getAbsoluteURL($this->themingDefaults->getLogo()) . '?v='. $this->themingDefaults->getCacheBusterCounter(); + $this->htmlBody .= vsprintf($this->header, [$this->themingDefaults->getColorPrimary(), $logoUrl]); } /** @@ -328,7 +341,7 @@ EOF; $this->bodyOpened = true; } - $color = $this->defaults->getColorPrimary(); + $color = $this->themingDefaults->getColorPrimary(); $this->htmlBody .= vsprintf($this->buttonGroup, [$color, $color, $urlLeft, $color, $textLeft, $urlRight, $textRight]); $this->plainBody .= $textLeft . ': ' . $urlLeft . PHP_EOL; $this->plainBody .= $textRight . ': ' . $urlRight . PHP_EOL . PHP_EOL; @@ -338,10 +351,13 @@ EOF; /** * Adds a logo and a text to the footer.
in the text will be replaced by new lines in the plain text email * - * @param string $logoUrl * @param string $text */ - public function addFooter($logoUrl, $text) { + public function addFooter($text = '') { + if($text === '') { + $text = $this->themingDefaults->getName() . ' - ' . $this->themingDefaults->getSlogan() . '
' . $this->l10n->t('This is an automatically generated email, please do not reply.'); + } + if ($this->footerAdded) { return; } @@ -351,7 +367,8 @@ EOF; $this->htmlBody .= $this->bodyEnd; $this->bodyOpened = false; } - $this->htmlBody .= vsprintf($this->footer, [$logoUrl, $text]); + + $this->htmlBody .= vsprintf($this->footer, [$text]); $this->htmlBody .= $this->tail; $this->plainBody .= '--' . PHP_EOL; $this->plainBody .= str_replace('
', PHP_EOL, $text); @@ -389,4 +406,3 @@ EOF; return $this->plainBody; } } - diff --git a/lib/private/Mail/IEMailTemplate.php b/lib/private/Mail/IEMailTemplate.php index 5bf2b8e439..0d660a3551 100644 --- a/lib/private/Mail/IEMailTemplate.php +++ b/lib/private/Mail/IEMailTemplate.php @@ -34,7 +34,7 @@ namespace OC\Mail; * * $emailTemplate = new EMailTemplate($this->defaults); * - * $emailTemplate->addHeader('https://example.org/img/logo-mail-header.png'); + * $emailTemplate->addHeader(); * $emailTemplate->addHeading('Welcome aboard'); * $emailTemplate->addBodyText('You have now an Nextcloud account, you can add, protect, and share your data.'); * @@ -43,21 +43,25 @@ namespace OC\Mail; * 'Install Client', 'https://nextcloud.com/install/#install-clients' * ); * - * $emailTemplate->addFooter( - * 'https://example.org/img/logo-mail-footer.png', - * 'Nextcloud - a safe home for your data
This is an automatically generated email, please do not reply.' - * ); + * $emailTemplate->addFooter('Optional footer text'); * * $htmlContent = $emailTemplate->renderHTML(); * $plainContent = $emailTemplate->renderText(); */ interface IEMailTemplate { /** - * Adds a header to the email - * - * @param string $logoUrl + * @param \OCA\Theming\ThemingDefaults $themingDefaults + * @param \OCP\IURLGenerator $urlGenerator + * @param \OCP\IL10N $l10n */ - public function addHeader($logoUrl); + public function __construct(\OCA\Theming\ThemingDefaults $themingDefaults, + \OCP\IURLGenerator $urlGenerator, + \OCP\IL10N $l10n); + + /** + * Adds a header to the email + */ + public function addHeader(); /** * Adds a heading to the email @@ -86,10 +90,9 @@ interface IEMailTemplate { /** * Adds a logo and a text to the footer.
in the text will be replaced by new lines in the plain text email * - * @param string $logoUrl * @param string $text */ - public function addFooter($logoUrl, $text); + public function addFooter($text = ''); /** * Returns the rendered HTML email as string @@ -104,4 +107,4 @@ interface IEMailTemplate { * @return string */ public function renderText(); -} \ No newline at end of file +} diff --git a/lib/private/Server.php b/lib/private/Server.php index 98910b097b..0d05bfe0dc 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 44747c2f68..bf149def94 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 c7b2c2537d..b42d4faa56 100644 --- a/settings/Controller/UsersController.php +++ b/settings/Controller/UsersController.php @@ -33,12 +33,10 @@ namespace OC\Settings\Controller; use OC\Accounts\AccountManager; use OC\AppFramework\Http; use OC\ForbiddenException; -use OC\Mail\EMailTemplate; -use OC\User\User; +use OC\Settings\Mailer\NewUserMailHelper; use OCP\App\IAppManager; use OCP\AppFramework\Controller; use OCP\AppFramework\Http\DataResponse; -use OCP\AppFramework\Http\TemplateResponse; use OCP\IConfig; use OCP\IGroupManager; use OCP\IL10N; @@ -50,9 +48,7 @@ use OCP\IUserManager; use OCP\IUserSession; use OCP\Mail\IMailer; use OCP\IAvatarManager; -use OCP\Security\ICrypto; use OCP\Security\ISecureRandom; -use OCP\AppFramework\Utility\ITimeFactory; /** * @package OC\Settings\Controller @@ -72,14 +68,8 @@ class UsersController extends Controller { private $config; /** @var ILogger */ private $log; - /** @var \OC_Defaults */ - private $defaults; /** @var IMailer */ private $mailer; - /** @var string */ - private $fromMailAddress; - /** @var IURLGenerator */ - private $urlGenerator; /** @var bool contains the state of the encryption app */ private $isEncryptionAppEnabled; /** @var bool contains the state of the admin recovery setting */ @@ -90,11 +80,8 @@ class UsersController extends Controller { private $accountManager; /** @var ISecureRandom */ private $secureRandom; - /** @var ITimeFactory */ - private $timeFactory; - /** @var ICrypto */ - private $crypto; - + /** @var NewUserMailHelper */ + private $newUserMailHelper; /** * @param string $appName @@ -106,16 +93,13 @@ class UsersController extends Controller { * @param bool $isAdmin * @param IL10N $l10n * @param ILogger $log - * @param \OC_Defaults $defaults * @param IMailer $mailer - * @param string $fromMailAddress * @param IURLGenerator $urlGenerator * @param IAppManager $appManager * @param IAvatarManager $avatarManager * @param AccountManager $accountManager * @param ISecureRandom $secureRandom - * @param ITimeFactory $timeFactory - * @param ICrypto $crypto + * @param NewUserMailHelper $newUserMailHelper */ public function __construct($appName, IRequest $request, @@ -126,16 +110,13 @@ class UsersController extends Controller { $isAdmin, IL10N $l10n, ILogger $log, - \OC_Defaults $defaults, IMailer $mailer, - $fromMailAddress, IURLGenerator $urlGenerator, IAppManager $appManager, IAvatarManager $avatarManager, AccountManager $accountManager, ISecureRandom $secureRandom, - ITimeFactory $timeFactory, - ICrypto $crypto) { + NewUserMailHelper $newUserMailHelper) { parent::__construct($appName, $request); $this->userManager = $userManager; $this->groupManager = $groupManager; @@ -144,15 +125,11 @@ class UsersController extends Controller { $this->isAdmin = $isAdmin; $this->l10n = $l10n; $this->log = $log; - $this->defaults = $defaults; $this->mailer = $mailer; - $this->fromMailAddress = $fromMailAddress; - $this->urlGenerator = $urlGenerator; $this->avatarManager = $avatarManager; $this->accountManager = $accountManager; $this->secureRandom = $secureRandom; - $this->timeFactory = $timeFactory; - $this->crypto = $crypto; + $this->newUserMailHelper = $newUserMailHelper; // check for encryption state - TODO see formatUserForIndex $this->isEncryptionAppEnabled = $appManager->isEnabledForUser('encryption'); @@ -380,7 +357,7 @@ class UsersController extends Controller { ); } - $generatedPassword = false; + $generatePasswordResetToken = false; if ($password === '') { if ($email === '') { return new DataResponse( @@ -392,7 +369,7 @@ class UsersController extends Controller { } $password = $this->secureRandom->generate(32); - $generatedPassword = true; + $generatePasswordResetToken = true; } try { @@ -426,68 +403,9 @@ class UsersController extends Controller { */ if($email !== '') { $user->setEMailAddress($email); - - if ($generatedPassword) { - $token = $this->secureRandom->generate( - 21, - ISecureRandom::CHAR_DIGITS . - ISecureRandom::CHAR_LOWER . - ISecureRandom::CHAR_UPPER - ); - $tokenValue = $this->timeFactory->getTime() . ':' . $token; - $mailAddress = !is_null($user->getEMailAddress()) ? $user->getEMailAddress() : ''; - $encryptedValue = $this->crypto->encrypt($tokenValue, $mailAddress . $this->config->getSystemValue('secret')); - $this->config->setUserValue($username, 'core', 'lostpassword', $encryptedValue); - - $link = $this->urlGenerator->linkToRouteAbsolute('core.lost.resetform', ['userId' => $username, 'token' => $token]); - } else { - $link = $this->urlGenerator->getAbsoluteURL('/'); - } - - $emailTemplate = new EMailTemplate($this->defaults); - - $emailTemplate->addHeader($this->urlGenerator->getAbsoluteURL($this->urlGenerator->imagePath('', 'logo-mail-header.png'))); - - $displayName = $user->getDisplayName(); - if ($displayName === $username) { - $emailTemplate->addHeading($this->l10n->t('Welcome aboard')); - } else { - $emailTemplate->addHeading($this->l10n->t('Welcome aboard %s', [$displayName])); - } - $emailTemplate->addBodyText($this->l10n->t('You have now an %s account, you can add, protect, and share your data.', [$this->defaults->getName()])); - $emailTemplate->addBodyText($this->l10n->t('Your username is: %s', [$username])); - - if ($generatedPassword) { - $leftButtonText = $this->l10n->t('Set your password'); - } else { - $leftButtonText = $this->l10n->t('Go to %s', [$this->defaults->getName()]); - } - - $emailTemplate->addBodyButtonGroup( - $leftButtonText, - $link, - $this->l10n->t('Install Client'), - 'https://nextcloud.com/install/#install-clients' - ); - - $emailTemplate->addFooter( - $this->urlGenerator->getAbsoluteURL($this->urlGenerator->imagePath('', 'logo-mail-footer.png')), - $this->defaults->getName() . ' - ' . $this->defaults->getSlogan() . '
' . $this->l10n->t('This is an automatically generated email, please do not reply.') - ); - - $mailContent = $emailTemplate->renderHTML(); - $plainTextMailContent = $emailTemplate->renderText(); - - $subject = $this->l10n->t('Your %s account was created', [$this->defaults->getName()]); - try { - $message = $this->mailer->createMessage(); - $message->setTo([$email => $username]); - $message->setSubject($subject); - $message->setHtmlBody($mailContent); - $message->setPlainBody($plainTextMailContent); - $message->setFrom([$this->fromMailAddress => $this->defaults->getName()]); - $this->mailer->send($message); + $emailTemplate = $this->newUserMailHelper->generateTemplate($user, $generatePasswordResetToken); + $this->newUserMailHelper->sendMail($user, $emailTemplate); } catch(\Exception $e) { $this->log->error("Can't send new user mail to $email: " . $e->getMessage(), array('app' => 'settings')); } diff --git a/settings/Mailer/NewUserMailHelper.php b/settings/Mailer/NewUserMailHelper.php new file mode 100644 index 0000000000..15b912f803 --- /dev/null +++ b/settings/Mailer/NewUserMailHelper.php @@ -0,0 +1,166 @@ + + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +namespace OC\Settings\Mailer; + +use OC\Mail\EMailTemplate; +use OC\Mail\IEMailTemplate; +use OCA\Theming\ThemingDefaults; +use OCP\AppFramework\Utility\ITimeFactory; +use OCP\IConfig; +use OCP\IL10N; +use OCP\IURLGenerator; +use OCP\IUser; +use OCP\Mail\IMailer; +use OCP\Security\ICrypto; +use OCP\Security\ISecureRandom; + +class NewUserMailHelper { + /** @var ThemingDefaults */ + private $themingDefaults; + /** @var IURLGenerator */ + private $urlGenerator; + /** @var IL10N */ + private $l10n; + /** @var IMailer */ + private $mailer; + /** @var ISecureRandom */ + private $secureRandom; + /** @var ITimeFactory */ + private $timeFactory; + /** @var IConfig */ + private $config; + /** @var ICrypto */ + private $crypto; + /** @var string */ + private $fromAddress; + + /** + * @param ThemingDefaults $themingDefaults + * @param IURLGenerator $urlGenerator + * @param IL10N $l10n + * @param IMailer $mailer + * @param ISecureRandom $secureRandom + * @param ITimeFactory $timeFactory + * @param IConfig $config + * @param ICrypto $crypto + * @param string $fromAddress + */ + public function __construct(ThemingDefaults $themingDefaults, + IURLGenerator $urlGenerator, + IL10N $l10n, + IMailer $mailer, + ISecureRandom $secureRandom, + ITimeFactory $timeFactory, + IConfig $config, + ICrypto $crypto, + $fromAddress) { + $this->themingDefaults = $themingDefaults; + $this->urlGenerator = $urlGenerator; + $this->l10n = $l10n; + $this->mailer = $mailer; + $this->secureRandom = $secureRandom; + $this->timeFactory = $timeFactory; + $this->config = $config; + $this->crypto = $crypto; + $this->fromAddress = $fromAddress; + } + + /** + * Set the IL10N object + * + * @param IL10N $l10n + */ + public function setL10N(IL10N $l10n) { + $this->l10n = $l10n; + } + + /** + * @param IUser $user + * @param bool $generatePasswordResetToken + * @return EMailTemplate + */ + public function generateTemplate(IUser $user, $generatePasswordResetToken = false) { + if ($generatePasswordResetToken) { + $token = $this->secureRandom->generate( + 21, + ISecureRandom::CHAR_DIGITS . + ISecureRandom::CHAR_LOWER . + ISecureRandom::CHAR_UPPER + ); + $tokenValue = $this->timeFactory->getTime() . ':' . $token; + $mailAddress = (null !== $user->getEMailAddress()) ? $user->getEMailAddress() : ''; + $encryptedValue = $this->crypto->encrypt($tokenValue, $mailAddress . $this->config->getSystemValue('secret')); + $this->config->setUserValue($user->getUID(), 'core', 'lostpassword', $encryptedValue); + $link = $this->urlGenerator->linkToRouteAbsolute('core.lost.resetform', ['userId' => $user->getUID(), 'token' => $token]); + } else { + $link = $this->urlGenerator->getAbsoluteURL('/'); + } + + $emailTemplate = new EMailTemplate( + $this->themingDefaults, + $this->urlGenerator, + $this->l10n + ); + $emailTemplate->addHeader(); + $displayName = $user->getDisplayName(); + $userName = $user->getUID(); + if ($displayName === $userName) { + $emailTemplate->addHeading($this->l10n->t('Welcome aboard')); + } else { + $emailTemplate->addHeading($this->l10n->t('Welcome aboard %s', [$displayName])); + } + $emailTemplate->addBodyText($this->l10n->t('You have now an %s account, you can add, protect, and share your data.', [$this->themingDefaults->getName()])); + $emailTemplate->addBodyText($this->l10n->t('Your username is: %s', [$userName])); + if ($generatePasswordResetToken) { + $leftButtonText = $this->l10n->t('Set your password'); + } else { + $leftButtonText = $this->l10n->t('Go to %s', [$this->themingDefaults->getName()]); + } + $emailTemplate->addBodyButtonGroup( + $leftButtonText, + $link, + $this->l10n->t('Install Client'), + 'https://nextcloud.com/install/#install-clients' + ); + $emailTemplate->addFooter(); + + return $emailTemplate; + } + + /** + * Sends a welcome mail to $user + * + * @param IUser $user + * @param IEmailTemplate $emailTemplate + * @throws \Exception If mail could not be sent + */ + public function sendMail(IUser $user, + IEMailTemplate $emailTemplate) { + $message = $this->mailer->createMessage(); + $message->setTo([$user->getEMailAddress() => $user->getDisplayName()]); + $message->setSubject($this->l10n->t('Your %s account was created', [$this->themingDefaults->getName()])); + $message->setHtmlBody($emailTemplate->renderHTML()); + $message->setPlainBody($emailTemplate->renderText()); + $message->setFrom([$this->fromAddress => $this->themingDefaults->getName()]); + $this->mailer->send($message); + } +} diff --git a/tests/Settings/Controller/UsersControllerTest.php b/tests/Settings/Controller/UsersControllerTest.php index 52a9a1cc84..d7961e2332 100644 --- a/tests/Settings/Controller/UsersControllerTest.php +++ b/tests/Settings/Controller/UsersControllerTest.php @@ -12,8 +12,9 @@ namespace Tests\Settings\Controller; use OC\Accounts\AccountManager; use OC\Group\Manager; -use OC\Mail\EMailTemplate; +use OC\Mail\IEMailTemplate; use OC\Settings\Controller\UsersController; +use OC\Settings\Mailer\NewUserMailHelper; use OCP\App\IAppManager; use OCP\AppFramework\Http; use OCP\AppFramework\Http\DataResponse; @@ -69,6 +70,8 @@ class UsersControllerTest extends \Test\TestCase { private $secureRandom; /** @var ITimeFactory | \PHPUnit_Framework_MockObject_MockObject */ private $timeFactory; + /** @var NewUserMailHelper|\PHPUnit_Framework_MockObject_MockObject */ + private $newUserMailHelper; /** @var ICrypto | \PHPUnit_Framework_MockObject_MockObject */ private $crypto; @@ -80,7 +83,6 @@ class UsersControllerTest extends \Test\TestCase { $this->userSession = $this->createMock(IUserSession::class); $this->config = $this->createMock(IConfig::class); $this->logger = $this->createMock(ILogger::class); - $this->defaults = $this->createMock(\OC_Defaults::class); $this->mailer = $this->createMock(IMailer::class); $this->urlGenerator = $this->createMock(IURLGenerator::class); $this->appManager = $this->createMock(IAppManager::class); @@ -89,6 +91,7 @@ class UsersControllerTest extends \Test\TestCase { $this->secureRandom = $this->createMock(ISecureRandom::class); $this->timeFactory = $this->createMock(ITimeFactory::class); $this->crypto = $this->createMock(ICrypto::class); + $this->newUserMailHelper = $this->createMock(NewUserMailHelper::class); $this->l = $this->createMock(IL10N::class); $this->l->method('t') ->will($this->returnCallback(function ($text, $parameters = []) { @@ -127,16 +130,13 @@ class UsersControllerTest extends \Test\TestCase { $isAdmin, $this->l, $this->logger, - $this->defaults, $this->mailer, - 'no-reply@nextcloud.com', $this->urlGenerator, $this->appManager, $this->avatarManager, $this->accountManager, $this->secureRandom, - $this->timeFactory, - $this->crypto + $this->newUserMailHelper ); } else { return $this->getMockBuilder(UsersController::class) @@ -151,16 +151,13 @@ class UsersControllerTest extends \Test\TestCase { $isAdmin, $this->l, $this->logger, - $this->defaults, $this->mailer, - 'no-reply@nextcloud.com', $this->urlGenerator, $this->appManager, $this->avatarManager, $this->accountManager, $this->secureRandom, - $this->timeFactory, - $this->crypto + $this->newUserMailHelper ] )->setMethods($mockedMethods)->getMock(); } @@ -1418,91 +1415,11 @@ class UsersControllerTest extends \Test\TestCase { */ public function testCreateSuccessfulWithValidEmailAdmin() { $controller = $this->getController(true); - $message = $this->getMockBuilder('\OC\Mail\Message') - ->disableOriginalConstructor()->getMock(); - $message - ->expects($this->at(0)) - ->method('setTo') - ->with(['validMail@Adre.ss' => 'foo']); - $message - ->expects($this->at(1)) - ->method('setSubject') - ->with('Your Nextcloud account was created'); - - $this->urlGenerator - ->expects($this->at(0)) - ->method('getAbsoluteURL') - ->with('/') - ->willReturn('https://example.org/'); - $this->urlGenerator - ->expects($this->at(1)) - ->method('imagePath') - ->with('', 'logo-mail-header.png') - ->willReturn('/img/logo-mail-header.png'); - $this->urlGenerator - ->expects($this->at(2)) - ->method('getAbsoluteURL') - ->with('/img/logo-mail-header.png') - ->willReturn('https://example.org/img/logo-mail-header.png'); - $this->urlGenerator - ->expects($this->at(3)) - ->method('imagePath') - ->with('', 'logo-mail-footer.png') - ->willReturn('/img/logo-mail-footer.png'); - $this->urlGenerator - ->expects($this->at(4)) - ->method('getAbsoluteURL') - ->with('/img/logo-mail-footer.png') - ->willReturn('https://example.org/img/logo-mail-footer.png'); - $this->defaults - ->expects($this->any()) - ->method('getName') - ->willReturn('Nextcloud'); - $this->defaults - ->expects($this->any()) - ->method('getSlogan') - ->willReturn('A safe home for your data'); - - $emailTemplate = new EMailTemplate($this->defaults); - $emailTemplate->addHeader('https://example.org/img/logo-mail-header.png'); - $emailTemplate->addHeading('Welcome aboard'); - $emailTemplate->addBodyText('You have now an Nextcloud account, you can add, protect, and share your data.'); - $emailTemplate->addBodyText('Your username is: foo'); - $emailTemplate->addBodyButtonGroup( - 'Go to Nextcloud', 'https://example.org/', - 'Install Client', 'https://nextcloud.com/install/#install-clients' - ); - $emailTemplate->addFooter( - 'https://example.org/img/logo-mail-footer.png', - 'Nextcloud - A safe home for your data
This is an automatically generated email, please do not reply.' - ); - - $message - ->expects($this->at(2)) - ->method('setHtmlBody') - ->with($emailTemplate->renderHTML()); - $message - ->expects($this->at(3)) - ->method('setPlainBody') - ->with($emailTemplate->renderText()); - $message - ->expects($this->at(4)) - ->method('setFrom') - ->with(['no-reply@nextcloud.com' => 'Nextcloud']); - $this->mailer ->expects($this->at(0)) ->method('validateMailAddress') ->with('validMail@Adre.ss') ->will($this->returnValue(true)); - $this->mailer - ->expects($this->at(1)) - ->method('createMessage') - ->will($this->returnValue($message)); - $this->mailer - ->expects($this->at(2)) - ->method('send') - ->with($message); $user = $this->getMockBuilder('\OC\User\User') ->disableOriginalConstructor()->getMock(); @@ -1523,6 +1440,17 @@ class UsersControllerTest extends \Test\TestCase { ->method('getBackendClassName') ->will($this->returnValue('bar')); + $emailTemplate = $this->createMock(IEMailTemplate::class); + $this->newUserMailHelper + ->expects($this->at(0)) + ->method('generateTemplate') + ->with($user, false) + ->willReturn($emailTemplate); + $this->newUserMailHelper + ->expects($this->at(1)) + ->method('sendMail') + ->with($user, $emailTemplate); + $this->userManager ->expects($this->once()) ->method('createUser') @@ -2334,106 +2262,22 @@ class UsersControllerTest extends \Test\TestCase { ->method('getSubAdmin') ->will($this->returnValue($subadmin)); - $this->secureRandom - ->expects($this->at(0)) - ->method('generate') - ->with(32) - ->will($this->returnValue('abc123')); - $this->secureRandom - ->expects($this->at(1)) - ->method('generate') - ->with(21, - ISecureRandom::CHAR_DIGITS . - ISecureRandom::CHAR_LOWER . - ISecureRandom::CHAR_UPPER) - ->will($this->returnValue('mytoken')); - $controller = $this->getController(true); - $message = $this->getMockBuilder('\OC\Mail\Message') - ->disableOriginalConstructor()->getMock(); - $message - ->expects($this->at(0)) - ->method('setTo') - ->with(['abc@example.org' => 'foo']); - $message - ->expects($this->at(1)) - ->method('setSubject') - ->with('Your Nextcloud account was created'); - - $this->urlGenerator - ->expects($this->at(0)) - ->method('linkToRouteAbsolute') - ->with('core.lost.resetform', ['userId' => 'foo', 'token' => 'mytoken']) - ->will($this->returnValue('https://example.org/resetPassword/123')); - $this->urlGenerator - ->expects($this->at(1)) - ->method('imagePath') - ->with('', 'logo-mail-header.png') - ->willReturn('/img/logo-mail-header.png'); - $this->urlGenerator - ->expects($this->at(2)) - ->method('getAbsoluteURL') - ->with('/img/logo-mail-header.png') - ->willReturn('https://example.org/img/logo-mail-header.png'); - $this->urlGenerator - ->expects($this->at(3)) - ->method('imagePath') - ->with('', 'logo-mail-footer.png') - ->willReturn('/img/logo-mail-footer.png'); - $this->urlGenerator - ->expects($this->at(4)) - ->method('getAbsoluteURL') - ->with('/img/logo-mail-footer.png') - ->willReturn('https://example.org/img/logo-mail-footer.png'); - $this->defaults - ->expects($this->any()) - ->method('getName') - ->willReturn('Nextcloud'); - $this->defaults - ->expects($this->any()) - ->method('getSlogan') - ->willReturn('A safe home for your data'); - - $emailTemplate = new EMailTemplate($this->defaults); - $emailTemplate->addHeader('https://example.org/img/logo-mail-header.png'); - $emailTemplate->addHeading('Welcome aboard John Doe'); - $emailTemplate->addBodyText('You have now an Nextcloud account, you can add, protect, and share your data.'); - $emailTemplate->addBodyText('Your username is: foo'); - $emailTemplate->addBodyButtonGroup( - 'Set your password', 'https://example.org/resetPassword/123', - 'Install Client', 'https://nextcloud.com/install/#install-clients' - ); - $emailTemplate->addFooter( - 'https://example.org/img/logo-mail-footer.png', - 'Nextcloud - A safe home for your data
This is an automatically generated email, please do not reply.' - ); - - $message - ->expects($this->at(2)) - ->method('setHtmlBody') - ->with($emailTemplate->renderHTML()); - $message - ->expects($this->at(3)) - ->method('setPlainBody') - ->with($emailTemplate->renderText()); - $message - ->expects($this->at(4)) - ->method('setFrom') - ->with(['no-reply@nextcloud.com' => 'Nextcloud']); - $this->mailer ->expects($this->at(0)) ->method('validateMailAddress') ->with('abc@example.org') ->will($this->returnValue(true)); - $this->mailer + $emailTemplate = $this->createMock(IEMailTemplate::class); + $this->newUserMailHelper + ->expects($this->at(0)) + ->method('generateTemplate') + ->with($user, true) + ->willReturn($emailTemplate); + $this->newUserMailHelper ->expects($this->at(1)) - ->method('createMessage') - ->will($this->returnValue($message)); - $this->mailer - ->expects($this->at(2)) - ->method('send') - ->with($message); + ->method('sendMail') + ->with($user, $emailTemplate); $expectedResponse = new DataResponse( [ diff --git a/tests/Settings/Mailer/NewUserMailHelperTest.php b/tests/Settings/Mailer/NewUserMailHelperTest.php new file mode 100644 index 0000000000..e77e8e197b --- /dev/null +++ b/tests/Settings/Mailer/NewUserMailHelperTest.php @@ -0,0 +1,639 @@ + + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +namespace Tests\Settings\Mailer; + +use OC\Mail\EMailTemplate; +use OC\Mail\IEMailTemplate; +use OC\Mail\Message; +use OC\Settings\Mailer\NewUserMailHelper; +use OCA\Theming\ThemingDefaults; +use OCP\AppFramework\Utility\ITimeFactory; +use OCP\IConfig; +use OCP\IL10N; +use OCP\IURLGenerator; +use OCP\IUser; +use OCP\Mail\IMailer; +use OCP\Security\ICrypto; +use OCP\Security\ISecureRandom; +use Test\TestCase; + +class NewUserMailHelperTest extends TestCase { + /** @var ThemingDefaults|\PHPUnit_Framework_MockObject_MockObject */ + private $themingDefaults; + /** @var IURLGenerator|\PHPUnit_Framework_MockObject_MockObject */ + private $urlGenerator; + /** @var IL10N|\PHPUnit_Framework_MockObject_MockObject */ + private $l10n; + /** @var IMailer|\PHPUnit_Framework_MockObject_MockObject */ + private $mailer; + /** @var ISecureRandom|\PHPUnit_Framework_MockObject_MockObject */ + private $secureRandom; + /** @var ITimeFactory|\PHPUnit_Framework_MockObject_MockObject */ + private $timeFactory; + /** @var IConfig|\PHPUnit_Framework_MockObject_MockObject */ + private $config; + /** @var ICrypto|\PHPUnit_Framework_MockObject_MockObject */ + private $crypto; + /** @var NewUserMailHelper */ + private $newUserMailHelper; + + public function setUp() { + parent::setUp(); + + $this->themingDefaults = $this->createMock(ThemingDefaults::class); + $this->urlGenerator = $this->createMock(IURLGenerator::class); + $this->l10n = $this->createMock(IL10N::class); + $this->mailer = $this->createMock(IMailer::class); + $this->secureRandom = $this->createMock(ISecureRandom::class); + $this->timeFactory = $this->createMock(ITimeFactory::class); + $this->config = $this->createMock(IConfig::class); + $this->crypto = $this->createMock(ICrypto::class); + $this->l10n->method('t') + ->will($this->returnCallback(function ($text, $parameters = []) { + return vsprintf($text, $parameters); + })); + + $this->newUserMailHelper = new NewUserMailHelper( + $this->themingDefaults, + $this->urlGenerator, + $this->l10n, + $this->mailer, + $this->secureRandom, + $this->timeFactory, + $this->config, + $this->crypto, + 'no-reply@nextcloud.com' + ); + } + + public function testGenerateTemplateWithPasswordResetToken() { + $this->secureRandom + ->expects($this->once()) + ->method('generate') + ->with(21, + ISecureRandom::CHAR_DIGITS . + ISecureRandom::CHAR_LOWER . + ISecureRandom::CHAR_UPPER + ) + ->willReturn('MySuperLongSecureRandomToken'); + $this->timeFactory + ->expects($this->once()) + ->method('getTime') + ->willReturn('12345'); + /** @var IUser|\PHPUnit_Framework_MockObject_MockObject $user */ + $user = $this->createMock(IUser::class); + $user + ->expects($this->at(0)) + ->method('getEmailAddress') + ->willReturn('recipient@example.com'); + $user + ->expects($this->at(1)) + ->method('getEmailAddress') + ->willReturn('recipient@example.com'); + $this->config + ->expects($this->at(0)) + ->method('getSystemValue') + ->with('secret') + ->willReturn('MyInstanceWideSecret'); + $this->crypto + ->expects($this->once()) + ->method('encrypt') + ->with('12345:MySuperLongSecureRandomToken', 'recipient@example.comMyInstanceWideSecret') + ->willReturn('TokenCiphertext'); + $user + ->expects($this->at(2)) + ->method('getUID') + ->willReturn('john'); + $this->config + ->expects($this->at(1)) + ->method('setUserValue') + ->with('john', 'core', 'lostpassword', 'TokenCiphertext'); + $user + ->expects($this->at(3)) + ->method('getUID') + ->willReturn('john'); + $this->urlGenerator + ->expects($this->at(0)) + ->method('linkToRouteAbsolute') + ->with('core.lost.resetform', ['userId' => 'john', 'token' => 'MySuperLongSecureRandomToken']) + ->willReturn('https://example.com/resetPassword/MySuperLongSecureRandomToken'); + $user + ->expects($this->at(4)) + ->method('getDisplayName') + ->willReturn('john'); + $user + ->expects($this->at(5)) + ->method('getUID') + ->willReturn('john'); + $this->themingDefaults + ->expects($this->at(0)) + ->method('getName') + ->willReturn('TestCloud'); + + $expectedHtmlBody = << + + + + + + + + + + + + + +
+
+ + + +
+ + + + + + +
+ + + +
+ +
+ + +
+
+
+ + + + + + +
 
+ + + + + +
+

Welcome aboard

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

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

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

Your username is: john

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

Welcome aboard John Doe

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

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

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

Your username is: john

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

Welcome aboard

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

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

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

Your username is: abc

+
+
+ + + + + +
 
+ + + + + + +
+ + + + + +
+
+ + + + +
+ + + + +
+ Set your password +
+
+ + + + +
+ + + + +
+ Install Client +
+
+
+
+
+
+
+ + + + + +
 
+ + + + +
+
+ +
                                                           
+ + \ No newline at end of file diff --git a/tests/data/emails/new-account-email-custom.txt b/tests/data/emails/new-account-email-custom.txt new file mode 100644 index 0000000000..962128980e --- /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 9b9155fa1d..a32ad61c49 100644 --- a/tests/data/emails/new-account-email.html +++ b/tests/data/emails/new-account-email.html @@ -22,8 +22,8 @@ -
- +
+
@@ -165,8 +165,7 @@
diff --git a/tests/lib/Mail/EMailTemplateTest.php b/tests/lib/Mail/EMailTemplateTest.php index 3acb742aec..47fe09aabb 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; + /** @var IURLGenerator|\PHPUnit_Framework_MockObject_MockObject */ + private $urlGenerator; + /** @var IL10N|\PHPUnit_Framework_MockObject_MockObject */ + private $l10n; + /** @var EMailTemplate */ + private $emailTemplate; - function setUp() { + 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'); - } + $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'); - 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->emailTemplate->addHeader(); + $this->emailTemplate->addHeading('Welcome aboard'); + $this->emailTemplate->addBodyText('You have now an Nextcloud account, you can add, protect, and share your data.'); + $this->emailTemplate->addBodyText('Your username is: abc'); + $this->emailTemplate->addBodyButtonGroup( 'Set your password', 'https://example.org/resetPassword/123', 'Install Client', 'https://nextcloud.com/install/#install-clients' ); - - $emailTemplate->addFooter( - 'https://example.org/img/logo-mail-footer.png', + $this->emailTemplate->addFooter( 'TestCloud - A safe home for your data
This is an automatically generated email, please do not reply.' ); $expectedHTML = file_get_contents(\OC::$SERVERROOT . '/tests/data/emails/new-account-email.html'); - $this->assertSame($expectedHTML, $emailTemplate->renderHTML()); - - + $this->assertSame($expectedHTML, $this->emailTemplate->renderHTML()); $expectedTXT = file_get_contents(\OC::$SERVERROOT . '/tests/data/emails/new-account-email.txt'); - $this->assertSame($expectedTXT, $emailTemplate->renderText()); + $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(); + + $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()); } From 8daf3d4a70bc97b6680956f6b13143e184a83c96 Mon Sep 17 00:00:00 2001 From: Lukas Reschke Date: Fri, 7 Apr 2017 16:25:45 +0200 Subject: [PATCH 4/4] Update autoloader Signed-off-by: Lukas Reschke --- lib/composer/composer/autoload_classmap.php | 3 +++ lib/composer/composer/autoload_static.php | 3 +++ 2 files changed, 6 insertions(+) diff --git a/lib/composer/composer/autoload_classmap.php b/lib/composer/composer/autoload_classmap.php index 915f522928..fd73a9561a 100644 --- a/lib/composer/composer/autoload_classmap.php +++ b/lib/composer/composer/autoload_classmap.php @@ -637,6 +637,8 @@ return array( 'OC\\Log\\File' => $baseDir . '/lib/private/Log/File.php', 'OC\\Log\\Rotate' => $baseDir . '/lib/private/Log/Rotate.php', 'OC\\Log\\Syslog' => $baseDir . '/lib/private/Log/Syslog.php', + 'OC\\Mail\\EMailTemplate' => $baseDir . '/lib/private/Mail/EMailTemplate.php', + 'OC\\Mail\\IEMailTemplate' => $baseDir . '/lib/private/Mail/IEMailTemplate.php', 'OC\\Mail\\Mailer' => $baseDir . '/lib/private/Mail/Mailer.php', 'OC\\Mail\\Message' => $baseDir . '/lib/private/Mail/Message.php', 'OC\\Memcache\\APCu' => $baseDir . '/lib/private/Memcache/APCu.php', @@ -769,6 +771,7 @@ return array( 'OC\\Settings\\Controller\\PersonalController' => $baseDir . '/settings/Controller/PersonalController.php', 'OC\\Settings\\Controller\\SecuritySettingsController' => $baseDir . '/settings/Controller/SecuritySettingsController.php', 'OC\\Settings\\Controller\\UsersController' => $baseDir . '/settings/Controller/UsersController.php', + 'OC\\Settings\\Mailer\\NewUserMailHelper' => $baseDir . '/settings/Mailer/NewUserMailHelper.php', 'OC\\Settings\\Manager' => $baseDir . '/lib/private/Settings/Manager.php', 'OC\\Settings\\Mapper' => $baseDir . '/lib/private/Settings/Mapper.php', 'OC\\Settings\\Middleware\\SubadminMiddleware' => $baseDir . '/settings/Middleware/SubadminMiddleware.php', diff --git a/lib/composer/composer/autoload_static.php b/lib/composer/composer/autoload_static.php index a4dc2dbb48..9fe795cfb0 100644 --- a/lib/composer/composer/autoload_static.php +++ b/lib/composer/composer/autoload_static.php @@ -667,6 +667,8 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c 'OC\\Log\\File' => __DIR__ . '/../../..' . '/lib/private/Log/File.php', 'OC\\Log\\Rotate' => __DIR__ . '/../../..' . '/lib/private/Log/Rotate.php', 'OC\\Log\\Syslog' => __DIR__ . '/../../..' . '/lib/private/Log/Syslog.php', + 'OC\\Mail\\EMailTemplate' => __DIR__ . '/../../..' . '/lib/private/Mail/EMailTemplate.php', + 'OC\\Mail\\IEMailTemplate' => __DIR__ . '/../../..' . '/lib/private/Mail/IEMailTemplate.php', 'OC\\Mail\\Mailer' => __DIR__ . '/../../..' . '/lib/private/Mail/Mailer.php', 'OC\\Mail\\Message' => __DIR__ . '/../../..' . '/lib/private/Mail/Message.php', 'OC\\Memcache\\APCu' => __DIR__ . '/../../..' . '/lib/private/Memcache/APCu.php', @@ -799,6 +801,7 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c 'OC\\Settings\\Controller\\PersonalController' => __DIR__ . '/../../..' . '/settings/Controller/PersonalController.php', 'OC\\Settings\\Controller\\SecuritySettingsController' => __DIR__ . '/../../..' . '/settings/Controller/SecuritySettingsController.php', 'OC\\Settings\\Controller\\UsersController' => __DIR__ . '/../../..' . '/settings/Controller/UsersController.php', + 'OC\\Settings\\Mailer\\NewUserMailHelper' => __DIR__ . '/../../..' . '/settings/Mailer/NewUserMailHelper.php', 'OC\\Settings\\Manager' => __DIR__ . '/../../..' . '/lib/private/Settings/Manager.php', 'OC\\Settings\\Mapper' => __DIR__ . '/../../..' . '/lib/private/Settings/Mapper.php', 'OC\\Settings\\Middleware\\SubadminMiddleware' => __DIR__ . '/../../..' . '/settings/Middleware/SubadminMiddleware.php',