You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by da...@apache.org on 2015/01/04 20:48:44 UTC

[10/20] isis git commit: ISIS-987 Provide some sort of mechanism to allow users to self-register for an Isis application.

ISIS-987 Provide some sort of mechanism to allow users to self-register for an Isis application.

Try to improve the email templates. (It will need more work).


Project: http://git-wip-us.apache.org/repos/asf/isis/repo
Commit: http://git-wip-us.apache.org/repos/asf/isis/commit/08466a13
Tree: http://git-wip-us.apache.org/repos/asf/isis/tree/08466a13
Diff: http://git-wip-us.apache.org/repos/asf/isis/diff/08466a13

Branch: refs/heads/master
Commit: 08466a1358cae7197f00c540b9d3d71b327f1f69
Parents: 06dc69a
Author: Martin Tzvetanov Grigorov <mg...@apache.org>
Authored: Sat Jan 3 20:16:36 2015 +0200
Committer: Martin Tzvetanov Grigorov <mg...@apache.org>
Committed: Sat Jan 3 20:16:36 2015 +0200

----------------------------------------------------------------------
 .../signup/PasswordResetEmailPanel.java         |   4 +-
 .../email/EmailNotificationService.java         |   4 +
 .../email/events/PasswordResetEvent.java        |  25 +
 .../email/EmailNotificationServiceDefault.java  |  79 +-
 .../email/EmailVerificationTemplate.html        | 796 +++++++++++++++++-
 .../services/email/PasswordResetTemplate.html   | 817 +++++++++++++++++++
 6 files changed, 1700 insertions(+), 25 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/isis/blob/08466a13/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/password_reset/signup/PasswordResetEmailPanel.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/password_reset/signup/PasswordResetEmailPanel.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/password_reset/signup/PasswordResetEmailPanel.java
index ba2384d..1de7e1f 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/password_reset/signup/PasswordResetEmailPanel.java
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/password_reset/signup/PasswordResetEmailPanel.java
@@ -37,7 +37,7 @@ import org.apache.wicket.request.UrlRenderer;
 import org.apache.wicket.request.mapper.parameter.PageParameters;
 import org.apache.wicket.validation.validator.EmailAddressValidator;
 import org.apache.isis.applib.services.email.EmailNotificationService;
-import org.apache.isis.applib.services.email.events.EmailRegistrationEvent;
+import org.apache.isis.applib.services.email.events.PasswordResetEvent;
 import org.apache.isis.viewer.wicket.ui.components.widgets.bootstrap.FormGroup;
 import org.apache.isis.viewer.wicket.ui.pages.signup.AccountConfirmationMap;
 import org.apache.isis.viewer.wicket.ui.pages.signup.EmailAvailableValidator;
@@ -80,7 +80,7 @@ public class PasswordResetEmailPanel extends Panel {
 
                 String confirmationUrl = createUrl(email);
 
-                boolean emailSent = emailService.send(new EmailRegistrationEvent(email, confirmationUrl));
+                boolean emailSent = emailService.send(new PasswordResetEvent(email, confirmationUrl));
                 if (emailSent) {
                     Map<String, String> map = new HashMap<>();
                     map.put("email", email);

http://git-wip-us.apache.org/repos/asf/isis/blob/08466a13/core/applib/src/main/java/org/apache/isis/applib/services/email/EmailNotificationService.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/email/EmailNotificationService.java b/core/applib/src/main/java/org/apache/isis/applib/services/email/EmailNotificationService.java
index 255bad4..049bd07 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/services/email/EmailNotificationService.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/services/email/EmailNotificationService.java
@@ -3,6 +3,7 @@ package org.apache.isis.applib.services.email;
 import java.io.Serializable;
 import org.apache.isis.applib.annotation.Programmatic;
 import org.apache.isis.applib.services.email.events.EmailRegistrationEvent;
+import org.apache.isis.applib.services.email.events.PasswordResetEvent;
 
 /**
  * TODO ISIS-987 Javadoc
@@ -11,4 +12,7 @@ public interface EmailNotificationService extends Serializable {
 
     @Programmatic
     boolean send(EmailRegistrationEvent emailRegistrationEvent);
+
+    @Programmatic
+    boolean send(PasswordResetEvent emailRegistrationEvent);
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/08466a13/core/applib/src/main/java/org/apache/isis/applib/services/email/events/PasswordResetEvent.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/email/events/PasswordResetEvent.java b/core/applib/src/main/java/org/apache/isis/applib/services/email/events/PasswordResetEvent.java
new file mode 100644
index 0000000..ad7b52b
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/applib/services/email/events/PasswordResetEvent.java
@@ -0,0 +1,25 @@
+package org.apache.isis.applib.services.email.events;
+
+/**
+ * An event send to all services interested in user password reset
+ */
+public class PasswordResetEvent {
+
+    private final String email;
+    private final String confirmationUrl;
+
+    public PasswordResetEvent(
+        final String email,
+        final String confirmationUrl) {
+        this.email = email;
+        this.confirmationUrl = confirmationUrl;
+    }
+
+    public String getEmail() {
+        return email;
+    }
+
+    public String getConfirmationUrl() {
+        return confirmationUrl;
+    }
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/08466a13/core/runtime/src/main/java/org/apache/isis/core/runtime/services/email/EmailNotificationServiceDefault.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/services/email/EmailNotificationServiceDefault.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/email/EmailNotificationServiceDefault.java
index d4321a7..311cc1c 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/services/email/EmailNotificationServiceDefault.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/email/EmailNotificationServiceDefault.java
@@ -3,8 +3,10 @@ package org.apache.isis.core.runtime.services.email;
 import java.io.IOException;
 import java.net.URL;
 import java.util.Properties;
+import java.util.regex.Pattern;
 import com.google.common.base.Charsets;
 import com.google.common.io.Resources;
+import com.google.inject.name.Named;
 import org.apache.commons.mail.DefaultAuthenticator;
 import org.apache.commons.mail.Email;
 import org.apache.commons.mail.EmailException;
@@ -14,19 +16,53 @@ import org.slf4j.LoggerFactory;
 import org.apache.isis.applib.annotation.DomainService;
 import org.apache.isis.applib.services.email.EmailNotificationService;
 import org.apache.isis.applib.services.email.events.EmailRegistrationEvent;
+import org.apache.isis.applib.services.email.events.PasswordResetEvent;
 import org.apache.isis.core.commons.config.IsisConfiguration;
 import org.apache.isis.core.runtime.system.context.IsisContext;
 
+import static java.util.regex.Pattern.compile;
+import static java.util.regex.Pattern.quote;
+
 /**
- * TODO ISIS-987 Javadoc
+ * A service that sends email notifications when specific events occur
  */
 @DomainService
 public class EmailNotificationServiceDefault implements EmailNotificationService {
 
     private static final Logger LOGGER = LoggerFactory.getLogger(EmailNotificationServiceDefault.class);
 
+    private static final Pattern EMAIL_PATTERN = compile(quote("${email}"));
+    private static final Pattern CONFIRMATION_URL_PATTERN = compile(quote("${confirmationUrl}"));
+    private static final Pattern APPLICATION_NAME_PATTERN = compile(quote("${applicationName}"));
+
+    private final String passwordResetTemplate;
+    private final String emailVerificationTemplate;
+
+    /**
+     * Constructor.
+     *
+     * Loads responsive email templates borrowed from http://zurb.com/ink/templates.php (Basic)
+     * @throws IOException
+     */
+    public EmailNotificationServiceDefault() throws IOException {
+        URL passwordResetTemplateUrl = Resources.getResource(EmailNotificationServiceDefault.class, "PasswordResetTemplate.html");
+        this.passwordResetTemplate = Resources.toString(passwordResetTemplateUrl, Charsets.UTF_8);
+
+        URL emailVerificationTemplateUrl = Resources.getResource(EmailNotificationServiceDefault.class, "EmailVerificationTemplate.html");
+        this.emailVerificationTemplate = Resources.toString(emailVerificationTemplateUrl, Charsets.UTF_8);
+    }
+
     @Override
     public boolean send(EmailRegistrationEvent emailRegistrationEvent) {
+        return send(calculateSubject(emailRegistrationEvent), loadMessage(emailRegistrationEvent));
+    }
+
+    @Override
+    public boolean send(PasswordResetEvent passwordResetEvent) {
+        return send(calculateSubject(passwordResetEvent), loadMessage(passwordResetEvent));
+    }
+
+    protected boolean send(String subject, String body) {
 
         boolean mailSent = true;
         try {
@@ -50,8 +86,8 @@ public class EmailNotificationServiceDefault implements EmailNotificationService
 
             email.setFrom(senderEmailAddress);
 
-            email.setSubject("SignUp verification");
-            email.setMsg(loadMessage(emailRegistrationEvent));
+            email.setSubject(subject);
+            email.setMsg(body);
 
             // TODO ISIS-987 use the provided email once development/testing is done
             email.addTo("martin.grigorov@gmail.com");
@@ -65,21 +101,32 @@ public class EmailNotificationServiceDefault implements EmailNotificationService
         return mailSent;
     }
 
-    private String loadMessage(EmailRegistrationEvent emailRegistrationEvent) {
-        String message;
-        try {
-            URL emailVerificationTemplateUrl = Resources.getResource(EmailNotificationServiceDefault.class, "EmailVerificationTemplate.html");
-            String emailVerificationTemplate = Resources.toString(emailVerificationTemplateUrl, Charsets.UTF_8);
-            message = emailVerificationTemplate.replace("${email}", emailRegistrationEvent.getEmail());
-            message = message.replace("${confirmationUrl}", emailRegistrationEvent.getConfirmationUrl());
-        } catch (IOException e) {
-            e.printStackTrace();
-            message = "Problem: " + e.getMessage();
-        }
+    protected String loadMessage(EmailRegistrationEvent emailRegistrationEvent) {
+        String message = EMAIL_PATTERN.matcher(emailVerificationTemplate).replaceFirst(emailRegistrationEvent.getEmail());
+        message = CONFIRMATION_URL_PATTERN.matcher(message).replaceFirst(emailRegistrationEvent.getConfirmationUrl());
+        message = APPLICATION_NAME_PATTERN.matcher(message).replaceAll(applicationName);
+        return message;
+    }
 
+    protected String loadMessage(PasswordResetEvent passwordResetEvent) {
+        String message = EMAIL_PATTERN.matcher(passwordResetTemplate).replaceFirst(passwordResetEvent.getEmail());
+        message = CONFIRMATION_URL_PATTERN.matcher(message).replaceFirst(passwordResetEvent.getConfirmationUrl());
+        message = APPLICATION_NAME_PATTERN.matcher(message).replaceAll(applicationName);
         return message;
     }
 
+    protected String calculateSubject(Object event) {
+        String subject;
+        if (event instanceof EmailRegistrationEvent) {
+            subject = "["+applicationName+"] Please confirm your identity";
+        } else if (event instanceof PasswordResetEvent) {
+            subject = "["+applicationName+"] Password reset request";
+        } else {
+            subject = "[" + applicationName + "]";
+        }
+        return subject;
+    }
+
     protected String getSenderEmailAddress() {
         return getConfiguration().getString("isis.notification.email.sender.address");
     }
@@ -103,4 +150,8 @@ public class EmailNotificationServiceDefault implements EmailNotificationService
     private IsisConfiguration getConfiguration() {
         return IsisContext.getConfiguration();
     }
+
+    @com.google.inject.Inject
+    @Named("applicationName")
+    protected String applicationName;
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/08466a13/core/runtime/src/main/java/org/apache/isis/core/runtime/services/email/EmailVerificationTemplate.html
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/services/email/EmailVerificationTemplate.html b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/email/EmailVerificationTemplate.html
index 0ab564f..a0d4f85 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/services/email/EmailVerificationTemplate.html
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/email/EmailVerificationTemplate.html
@@ -1,15 +1,793 @@
-<!DOCTYPE html>
-<html>
-    <head lang="en">
-        <meta charset="UTF-8">
-        <title>Email verification</title>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+        <meta name="viewport" content="width=device-width"/>
+        <style>
+            /**********************************************
+            * Ink v1.0.5 - Copyright 2013 ZURB Inc        *
+            **********************************************/
+
+            /* Client-specific Styles & Reset */
+
+            #outlook a {
+                padding:0;
+            }
+
+            body{
+                width:100% !important;
+                min-width: 100%;
+                -webkit-text-size-adjust:100%;
+                -ms-text-size-adjust:100%;
+                margin:0;
+                padding:0;
+            }
+
+            img {
+                outline:none;
+                text-decoration:none;
+                -ms-interpolation-mode: bicubic;
+                width: auto;
+                max-width: 100%;
+                float: left;
+                clear: both;
+                display: block;
+            }
+
+            center {
+                width: 100%;
+                min-width: 580px;
+            }
+
+            a img {
+                border: none;
+            }
+
+            p {
+                margin: 0 0 0 10px;
+            }
+
+            table {
+                border-spacing: 0;
+                border-collapse: collapse;
+            }
+
+            td {
+                word-break: break-word;
+                -webkit-hyphens: auto;
+                -moz-hyphens: auto;
+                hyphens: auto;
+                border-collapse: collapse !important;
+            }
+
+            table, tr, td {
+                padding: 0;
+                vertical-align: top;
+                text-align: left;
+            }
+
+            hr {
+                color: #d9d9d9;
+                background-color: #d9d9d9;
+                height: 1px;
+                border: none;
+            }
+
+            /* Responsive Grid */
+
+            table.body {
+                height: 100%;
+                width: 100%;
+            }
+
+            table.container {
+                width: 580px;
+                margin: 0 auto;
+                text-align: inherit;
+            }
+
+            table.row {
+                padding: 0px;
+                width: 100%;
+                position: relative;
+            }
+
+            table.container table.row {
+                display: block;
+            }
+
+            td.wrapper {
+                padding: 10px 20px 0px 0px;
+                position: relative;
+            }
+
+            table.columns,
+            table.column {
+                margin: 0 auto;
+            }
+
+            table.columns td,
+            table.column td {
+                padding: 0px 0px 10px;
+            }
+
+            table.columns td.sub-columns,
+            table.column td.sub-columns,
+            table.columns td.sub-column,
+            table.column td.sub-column {
+                padding-right: 10px;
+            }
+
+            td.sub-column, td.sub-columns {
+                min-width: 0px;
+            }
+
+            table.row td.last,
+            table.container td.last {
+                padding-right: 0px;
+            }
+
+            table.one { width: 30px; }
+            table.two { width: 80px; }
+            table.three { width: 130px; }
+            table.four { width: 180px; }
+            table.five { width: 230px; }
+            table.six { width: 280px; }
+            table.seven { width: 330px; }
+            table.eight { width: 380px; }
+            table.nine { width: 430px; }
+            table.ten { width: 480px; }
+            table.eleven { width: 530px; }
+            table.twelve { width: 580px; }
+
+            table.one center { min-width: 30px; }
+            table.two center { min-width: 80px; }
+            table.three center { min-width: 130px; }
+            table.four center { min-width: 180px; }
+            table.five center { min-width: 230px; }
+            table.six center { min-width: 280px; }
+            table.seven center { min-width: 330px; }
+            table.eight center { min-width: 380px; }
+            table.nine center { min-width: 430px; }
+            table.ten center { min-width: 480px; }
+            table.eleven center { min-width: 530px; }
+            table.twelve center { min-width: 580px; }
+
+            table.one .panel center { min-width: 10px; }
+            table.two .panel center { min-width: 60px; }
+            table.three .panel center { min-width: 110px; }
+            table.four .panel center { min-width: 160px; }
+            table.five .panel center { min-width: 210px; }
+            table.six .panel center { min-width: 260px; }
+            table.seven .panel center { min-width: 310px; }
+            table.eight .panel center { min-width: 360px; }
+            table.nine .panel center { min-width: 410px; }
+            table.ten .panel center { min-width: 460px; }
+            table.eleven .panel center { min-width: 510px; }
+            table.twelve .panel center { min-width: 560px; }
+
+            .body .columns td.one,
+            .body .column td.one { width: 8.333333%; }
+            .body .columns td.two,
+            .body .column td.two { width: 16.666666%; }
+            .body .columns td.three,
+            .body .column td.three { width: 25%; }
+            .body .columns td.four,
+            .body .column td.four { width: 33.333333%; }
+            .body .columns td.five,
+            .body .column td.five { width: 41.666666%; }
+            .body .columns td.six,
+            .body .column td.six { width: 50%; }
+            .body .columns td.seven,
+            .body .column td.seven { width: 58.333333%; }
+            .body .columns td.eight,
+            .body .column td.eight { width: 66.666666%; }
+            .body .columns td.nine,
+            .body .column td.nine { width: 75%; }
+            .body .columns td.ten,
+            .body .column td.ten { width: 83.333333%; }
+            .body .columns td.eleven,
+            .body .column td.eleven { width: 91.666666%; }
+            .body .columns td.twelve,
+            .body .column td.twelve { width: 100%; }
+
+            td.offset-by-one { padding-left: 50px; }
+            td.offset-by-two { padding-left: 100px; }
+            td.offset-by-three { padding-left: 150px; }
+            td.offset-by-four { padding-left: 200px; }
+            td.offset-by-five { padding-left: 250px; }
+            td.offset-by-six { padding-left: 300px; }
+            td.offset-by-seven { padding-left: 350px; }
+            td.offset-by-eight { padding-left: 400px; }
+            td.offset-by-nine { padding-left: 450px; }
+            td.offset-by-ten { padding-left: 500px; }
+            td.offset-by-eleven { padding-left: 550px; }
+
+            td.expander {
+                visibility: hidden;
+                width: 0px;
+                padding: 0 !important;
+            }
+
+            table.columns .text-pad,
+            table.column .text-pad {
+                padding-left: 10px;
+                padding-right: 10px;
+            }
+
+            table.columns .left-text-pad,
+            table.columns .text-pad-left,
+            table.column .left-text-pad,
+            table.column .text-pad-left {
+                padding-left: 10px;
+            }
+
+            table.columns .right-text-pad,
+            table.columns .text-pad-right,
+            table.column .right-text-pad,
+            table.column .text-pad-right {
+                padding-right: 10px;
+            }
+
+            /* Block Grid */
+
+            .block-grid {
+                width: 100%;
+                max-width: 580px;
+            }
+
+            .block-grid td {
+                display: inline-block;
+                padding:10px;
+            }
+
+            .two-up td {
+                width:270px;
+            }
+
+            .three-up td {
+                width:173px;
+            }
+
+            .four-up td {
+                width:125px;
+            }
+
+            .five-up td {
+                width:96px;
+            }
+
+            .six-up td {
+                width:76px;
+            }
+
+            .seven-up td {
+                width:62px;
+            }
+
+            .eight-up td {
+                width:52px;
+            }
+
+            /* Alignment & Visibility Classes */
+
+            table.center, td.center {
+                text-align: center;
+            }
+
+            h1.center,
+            h2.center,
+            h3.center,
+            h4.center,
+            h5.center,
+            h6.center {
+                text-align: center;
+            }
+
+            span.center {
+                display: block;
+                width: 100%;
+                text-align: center;
+            }
+
+            img.center {
+                margin: 0 auto;
+                float: none;
+            }
+
+            .show-for-small,
+            .hide-for-desktop {
+                display: none;
+            }
+
+            /* Typography */
+
+            body, table.body, h1, h2, h3, h4, h5, h6, p, td {
+                color: #222222;
+                font-family: "Helvetica", "Arial", sans-serif;
+                font-weight: normal;
+                padding:0;
+                margin: 0;
+                text-align: left;
+                line-height: 1.3;
+            }
+
+            h1, h2, h3, h4, h5, h6 {
+                word-break: normal;
+            }
+
+            h1 {font-size: 40px;}
+            h2 {font-size: 36px;}
+            h3 {font-size: 32px;}
+            h4 {font-size: 28px;}
+            h5 {font-size: 24px;}
+            h6 {font-size: 20px;}
+            body, table.body, p, td {font-size: 14px;line-height:19px;}
+
+            p.lead, p.lede, p.leed {
+                font-size: 18px;
+                line-height:21px;
+            }
+
+            p {
+                margin-bottom: 10px;
+            }
+
+            small {
+                font-size: 10px;
+            }
+
+            a {
+                color: #2ba6cb;
+                text-decoration: none;
+            }
+
+            a:hover {
+                color: #2795b6 !important;
+            }
+
+            a:active {
+                color: #2795b6 !important;
+            }
+
+            a:visited {
+                color: #2ba6cb !important;
+            }
+
+            h1 a,
+            h2 a,
+            h3 a,
+            h4 a,
+            h5 a,
+            h6 a {
+                color: #2ba6cb;
+            }
+
+            h1 a:active,
+            h2 a:active,
+            h3 a:active,
+            h4 a:active,
+            h5 a:active,
+            h6 a:active {
+                color: #2ba6cb !important;
+            }
+
+            h1 a:visited,
+            h2 a:visited,
+            h3 a:visited,
+            h4 a:visited,
+            h5 a:visited,
+            h6 a:visited {
+                color: #2ba6cb !important;
+            }
+
+            /* Panels */
+
+            .panel {
+                background: #f2f2f2;
+                border: 1px solid #d9d9d9;
+                padding: 10px !important;
+            }
+
+            .sub-grid table {
+                width: 100%;
+            }
+
+            .sub-grid td.sub-columns {
+                padding-bottom: 0;
+            }
+
+            /* Buttons */
+
+            table.button,
+            table.tiny-button,
+            table.small-button,
+            table.medium-button,
+            table.large-button {
+                width: 100%;
+                overflow: hidden;
+            }
+
+            table.button td,
+            table.tiny-button td,
+            table.small-button td,
+            table.medium-button td,
+            table.large-button td {
+                display: block;
+                width: auto !important;
+                text-align: center;
+                background: #2ba6cb;
+                border: 1px solid #2284a1;
+                color: #ffffff;
+                padding: 8px 0;
+            }
+
+            table.tiny-button td {
+                padding: 5px 0 4px;
+            }
+
+            table.small-button td {
+                padding: 8px 0 7px;
+            }
+
+            table.medium-button td {
+                padding: 12px 0 10px;
+            }
+
+            table.large-button td {
+                padding: 21px 0 18px;
+            }
+
+            table.button td a,
+            table.tiny-button td a,
+            table.small-button td a,
+            table.medium-button td a,
+            table.large-button td a {
+                font-weight: bold;
+                text-decoration: none;
+                font-family: Helvetica, Arial, sans-serif;
+                color: #ffffff;
+                font-size: 16px;
+            }
+
+            table.tiny-button td a {
+                font-size: 12px;
+                font-weight: normal;
+            }
+
+            table.small-button td a {
+                font-size: 16px;
+            }
+
+            table.medium-button td a {
+                font-size: 20px;
+            }
+
+            table.large-button td a {
+                font-size: 24px;
+            }
+
+            table.button:hover td,
+            table.button:visited td,
+            table.button:active td {
+                background: #2795b6 !important;
+            }
+
+            table.button:hover td a,
+            table.button:visited td a,
+            table.button:active td a {
+                color: #fff !important;
+            }
+
+            table.button:hover td,
+            table.tiny-button:hover td,
+            table.small-button:hover td,
+            table.medium-button:hover td,
+            table.large-button:hover td {
+                background: #2795b6 !important;
+            }
+
+            table.button:hover td a,
+            table.button:active td a,
+            table.button td a:visited,
+            table.tiny-button:hover td a,
+            table.tiny-button:active td a,
+            table.tiny-button td a:visited,
+            table.small-button:hover td a,
+            table.small-button:active td a,
+            table.small-button td a:visited,
+            table.medium-button:hover td a,
+            table.medium-button:active td a,
+            table.medium-button td a:visited,
+            table.large-button:hover td a,
+            table.large-button:active td a,
+            table.large-button td a:visited {
+                color: #ffffff !important;
+            }
+
+            table.secondary td {
+                background: #e9e9e9;
+                border-color: #d0d0d0;
+                color: #555;
+            }
+
+            table.secondary td a {
+                color: #555;
+            }
+
+            table.secondary:hover td {
+                background: #d0d0d0 !important;
+                color: #555;
+            }
+
+            table.secondary:hover td a,
+            table.secondary td a:visited,
+            table.secondary:active td a {
+                color: #555 !important;
+            }
+
+            table.success td {
+                background: #5da423;
+                border-color: #457a1a;
+            }
+
+            table.success:hover td {
+                background: #457a1a !important;
+            }
+
+            table.alert td {
+                background: #c60f13;
+                border-color: #970b0e;
+            }
+
+            table.alert:hover td {
+                background: #970b0e !important;
+            }
+
+            table.radius td {
+                -webkit-border-radius: 3px;
+                -moz-border-radius: 3px;
+                border-radius: 3px;
+            }
+
+            table.round td {
+                -webkit-border-radius: 500px;
+                -moz-border-radius: 500px;
+                border-radius: 500px;
+            }
+
+            /* Outlook First */
+
+            body.outlook p {
+                display: inline !important;
+            }
+
+            /*  Media Queries */
+
+            @media only screen and (max-width: 600px) {
+
+                table[class="body"] img {
+                    width: auto !important;
+                    height: auto !important;
+                }
+
+                table[class="body"] center {
+                    min-width: 0 !important;
+                }
+
+                table[class="body"] .container {
+                    width: 95% !important;
+                }
+
+                table[class="body"] .row {
+                    width: 100% !important;
+                    display: block !important;
+                }
+
+                table[class="body"] .wrapper {
+                    display: block !important;
+                    padding-right: 0 !important;
+                }
+
+                table[class="body"] .columns,
+                table[class="body"] .column {
+                    table-layout: fixed !important;
+                    float: none !important;
+                    width: 100% !important;
+                    padding-right: 0px !important;
+                    padding-left: 0px !important;
+                    display: block !important;
+                }
+
+                table[class="body"] .wrapper.first .columns,
+                table[class="body"] .wrapper.first .column {
+                    display: table !important;
+                }
+
+                table[class="body"] table.columns td,
+                table[class="body"] table.column td {
+                    width: 100% !important;
+                }
+
+                table[class="body"] .columns td.one,
+                table[class="body"] .column td.one { width: 8.333333% !important; }
+                table[class="body"] .columns td.two,
+                table[class="body"] .column td.two { width: 16.666666% !important; }
+                table[class="body"] .columns td.three,
+                table[class="body"] .column td.three { width: 25% !important; }
+                table[class="body"] .columns td.four,
+                table[class="body"] .column td.four { width: 33.333333% !important; }
+                table[class="body"] .columns td.five,
+                table[class="body"] .column td.five { width: 41.666666% !important; }
+                table[class="body"] .columns td.six,
+                table[class="body"] .column td.six { width: 50% !important; }
+                table[class="body"] .columns td.seven,
+                table[class="body"] .column td.seven { width: 58.333333% !important; }
+                table[class="body"] .columns td.eight,
+                table[class="body"] .column td.eight { width: 66.666666% !important; }
+                table[class="body"] .columns td.nine,
+                table[class="body"] .column td.nine { width: 75% !important; }
+                table[class="body"] .columns td.ten,
+                table[class="body"] .column td.ten { width: 83.333333% !important; }
+                table[class="body"] .columns td.eleven,
+                table[class="body"] .column td.eleven { width: 91.666666% !important; }
+                table[class="body"] .columns td.twelve,
+                table[class="body"] .column td.twelve { width: 100% !important; }
+
+                table[class="body"] td.offset-by-one,
+                table[class="body"] td.offset-by-two,
+                table[class="body"] td.offset-by-three,
+                table[class="body"] td.offset-by-four,
+                table[class="body"] td.offset-by-five,
+                table[class="body"] td.offset-by-six,
+                table[class="body"] td.offset-by-seven,
+                table[class="body"] td.offset-by-eight,
+                table[class="body"] td.offset-by-nine,
+                table[class="body"] td.offset-by-ten,
+                table[class="body"] td.offset-by-eleven {
+                    padding-left: 0 !important;
+                }
+
+                table[class="body"] table.columns td.expander {
+                    width: 1px !important;
+                }
+
+                table[class="body"] .right-text-pad,
+                table[class="body"] .text-pad-right {
+                    padding-left: 10px !important;
+                }
+
+                table[class="body"] .left-text-pad,
+                table[class="body"] .text-pad-left {
+                    padding-right: 10px !important;
+                }
+
+                table[class="body"] .hide-for-small,
+                table[class="body"] .show-for-desktop {
+                    display: none !important;
+                }
+
+                table[class="body"] .show-for-small,
+                table[class="body"] .hide-for-desktop {
+                    display: inherit !important;
+                }
+            }
+
+        </style>
+        <style>
+
+            table.facebook td {
+                background: #3b5998;
+                border-color: #2d4473;
+            }
+
+            table.facebook:hover td {
+                background: #2d4473 !important;
+            }
+
+            table.twitter td {
+                background: #00acee;
+                border-color: #0087bb;
+            }
+
+            table.twitter:hover td {
+                background: #0087bb !important;
+            }
+
+            table.google-plus td {
+                background-color: #DB4A39;
+                border-color: #CC0000;
+            }
+
+            table.google-plus:hover td {
+                background: #CC0000 !important;
+            }
+
+            .template-label {
+                color: #ffffff;
+                font-weight: bold;
+                font-size: 11px;
+            }
+
+            .callout .wrapper {
+                padding-bottom: 20px;
+            }
+
+            .callout .panel {
+                background: #ECF8FF;
+                border-color: #b9e5ff;
+            }
+
+            .header {
+                background: #999999;
+            }
+
+            .footer .wrapper {
+                background: #ebebeb;
+            }
+
+            .footer h5 {
+                padding-bottom: 10px;
+            }
+
+            table.columns .text-pad {
+                padding-left: 10px;
+                padding-right: 10px;
+            }
+
+            table.columns .left-text-pad {
+                padding-left: 10px;
+            }
+
+            table.columns .right-text-pad {
+                padding-right: 10px;
+            }
+
+            @media only screen and (max-width: 600px) {
+
+                table[class="body"] .right-text-pad {
+                    padding-left: 10px !important;
+                }
+
+                table[class="body"] .left-text-pad {
+                    padding-right: 10px !important;
+                }
+            }
+
+        </style>
     </head>
     <body>
-        Welcome, <strong>${email}</strong>!
+        <table class="body">
+            <tr>
+                <td class="center" align="center" valign="top">
+                    <table class="container">
+                        <tr>
+                            <td>
+                                <table class="row">
+                                    <tr>
+                                        <td class="wrapper last">
+
+                                            <table class="twelve columns">
+                                                <tr>
+                                                    <td>
+                                                        <h1>Hi, ${email}!</h1>
+
+                                                        <h3>Account creation request.</h3>
+
+                                                        <p>It seems someone has requested creation of an account  at <strong>${applicationName}</strong>. If that was you then please follow this <a href="${confirmationUrl}">link</a> where you can set a new password. Otherwise please just ignore this email.</p>
+                                                    </td>
+                                                </tr>
+                                            </table>
 
-        <p>
-            Please click on the link to confirm that you own this email and create an account: <a href="${confirmationUrl}">confirm</a>.
-        </p>
+                                        </td>
+                                    </tr>
+                                </table>
 
+                            </td>
+                        </tr>
+                    </table>
+                </td>
+            </tr>
+        </table>
     </body>
 </html>

http://git-wip-us.apache.org/repos/asf/isis/blob/08466a13/core/runtime/src/main/java/org/apache/isis/core/runtime/services/email/PasswordResetTemplate.html
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/services/email/PasswordResetTemplate.html b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/email/PasswordResetTemplate.html
new file mode 100644
index 0000000..7712def
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/email/PasswordResetTemplate.html
@@ -0,0 +1,817 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+        <meta name="viewport" content="width=device-width"/>
+        <style>
+            /**********************************************
+            * Ink v1.0.5 - Copyright 2013 ZURB Inc        *
+            **********************************************/
+
+            /* Client-specific Styles & Reset */
+
+            #outlook a {
+                padding:0;
+            }
+
+            body{
+                width:100% !important;
+                min-width: 100%;
+                -webkit-text-size-adjust:100%;
+                -ms-text-size-adjust:100%;
+                margin:0;
+                padding:0;
+            }
+
+            .ExternalClass {
+                width:100%;
+            }
+
+            .ExternalClass,
+            .ExternalClass p,
+            .ExternalClass span,
+            .ExternalClass font,
+            .ExternalClass td,
+            .ExternalClass div {
+                line-height: 100%;
+            }
+
+            #backgroundTable {
+                margin:0;
+                padding:0;
+                width:100% !important;
+                line-height: 100% !important;
+            }
+
+            img {
+                outline:none;
+                text-decoration:none;
+                -ms-interpolation-mode: bicubic;
+                width: auto;
+                max-width: 100%;
+                float: left;
+                clear: both;
+                display: block;
+            }
+
+            center {
+                width: 100%;
+                min-width: 580px;
+            }
+
+            a img {
+                border: none;
+            }
+
+            p {
+                margin: 0 0 0 10px;
+            }
+
+            table {
+                border-spacing: 0;
+                border-collapse: collapse;
+            }
+
+            td {
+                word-break: break-word;
+                -webkit-hyphens: auto;
+                -moz-hyphens: auto;
+                hyphens: auto;
+                border-collapse: collapse !important;
+            }
+
+            table, tr, td {
+                padding: 0;
+                vertical-align: top;
+                text-align: left;
+            }
+
+            hr {
+                color: #d9d9d9;
+                background-color: #d9d9d9;
+                height: 1px;
+                border: none;
+            }
+
+            /* Responsive Grid */
+
+            table.body {
+                height: 100%;
+                width: 100%;
+            }
+
+            table.container {
+                width: 580px;
+                margin: 0 auto;
+                text-align: inherit;
+            }
+
+            table.row {
+                padding: 0px;
+                width: 100%;
+                position: relative;
+            }
+
+            table.container table.row {
+                display: block;
+            }
+
+            td.wrapper {
+                padding: 10px 20px 0px 0px;
+                position: relative;
+            }
+
+            table.columns,
+            table.column {
+                margin: 0 auto;
+            }
+
+            table.columns td,
+            table.column td {
+                padding: 0px 0px 10px;
+            }
+
+            table.columns td.sub-columns,
+            table.column td.sub-columns,
+            table.columns td.sub-column,
+            table.column td.sub-column {
+                padding-right: 10px;
+            }
+
+            td.sub-column, td.sub-columns {
+                min-width: 0px;
+            }
+
+            table.row td.last,
+            table.container td.last {
+                padding-right: 0px;
+            }
+
+            table.one { width: 30px; }
+            table.two { width: 80px; }
+            table.three { width: 130px; }
+            table.four { width: 180px; }
+            table.five { width: 230px; }
+            table.six { width: 280px; }
+            table.seven { width: 330px; }
+            table.eight { width: 380px; }
+            table.nine { width: 430px; }
+            table.ten { width: 480px; }
+            table.eleven { width: 530px; }
+            table.twelve { width: 580px; }
+
+            table.one center { min-width: 30px; }
+            table.two center { min-width: 80px; }
+            table.three center { min-width: 130px; }
+            table.four center { min-width: 180px; }
+            table.five center { min-width: 230px; }
+            table.six center { min-width: 280px; }
+            table.seven center { min-width: 330px; }
+            table.eight center { min-width: 380px; }
+            table.nine center { min-width: 430px; }
+            table.ten center { min-width: 480px; }
+            table.eleven center { min-width: 530px; }
+            table.twelve center { min-width: 580px; }
+
+            table.one .panel center { min-width: 10px; }
+            table.two .panel center { min-width: 60px; }
+            table.three .panel center { min-width: 110px; }
+            table.four .panel center { min-width: 160px; }
+            table.five .panel center { min-width: 210px; }
+            table.six .panel center { min-width: 260px; }
+            table.seven .panel center { min-width: 310px; }
+            table.eight .panel center { min-width: 360px; }
+            table.nine .panel center { min-width: 410px; }
+            table.ten .panel center { min-width: 460px; }
+            table.eleven .panel center { min-width: 510px; }
+            table.twelve .panel center { min-width: 560px; }
+
+            .body .columns td.one,
+            .body .column td.one { width: 8.333333%; }
+            .body .columns td.two,
+            .body .column td.two { width: 16.666666%; }
+            .body .columns td.three,
+            .body .column td.three { width: 25%; }
+            .body .columns td.four,
+            .body .column td.four { width: 33.333333%; }
+            .body .columns td.five,
+            .body .column td.five { width: 41.666666%; }
+            .body .columns td.six,
+            .body .column td.six { width: 50%; }
+            .body .columns td.seven,
+            .body .column td.seven { width: 58.333333%; }
+            .body .columns td.eight,
+            .body .column td.eight { width: 66.666666%; }
+            .body .columns td.nine,
+            .body .column td.nine { width: 75%; }
+            .body .columns td.ten,
+            .body .column td.ten { width: 83.333333%; }
+            .body .columns td.eleven,
+            .body .column td.eleven { width: 91.666666%; }
+            .body .columns td.twelve,
+            .body .column td.twelve { width: 100%; }
+
+            td.offset-by-one { padding-left: 50px; }
+            td.offset-by-two { padding-left: 100px; }
+            td.offset-by-three { padding-left: 150px; }
+            td.offset-by-four { padding-left: 200px; }
+            td.offset-by-five { padding-left: 250px; }
+            td.offset-by-six { padding-left: 300px; }
+            td.offset-by-seven { padding-left: 350px; }
+            td.offset-by-eight { padding-left: 400px; }
+            td.offset-by-nine { padding-left: 450px; }
+            td.offset-by-ten { padding-left: 500px; }
+            td.offset-by-eleven { padding-left: 550px; }
+
+            td.expander {
+                visibility: hidden;
+                width: 0px;
+                padding: 0 !important;
+            }
+
+            table.columns .text-pad,
+            table.column .text-pad {
+                padding-left: 10px;
+                padding-right: 10px;
+            }
+
+            table.columns .left-text-pad,
+            table.columns .text-pad-left,
+            table.column .left-text-pad,
+            table.column .text-pad-left {
+                padding-left: 10px;
+            }
+
+            table.columns .right-text-pad,
+            table.columns .text-pad-right,
+            table.column .right-text-pad,
+            table.column .text-pad-right {
+                padding-right: 10px;
+            }
+
+            /* Block Grid */
+
+            .block-grid {
+                width: 100%;
+                max-width: 580px;
+            }
+
+            .block-grid td {
+                display: inline-block;
+                padding:10px;
+            }
+
+            .two-up td {
+                width:270px;
+            }
+
+            .three-up td {
+                width:173px;
+            }
+
+            .four-up td {
+                width:125px;
+            }
+
+            .five-up td {
+                width:96px;
+            }
+
+            .six-up td {
+                width:76px;
+            }
+
+            .seven-up td {
+                width:62px;
+            }
+
+            .eight-up td {
+                width:52px;
+            }
+
+            /* Alignment & Visibility Classes */
+
+            table.center, td.center {
+                text-align: center;
+            }
+
+            h1.center,
+            h2.center,
+            h3.center,
+            h4.center,
+            h5.center,
+            h6.center {
+                text-align: center;
+            }
+
+            span.center {
+                display: block;
+                width: 100%;
+                text-align: center;
+            }
+
+            img.center {
+                margin: 0 auto;
+                float: none;
+            }
+
+            .show-for-small,
+            .hide-for-desktop {
+                display: none;
+            }
+
+            /* Typography */
+
+            body, table.body, h1, h2, h3, h4, h5, h6, p, td {
+                color: #222222;
+                font-family: "Helvetica", "Arial", sans-serif;
+                font-weight: normal;
+                padding:0;
+                margin: 0;
+                text-align: left;
+                line-height: 1.3;
+            }
+
+            h1, h2, h3, h4, h5, h6 {
+                word-break: normal;
+            }
+
+            h1 {font-size: 40px;}
+            h2 {font-size: 36px;}
+            h3 {font-size: 32px;}
+            h4 {font-size: 28px;}
+            h5 {font-size: 24px;}
+            h6 {font-size: 20px;}
+            body, table.body, p, td {font-size: 14px;line-height:19px;}
+
+            p.lead, p.lede, p.leed {
+                font-size: 18px;
+                line-height:21px;
+            }
+
+            p {
+                margin-bottom: 10px;
+            }
+
+            small {
+                font-size: 10px;
+            }
+
+            a {
+                color: #2ba6cb;
+                text-decoration: none;
+            }
+
+            a:hover {
+                color: #2795b6 !important;
+            }
+
+            a:active {
+                color: #2795b6 !important;
+            }
+
+            a:visited {
+                color: #2ba6cb !important;
+            }
+
+            h1 a,
+            h2 a,
+            h3 a,
+            h4 a,
+            h5 a,
+            h6 a {
+                color: #2ba6cb;
+            }
+
+            h1 a:active,
+            h2 a:active,
+            h3 a:active,
+            h4 a:active,
+            h5 a:active,
+            h6 a:active {
+                color: #2ba6cb !important;
+            }
+
+            h1 a:visited,
+            h2 a:visited,
+            h3 a:visited,
+            h4 a:visited,
+            h5 a:visited,
+            h6 a:visited {
+                color: #2ba6cb !important;
+            }
+
+            /* Panels */
+
+            .panel {
+                background: #f2f2f2;
+                border: 1px solid #d9d9d9;
+                padding: 10px !important;
+            }
+
+            .sub-grid table {
+                width: 100%;
+            }
+
+            .sub-grid td.sub-columns {
+                padding-bottom: 0;
+            }
+
+            /* Buttons */
+
+            table.button,
+            table.tiny-button,
+            table.small-button,
+            table.medium-button,
+            table.large-button {
+                width: 100%;
+                overflow: hidden;
+            }
+
+            table.button td,
+            table.tiny-button td,
+            table.small-button td,
+            table.medium-button td,
+            table.large-button td {
+                display: block;
+                width: auto !important;
+                text-align: center;
+                background: #2ba6cb;
+                border: 1px solid #2284a1;
+                color: #ffffff;
+                padding: 8px 0;
+            }
+
+            table.tiny-button td {
+                padding: 5px 0 4px;
+            }
+
+            table.small-button td {
+                padding: 8px 0 7px;
+            }
+
+            table.medium-button td {
+                padding: 12px 0 10px;
+            }
+
+            table.large-button td {
+                padding: 21px 0 18px;
+            }
+
+            table.button td a,
+            table.tiny-button td a,
+            table.small-button td a,
+            table.medium-button td a,
+            table.large-button td a {
+                font-weight: bold;
+                text-decoration: none;
+                font-family: Helvetica, Arial, sans-serif;
+                color: #ffffff;
+                font-size: 16px;
+            }
+
+            table.tiny-button td a {
+                font-size: 12px;
+                font-weight: normal;
+            }
+
+            table.small-button td a {
+                font-size: 16px;
+            }
+
+            table.medium-button td a {
+                font-size: 20px;
+            }
+
+            table.large-button td a {
+                font-size: 24px;
+            }
+
+            table.button:hover td,
+            table.button:visited td,
+            table.button:active td {
+                background: #2795b6 !important;
+            }
+
+            table.button:hover td a,
+            table.button:visited td a,
+            table.button:active td a {
+                color: #fff !important;
+            }
+
+            table.button:hover td,
+            table.tiny-button:hover td,
+            table.small-button:hover td,
+            table.medium-button:hover td,
+            table.large-button:hover td {
+                background: #2795b6 !important;
+            }
+
+            table.button:hover td a,
+            table.button:active td a,
+            table.button td a:visited,
+            table.tiny-button:hover td a,
+            table.tiny-button:active td a,
+            table.tiny-button td a:visited,
+            table.small-button:hover td a,
+            table.small-button:active td a,
+            table.small-button td a:visited,
+            table.medium-button:hover td a,
+            table.medium-button:active td a,
+            table.medium-button td a:visited,
+            table.large-button:hover td a,
+            table.large-button:active td a,
+            table.large-button td a:visited {
+                color: #ffffff !important;
+            }
+
+            table.secondary td {
+                background: #e9e9e9;
+                border-color: #d0d0d0;
+                color: #555;
+            }
+
+            table.secondary td a {
+                color: #555;
+            }
+
+            table.secondary:hover td {
+                background: #d0d0d0 !important;
+                color: #555;
+            }
+
+            table.secondary:hover td a,
+            table.secondary td a:visited,
+            table.secondary:active td a {
+                color: #555 !important;
+            }
+
+            table.success td {
+                background: #5da423;
+                border-color: #457a1a;
+            }
+
+            table.success:hover td {
+                background: #457a1a !important;
+            }
+
+            table.alert td {
+                background: #c60f13;
+                border-color: #970b0e;
+            }
+
+            table.alert:hover td {
+                background: #970b0e !important;
+            }
+
+            table.radius td {
+                -webkit-border-radius: 3px;
+                -moz-border-radius: 3px;
+                border-radius: 3px;
+            }
+
+            table.round td {
+                -webkit-border-radius: 500px;
+                -moz-border-radius: 500px;
+                border-radius: 500px;
+            }
+
+            /* Outlook First */
+
+            body.outlook p {
+                display: inline !important;
+            }
+
+            /*  Media Queries */
+
+            @media only screen and (max-width: 600px) {
+
+                table[class="body"] img {
+                    width: auto !important;
+                    height: auto !important;
+                }
+
+                table[class="body"] center {
+                    min-width: 0 !important;
+                }
+
+                table[class="body"] .container {
+                    width: 95% !important;
+                }
+
+                table[class="body"] .row {
+                    width: 100% !important;
+                    display: block !important;
+                }
+
+                table[class="body"] .wrapper {
+                    display: block !important;
+                    padding-right: 0 !important;
+                }
+
+                table[class="body"] .columns,
+                table[class="body"] .column {
+                    table-layout: fixed !important;
+                    float: none !important;
+                    width: 100% !important;
+                    padding-right: 0px !important;
+                    padding-left: 0px !important;
+                    display: block !important;
+                }
+
+                table[class="body"] .wrapper.first .columns,
+                table[class="body"] .wrapper.first .column {
+                    display: table !important;
+                }
+
+                table[class="body"] table.columns td,
+                table[class="body"] table.column td {
+                    width: 100% !important;
+                }
+
+                table[class="body"] .columns td.one,
+                table[class="body"] .column td.one { width: 8.333333% !important; }
+                table[class="body"] .columns td.two,
+                table[class="body"] .column td.two { width: 16.666666% !important; }
+                table[class="body"] .columns td.three,
+                table[class="body"] .column td.three { width: 25% !important; }
+                table[class="body"] .columns td.four,
+                table[class="body"] .column td.four { width: 33.333333% !important; }
+                table[class="body"] .columns td.five,
+                table[class="body"] .column td.five { width: 41.666666% !important; }
+                table[class="body"] .columns td.six,
+                table[class="body"] .column td.six { width: 50% !important; }
+                table[class="body"] .columns td.seven,
+                table[class="body"] .column td.seven { width: 58.333333% !important; }
+                table[class="body"] .columns td.eight,
+                table[class="body"] .column td.eight { width: 66.666666% !important; }
+                table[class="body"] .columns td.nine,
+                table[class="body"] .column td.nine { width: 75% !important; }
+                table[class="body"] .columns td.ten,
+                table[class="body"] .column td.ten { width: 83.333333% !important; }
+                table[class="body"] .columns td.eleven,
+                table[class="body"] .column td.eleven { width: 91.666666% !important; }
+                table[class="body"] .columns td.twelve,
+                table[class="body"] .column td.twelve { width: 100% !important; }
+
+                table[class="body"] td.offset-by-one,
+                table[class="body"] td.offset-by-two,
+                table[class="body"] td.offset-by-three,
+                table[class="body"] td.offset-by-four,
+                table[class="body"] td.offset-by-five,
+                table[class="body"] td.offset-by-six,
+                table[class="body"] td.offset-by-seven,
+                table[class="body"] td.offset-by-eight,
+                table[class="body"] td.offset-by-nine,
+                table[class="body"] td.offset-by-ten,
+                table[class="body"] td.offset-by-eleven {
+                    padding-left: 0 !important;
+                }
+
+                table[class="body"] table.columns td.expander {
+                    width: 1px !important;
+                }
+
+                table[class="body"] .right-text-pad,
+                table[class="body"] .text-pad-right {
+                    padding-left: 10px !important;
+                }
+
+                table[class="body"] .left-text-pad,
+                table[class="body"] .text-pad-left {
+                    padding-right: 10px !important;
+                }
+
+                table[class="body"] .hide-for-small,
+                table[class="body"] .show-for-desktop {
+                    display: none !important;
+                }
+
+                table[class="body"] .show-for-small,
+                table[class="body"] .hide-for-desktop {
+                    display: inherit !important;
+                }
+            }
+
+        </style>
+        <style>
+
+            table.facebook td {
+                background: #3b5998;
+                border-color: #2d4473;
+            }
+
+            table.facebook:hover td {
+                background: #2d4473 !important;
+            }
+
+            table.twitter td {
+                background: #00acee;
+                border-color: #0087bb;
+            }
+
+            table.twitter:hover td {
+                background: #0087bb !important;
+            }
+
+            table.google-plus td {
+                background-color: #DB4A39;
+                border-color: #CC0000;
+            }
+
+            table.google-plus:hover td {
+                background: #CC0000 !important;
+            }
+
+            .template-label {
+                color: #ffffff;
+                font-weight: bold;
+                font-size: 11px;
+            }
+
+            .callout .wrapper {
+                padding-bottom: 20px;
+            }
+
+            .callout .panel {
+                background: #ECF8FF;
+                border-color: #b9e5ff;
+            }
+
+            .header {
+                background: #999999;
+            }
+
+            .footer .wrapper {
+                background: #ebebeb;
+            }
+
+            .footer h5 {
+                padding-bottom: 10px;
+            }
+
+            table.columns .text-pad {
+                padding-left: 10px;
+                padding-right: 10px;
+            }
+
+            table.columns .left-text-pad {
+                padding-left: 10px;
+            }
+
+            table.columns .right-text-pad {
+                padding-right: 10px;
+            }
+
+            @media only screen and (max-width: 600px) {
+
+                table[class="body"] .right-text-pad {
+                    padding-left: 10px !important;
+                }
+
+                table[class="body"] .left-text-pad {
+                    padding-right: 10px !important;
+                }
+            }
+
+        </style>
+    </head>
+    <body>
+        <table class="body">
+            <tr>
+                <td class="center" align="center" valign="top">
+                    <center>
+
+                        <table class="container">
+                            <tr>
+                                <td>
+                                    <table class="row">
+                                        <tr>
+                                            <td class="wrapper last">
+
+                                                <table class="twelve columns">
+                                                    <tr>
+                                                        <td>
+                                                            <h1>Hi, ${email}!</h1>
+
+                                                            <h3>Password reset request.</h3>
+
+                                                            <p>It seems someone has requested reset of your password for <strong>${applicationName}</strong>. If that was you then please follow this <a href="${confirmationUrl}">link</a> where you can set a new password. Otherwise please just ignore this email.</p>
+                                                        </td>
+                                                    </tr>
+                                                </table>
+
+                                            </td>
+                                        </tr>
+                                    </table>
+
+                                </td>
+                            </tr>
+                        </table>
+
+                    </center>
+                </td>
+            </tr>
+        </table>
+    </body>
+</html>