From 0560e6991323c156e548792c5fb1f82791868d90 Mon Sep 17 00:00:00 2001 From: Morris Jobke Date: Thu, 6 Apr 2017 13:20:47 -0500 Subject: [PATCH] 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 00000000000..7a884dd928c --- /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 00000000000..5bf2b8e4394 --- /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 19c5b068167..3688cb7b7e2 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 9418c21c6cb..00000000000 --- 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 2cc70ddfa2f..00000000000 --- 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 3cdde1b2d27..2ed298df2dc 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 00000000000..9b9155fa1d9 --- /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 00000000000..6732d806d76 --- /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 00000000000..3acb742aeca --- /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()); + } + + +} -- 2.39.5