1
0
mirror of https://github.com/bitwarden/server synced 2025-12-06 00:03:34 +00:00

[PM-21741] MJML welcome emails (#6549)

feat: Implement welcome email using MJML templating

- Implement MJML templates for welcome emails (individual, family, org)
- Create reusable MJML components (mj-bw-icon-row, mj-bw-learn-more-footer)
- Update documentation for MJML development process
This commit is contained in:
Ike
2025-11-10 13:37:11 -05:00
committed by GitHub
parent b2543b5c0f
commit 746b413cff
14 changed files with 580 additions and 262 deletions

View File

@@ -29,8 +29,8 @@
.mj-outlook-group-fix { width:100% !important; }
</style>
<![endif]-->
<style type="text/css">
@media only screen and (min-width:480px) {
.mj-column-per-70 { width:70% !important; max-width: 70%; }
@@ -45,19 +45,19 @@
.moz-text-html .mj-column-per-100 { width:100% !important; max-width: 100%; }
.moz-text-html .mj-column-per-90 { width:90% !important; max-width: 90%; }
</style>
<style type="text/css">
@media only screen and (max-width:479px) {
table.mj-full-width-mobile { width: 100% !important; }
td.mj-full-width-mobile { width: auto !important; }
}
</style>
<style type="text/css">
.border-fix > table {
border-collapse: separate !important;
@@ -65,250 +65,258 @@
.border-fix > table > tbody > tr > td {
border-radius: 3px;
}
@media only screen and
(max-width: 480px) { .hide-small-img { display: none !important; } .send-bubble { padding-left: 20px; padding-right: 20px; width: 90% !important; } }
@media only screen and (max-width: 480px) {
.hide-small-img {
display: none !important;
}
.send-bubble {
padding-left: 20px;
padding-right: 20px;
width: 90% !important;
}
}
</style>
<!-- Responsive icon visibility -->
</head>
<body style="word-spacing:normal;background-color:#e6e9ef;">
<div class="border-fix" style="background-color:#e6e9ef;" lang="und" dir="auto">
<!-- Blue Header Section -->
<!--[if mso | IE]><table align="center" border="0" cellpadding="0" cellspacing="0" class="border-fix-outlook" role="presentation" style="width:660px;" width="660" ><tr><td style="line-height:0px;font-size:0px;mso-line-height-rule:exactly;"><![endif]-->
<div class="border-fix" style="margin:0px auto;max-width:660px;">
<table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="width:100%;">
<tbody>
<tr>
<td style="direction:ltr;font-size:0px;padding:20px 20px 10px 20px;text-align:center;">
<!--[if mso | IE]><table role="presentation" border="0" cellpadding="0" cellspacing="0"><tr><td class="" width="660px" ><![endif]-->
<table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="background:#175ddc;background-color:#175ddc;width:100%;border-radius:4px 4px 0px 0px;">
<tbody>
<tr>
<td>
<!--[if mso | IE]><table align="center" border="0" cellpadding="0" cellspacing="0" class="" role="presentation" style="width:620px;" width="620" bgcolor="#175ddc" ><tr><td style="line-height:0px;font-size:0px;mso-line-height-rule:exactly;"><![endif]-->
<div style="margin:0px auto;border-radius:4px 4px 0px 0px;max-width:620px;">
<table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="width:100%;border-radius:4px 4px 0px 0px;">
<tbody>
<tr>
<td style="direction:ltr;font-size:0px;padding:20px 0;text-align:center;">
<!--[if mso | IE]><table role="presentation" border="0" cellpadding="0" cellspacing="0"><tr><td class="" style="vertical-align:top;width:434px;" ><![endif]-->
<div class="mj-column-per-70 mj-outlook-group-fix" style="font-size:0px;text-align:left;direction:ltr;display:inline-block;vertical-align:top;width:100%;">
<table border="0" cellpadding="0" cellspacing="0" role="presentation" style="vertical-align:top;" width="100%">
<tbody>
<tr>
<td align="left" style="font-size:0px;padding:10px 25px;word-break:break-word;">
<table border="0" cellpadding="0" cellspacing="0" role="presentation" style="border-collapse:collapse;border-spacing:0px;">
<tbody>
<tr>
<td style="width:150px;">
<img alt src="https://bitwarden.com/images/logo-horizontal-white.png" style="border:0;display:block;outline:none;text-decoration:none;height:30px;width:100%;font-size:16px;" width="150" height="30">
</td>
</tr>
</tbody>
</table>
</td>
</tr>
<tr>
<td align="left" style="font-size:0px;padding:10px 25px;padding-top:0;padding-bottom:0;word-break:break-word;">
<div style="font-family:'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:16px;line-height:1;text-align:left;color:#ffffff;"><h1 style="font-weight: normal; font-size: 24px; line-height: 32px">
Verify your email to access this Bitwarden Send
</h1></div>
</td>
</tr>
</tbody>
</table>
</div>
<!--[if mso | IE]></td><td class="" style="vertical-align:bottom;width:186px;" ><![endif]-->
<div class="mj-column-per-30 mj-outlook-group-fix" style="font-size:0px;text-align:left;direction:ltr;display:inline-block;vertical-align:bottom;width:100%;">
<table border="0" cellpadding="0" cellspacing="0" role="presentation" style="vertical-align:bottom;" width="100%">
<tbody>
<tr>
<td align="center" class="hide-small-img" style="font-size:0px;padding:0px;word-break:break-word;">
<table border="0" cellpadding="0" cellspacing="0" role="presentation" style="border-collapse:collapse;border-spacing:0px;">
<tbody>
<tr>
<td style="width:140px;">
<img alt src="https://assets.bitwarden.com/email/v1/spot-secure-send-round.png" style="border:0;display:block;outline:none;text-decoration:none;height:140px;width:100%;font-size:16px;" width="140" height="140">
<td style="width:155px;">
<img alt src="https://assets.bitwarden.com/email/v1/spot-secure-send-round.png" style="border:0;display:block;outline:none;text-decoration:none;height:auto;width:100%;font-size:16px;" width="155" height="auto">
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</div>
<!--[if mso | IE]></td></tr></table><![endif]-->
</td>
</tr>
</tbody>
</table>
</div>
<!--[if mso | IE]></td></tr></table><![endif]-->
</td>
</tr>
</tbody>
</table>
<!--[if mso | IE]></td></tr></table><![endif]-->
</td>
</tr>
</tbody>
</table>
</div>
<!--[if mso | IE]></td></tr></table><![endif]-->
<!-- Main Content -->
<!--[if mso | IE]><table align="center" border="0" cellpadding="0" cellspacing="0" class="" role="presentation" style="width:660px;" width="660" ><tr><td style="line-height:0px;font-size:0px;mso-line-height-rule:exactly;"><![endif]-->
<div style="margin:0px auto;max-width:660px;">
<table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="width:100%;">
<tbody>
<tr>
<td style="direction:ltr;font-size:0px;padding:5px 20px 10px 20px;text-align:center;">
<!--[if mso | IE]><table role="presentation" border="0" cellpadding="0" cellspacing="0"><tr><td class="" width="660px" ><table align="center" border="0" cellpadding="0" cellspacing="0" class="" role="presentation" style="width:620px;" width="620" bgcolor="#ffffff" ><tr><td style="line-height:0px;font-size:0px;mso-line-height-rule:exactly;"><![endif]-->
<div style="background:#ffffff;background-color:#ffffff;margin:0px auto;max-width:620px;">
<table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="background:#ffffff;background-color:#ffffff;width:100%;">
<tbody>
<tr>
<td style="direction:ltr;font-size:0px;padding:20px 0;text-align:center;">
<!--[if mso | IE]><table role="presentation" border="0" cellpadding="0" cellspacing="0"><tr><td class="" style="vertical-align:top;width:620px;" ><![endif]-->
<div class="mj-column-per-100 mj-outlook-group-fix" style="font-size:0px;text-align:left;direction:ltr;display:inline-block;vertical-align:top;width:100%;">
<table border="0" cellpadding="0" cellspacing="0" role="presentation" width="100%">
<tbody>
<tr>
<td style="vertical-align:top;padding:0px;">
<table border="0" cellpadding="0" cellspacing="0" role="presentation" style width="100%">
<tbody>
<tr>
<td align="left" style="font-size:0px;padding:10px 25px;word-break:break-word;">
<div style="font-family:'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:16px;line-height:1;text-align:left;color:#1B2029;">Your verification code is:</div>
</td>
</tr>
<tr>
<td align="left" style="font-size:0px;padding:10px 25px;word-break:break-word;">
<div style="font-family:'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:32px;line-height:1;text-align:left;color:#1B2029;"><b>{{Token}}</b></div>
</td>
</tr>
<tr>
<td style="font-size:0px;word-break:break-word;">
<div style="height:20px;line-height:20px;">&#8202;</div>
</td>
</tr>
<tr>
<td align="left" style="font-size:0px;padding:10px 25px;word-break:break-word;">
<div style="font-family:'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:16px;line-height:1;text-align:left;color:#1B2029;">This code expires in {{Expiry}} minutes. After that, you'll need to
verify your email again.</div>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</div>
<!--[if mso | IE]></td></tr></table><![endif]-->
</td>
</tr>
</tbody>
</table>
</div>
<!--[if mso | IE]></td></tr></table></td></tr><tr><td class="" width="660px" ><table align="center" border="0" cellpadding="0" cellspacing="0" class="" role="presentation" style="width:620px;" width="620" bgcolor="#ffffff" ><tr><td style="line-height:0px;font-size:0px;mso-line-height-rule:exactly;"><![endif]-->
<div style="background:#ffffff;background-color:#ffffff;margin:0px auto;max-width:620px;">
<table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="background:#ffffff;background-color:#ffffff;width:100%;">
<tbody>
<tr>
<td style="direction:ltr;font-size:0px;padding:0px 0px 20px 0px;text-align:center;">
<!--[if mso | IE]><table role="presentation" border="0" cellpadding="0" cellspacing="0"><tr><td class="send-bubble-outlook" style="vertical-align:top;width:558px;" ><![endif]-->
<div class="mj-column-per-90 mj-outlook-group-fix send-bubble" style="font-size:0px;text-align:left;direction:ltr;display:inline-block;vertical-align:top;width:100%;">
<table border="0" cellpadding="0" cellspacing="0" role="presentation" width="100%">
<tbody>
<tr>
<td style="vertical-align:top;padding:0px;">
<table border="0" cellpadding="0" cellspacing="0" role="presentation" style="background-color:#DBE5F6;border-radius:16px;" width="100%">
<tbody>
<tr>
<td align="left" style="font-size:0px;padding:10px 25px;word-break:break-word;">
<div style="font-family:'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:16px;line-height:1;text-align:left;color:#1B2029;"><p>
Bitwarden Send transmits sensitive, temporary information to
others easily and securely. Learn more about
@@ -317,160 +325,160 @@
<a href="https://bitwarden.com/signup" class="link" style="text-decoration: none; color: #175ddc; font-weight: 600;">sign up</a>
to try it today.
</p></div>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</div>
<!--[if mso | IE]></td></tr></table><![endif]-->
</td>
</tr>
</tbody>
</table>
</div>
<!--[if mso | IE]></td></tr></table></td></tr></table><![endif]-->
</td>
</tr>
</tbody>
</table>
</div>
<!--[if mso | IE]></td></tr></table><![endif]-->
<!-- Learn More Section -->
<!--[if mso | IE]><table align="center" border="0" cellpadding="0" cellspacing="0" class="" role="presentation" style="width:660px;" width="660" ><tr><td style="line-height:0px;font-size:0px;mso-line-height-rule:exactly;"><![endif]-->
<div style="margin:0px auto;max-width:660px;">
<table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="width:100%;">
<tbody>
<tr>
<td style="direction:ltr;font-size:0px;padding:5px 20px 10px 20px;text-align:center;">
<!--[if mso | IE]><table role="presentation" border="0" cellpadding="0" cellspacing="0"><tr><td class="" width="660px" ><table align="center" border="0" cellpadding="0" cellspacing="0" class="" role="presentation" style="width:620px;" width="620" bgcolor="#f6f6f6" ><tr><td style="line-height:0px;font-size:0px;mso-line-height-rule:exactly;"><![endif]-->
<div style="background:#f6f6f6;background-color:#f6f6f6;margin:0px auto;border-radius:0px 0px 4px 4px;max-width:620px;">
<table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="background:#f6f6f6;background-color:#f6f6f6;width:100%;border-radius:0px 0px 4px 4px;">
<tbody>
<tr>
<td style="direction:ltr;font-size:0px;padding:5px 20px 10px 20px;text-align:center;">
<!--[if mso | IE]><table role="presentation" border="0" cellpadding="0" cellspacing="0"><tr><td class="" style="vertical-align:top;width:406px;" ><![endif]-->
<td style="direction:ltr;font-size:0px;padding:5px 10px 10px 10px;text-align:center;">
<!--[if mso | IE]><table role="presentation" border="0" cellpadding="0" cellspacing="0"><tr><td class="" style="vertical-align:top;width:420px;" ><![endif]-->
<div class="mj-column-per-70 mj-outlook-group-fix" style="font-size:0px;text-align:left;direction:ltr;display:inline-block;vertical-align:top;width:100%;">
<table border="0" cellpadding="0" cellspacing="0" role="presentation" style="vertical-align:top;" width="100%">
<tbody>
<tr>
<td align="left" style="font-size:0px;padding:10px 25px;word-break:break-word;">
<div style="font-family:'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:16px;line-height:24px;text-align:left;color:#1B2029;"><h3 style="font-size: 20px; margin: 0; line-height: 28px">
<div style="font-family:'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:16px;line-height:24px;text-align:left;color:#1B2029;"><p style="font-size: 18px; line-height: 28px; font-weight: bold;">
Learn more about Bitwarden
</h3>
</p>
Find user guides, product documentation, and videos on the
<a href="https://bitwarden.com/help/" class="link" style="text-decoration: none; color: #175ddc; font-weight: 600;"> Bitwarden Help Center</a>.</div>
</td>
</tr>
</tbody>
</table>
</div>
<!--[if mso | IE]></td><td class="" style="vertical-align:top;width:174px;" ><![endif]-->
<!--[if mso | IE]></td><td class="" style="vertical-align:top;width:180px;" ><![endif]-->
<div class="mj-column-per-30 mj-outlook-group-fix" style="font-size:0px;text-align:left;direction:ltr;display:inline-block;vertical-align:top;width:100%;">
<table border="0" cellpadding="0" cellspacing="0" role="presentation" style="vertical-align:top;" width="100%">
<tbody>
<tr>
<td align="center" class="hide-small-img" style="font-size:0px;padding:10px 25px;word-break:break-word;">
<table border="0" cellpadding="0" cellspacing="0" role="presentation" style="border-collapse:collapse;border-spacing:0px;">
<tbody>
<tr>
<td style="width:94px;">
<img alt src="https://assets.bitwarden.com/email/v1/spot-community.png" style="border:0;display:block;outline:none;text-decoration:none;height:auto;width:100%;font-size:16px;" width="94" height="auto">
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</div>
<!--[if mso | IE]></td></tr></table><![endif]-->
</td>
</tr>
</tbody>
</table>
</div>
<!--[if mso | IE]></td></tr></table></td></tr></table><![endif]-->
</td>
</tr>
</tbody>
</table>
</div>
<!--[if mso | IE]></td></tr></table><![endif]-->
<!-- Footer -->
<!--[if mso | IE]><table align="center" border="0" cellpadding="0" cellspacing="0" class="" role="presentation" style="width:660px;" width="660" ><tr><td style="line-height:0px;font-size:0px;mso-line-height-rule:exactly;"><![endif]-->
<div style="margin:0px auto;max-width:660px;">
<table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="width:100%;">
<tbody>
<tr>
<td style="direction:ltr;font-size:0px;padding:20px 0;text-align:center;">
<!--[if mso | IE]><table role="presentation" border="0" cellpadding="0" cellspacing="0"><tr><td class="" style="vertical-align:top;width:660px;" ><![endif]-->
<div class="mj-column-per-100 mj-outlook-group-fix" style="font-size:0px;text-align:left;direction:ltr;display:inline-block;vertical-align:top;width:100%;">
<table border="0" cellpadding="0" cellspacing="0" role="presentation" style="vertical-align:top;" width="100%">
<tbody>
<tr>
<td align="center" style="font-size:0px;padding:0;word-break:break-word;">
<!--[if mso | IE]><table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" ><tr><td><![endif]-->
<table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="float:none;display:inline-table;">
<tbody>
<tr>
<td style="padding:10px;vertical-align:middle;">
<table border="0" cellpadding="0" cellspacing="0" role="presentation" style="border-radius:3px;width:30px;">
@@ -485,15 +493,15 @@
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
<!--[if mso | IE]></td><td><![endif]-->
<table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="float:none;display:inline-table;">
<tbody>
<tr>
<td style="padding:10px;vertical-align:middle;">
<table border="0" cellpadding="0" cellspacing="0" role="presentation" style="border-radius:3px;width:30px;">
@@ -508,15 +516,15 @@
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
<!--[if mso | IE]></td><td><![endif]-->
<table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="float:none;display:inline-table;">
<tbody>
<tr>
<td style="padding:10px;vertical-align:middle;">
<table border="0" cellpadding="0" cellspacing="0" role="presentation" style="border-radius:3px;width:30px;">
@@ -531,15 +539,15 @@
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
<!--[if mso | IE]></td><td><![endif]-->
<table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="float:none;display:inline-table;">
<tbody>
<tr>
<td style="padding:10px;vertical-align:middle;">
<table border="0" cellpadding="0" cellspacing="0" role="presentation" style="border-radius:3px;width:30px;">
@@ -554,15 +562,15 @@
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
<!--[if mso | IE]></td><td><![endif]-->
<table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="float:none;display:inline-table;">
<tbody>
<tr>
<td style="padding:10px;vertical-align:middle;">
<table border="0" cellpadding="0" cellspacing="0" role="presentation" style="border-radius:3px;width:30px;">
@@ -577,15 +585,15 @@
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
<!--[if mso | IE]></td><td><![endif]-->
<table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="float:none;display:inline-table;">
<tbody>
<tr>
<td style="padding:10px;vertical-align:middle;">
<table border="0" cellpadding="0" cellspacing="0" role="presentation" style="border-radius:3px;width:30px;">
@@ -600,15 +608,15 @@
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
<!--[if mso | IE]></td><td><![endif]-->
<table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="float:none;display:inline-table;">
<tbody>
<tr>
<td style="padding:10px;vertical-align:middle;">
<table border="0" cellpadding="0" cellspacing="0" role="presentation" style="border-radius:3px;width:30px;">
@@ -623,20 +631,20 @@
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
<!--[if mso | IE]></td></tr></table><![endif]-->
</td>
</tr>
<tr>
<td align="center" style="font-size:0px;padding:10px 25px;word-break:break-word;">
<div style="font-family:'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:12px;line-height:16px;text-align:center;color:#5A6D91;"><p style="margin-bottom: 5px">
© 2025 Bitwarden Inc. 1 N. Calle Cesar Chavez, Suite 102, Santa
Barbara, CA, USA
@@ -647,29 +655,28 @@
<a href="https://bitwarden.com/">bitwarden.com</a> |
<a href="https://bitwarden.com/help/emails-from-bitwarden/">Learn why we include this</a>
</p></div>
</td>
</tr>
</tbody>
</table>
</div>
<!--[if mso | IE]></td></tr></table><![endif]-->
</td>
</tr>
</tbody>
</table>
</div>
<!--[if mso | IE]></td></tr></table><![endif]-->
</div>
</body>
</html>

View File

@@ -1,5 +1,7 @@
{
"packages": [
"components/mj-bw-hero"
"components/mj-bw-hero",
"components/mj-bw-icon-row",
"components/mj-bw-learn-more-footer"
]
}

View File

@@ -45,7 +45,7 @@ When using MJML templating you can use the above [commands](#building-mjml-files
Not all MJML tags have the same attributes, it is highly recommended to review the documentation on the official MJML website to understand the usages of each of the tags.
### Recommended development
### Recommended development - IMailService
#### Mjml email template development
@@ -58,11 +58,17 @@ Not all MJML tags have the same attributes, it is highly recommended to review t
After the email is developed from the [initial step](#mjml-email-template-development) make sure the email `{{variables}}` are populated properly by running it through an `IMailService` implementation.
1. run `npm run build:minify`
1. run `npm run build:hbs`
2. copy built `*.html.hbs` files from the build directory to a location the mail service can consume them
1. all files in the `Core/MailTemplates/Mjml/out` directory can be copied to the `src/Core/MailTemplates/Handlebars/MJML` directory. If a shared component is modified it is important to copy and overwrite all files in that directory to capture
changes in the `*.html.hbs`.
3. run code that will send the email
The minified `html.hbs` artifacts are deliverables and must be placed into the correct `src/Core/MailTemplates/Handlebars/` directories in order to be used by `IMailService` implementations.
The minified `html.hbs` artifacts are deliverables and must be placed into the correct `src/Core/MailTemplates/Handlebars/` directories in order to be used by `IMailService` implementations, see 2.1 above.
### Recommended development - IMailer
TBD - PM-26475
### Custom tags
@@ -110,3 +116,8 @@ You are also able to reference other more static MJML templates in your MJML fil
<mj-include path="../../components/learn-more-footer.mjml" />
</mj-wrapper>
```
#### `head.mjml`
Currently we include the `head.mjml` file in all MJML templates as it contains shared styling and formatting that ensures consistency across all email implementations.
In the future we may deviate from this practice to support different layouts. At that time we will modify the docs with direction.

View File

@@ -22,9 +22,3 @@
border-radius: 3px;
}
</mj-style>
<!-- Responsive icon visibility -->
<mj-style>
@media only screen and
(max-width: 480px) { .hide-small-img { display: none !important; } .send-bubble { padding-left: 20px; padding-right: 20px; width: 90% !important; } }
</mj-style>

View File

@@ -1,18 +0,0 @@
<mj-section border-radius="0px 0px 4px 4px" background-color="#f6f6f6" padding="5px 20px 10px 20px">
<mj-column width="70%">
<mj-text line-height="24px">
<h3 style="font-size: 20px; margin: 0; line-height: 28px">
Learn more about Bitwarden
</h3>
Find user guides, product documentation, and videos on the
<a href="https://bitwarden.com/help/" class="link"> Bitwarden Help Center</a>.
</mj-text>
</mj-column>
<mj-column width="30%">
<mj-image
src="https://assets.bitwarden.com/email/v1/spot-community.png"
css-class="hide-small-img"
width="94px"
/>
</mj-column>
</mj-section>

View File

@@ -18,27 +18,19 @@ class MjBwHero extends BodyComponent {
static defaultAttributes = {};
componentHeadStyle = breakpoint => {
return `
@media only screen and (max-width:${breakpoint}) {
.mj-bw-hero-responsive-img {
display: none !important;
}
}
`
}
render() {
if (this.getAttribute("button-text") && this.getAttribute("button-url")) {
return this.renderMJML(`
<mj-section
full-width="full-width"
background-color="#175ddc"
border-radius="4px 4px 0px 0px"
>
<mj-column width="70%">
<mj-image
align="left"
src="https://bitwarden.com/images/logo-horizontal-white.png"
width="150px"
height="30px"
></mj-image>
<mj-text color="#fff" padding-top="0" padding-bottom="0">
<h1 style="font-weight: normal; font-size: 24px; line-height: 32px">
${this.getAttribute("title")}
</h1>
</mj-text>
<mj-button
const buttonElement = this.getAttribute("button-text") && this.getAttribute("button-url") ?
`<mj-button
href="${this.getAttribute("button-url")}"
background-color="#fff"
color="#1A41AC"
@@ -47,22 +39,16 @@ class MjBwHero extends BodyComponent {
>
${this.getAttribute("button-text")}
</mj-button
>
</mj-column>
<mj-column width="30%" vertical-align="bottom">
<mj-image
src="${this.getAttribute("img-src")}"
alt=""
width="140px"
height="140px"
padding="0px"
css-class="hide-small-img"
/>
</mj-column>
</mj-section>
`);
} else {
return this.renderMJML(`
>` : "";
const subTitleElement = this.getAttribute("sub-title") ?
`<mj-text color="#fff" padding-top="0" padding-bottom="0">
<h2 style="font-weight: normal; font-size: 16px; line-height: 0px">
${this.getAttribute("sub-title")}
</h2>
</mj-text>` : "";
return this.renderMJML(
`
<mj-section
full-width="full-width"
background-color="#175ddc"
@@ -79,21 +65,25 @@ class MjBwHero extends BodyComponent {
<h1 style="font-weight: normal; font-size: 24px; line-height: 32px">
${this.getAttribute("title")}
</h1>
</mj-text>
` +
subTitleElement +
`
</mj-text>` +
buttonElement +
`
</mj-column>
<mj-column width="30%" vertical-align="bottom">
<mj-image
src="${this.getAttribute("img-src")}"
alt=""
width="140px"
height="140px"
width="155px"
padding="0px"
css-class="hide-small-img"
/>
css-class="mj-bw-hero-responsive-img"
/>
</mj-column>
</mj-section>
`);
}
`,
);
}
}

View File

@@ -0,0 +1,100 @@
const { BodyComponent } = require("mjml-core");
class MjBwIconRow extends BodyComponent {
static dependencies = {
"mj-column": ["mj-bw-icon-row"],
"mj-wrapper": ["mj-bw-icon-row"],
"mj-bw-icon-row": [],
};
static allowedAttributes = {
"icon-src": "string",
"icon-alt": "string",
"head-url-text": "string",
"head-url": "string",
text: "string",
"foot-url-text": "string",
"foot-url": "string",
};
static defaultAttributes = {};
componentHeadStyle = (breakpoint) => {
return `
@media only screen and (max-width:${breakpoint}): {
".mj-bw-icon-row-text": {
padding-left: "5px !important",
line-height: "20px",
},
".mj-bw-icon-row": {
padding: "10px 15px",
width: "fit-content !important",
}
}
`;
};
render() {
const headAnchorElement =
this.getAttribute("head-url-text") && this.getAttribute("head-url")
? `<a href="${this.getAttribute("head-url")}" class="link">
${this.getAttribute("head-url-text")}
<span style="text-decoration: none">
<img src="https://assets.bitwarden.com/email/v1/bwi-external-link-16px.png"
alt="External Link Icon"
width="16px"
style="vertical-align: middle;"
/>
</span>
</a>`
: "";
const footAnchorElement =
this.getAttribute("foot-url-text") && this.getAttribute("foot-url")
? `<a href="${this.getAttribute("foot-url")}" class="link">
${this.getAttribute("foot-url-text")}
<span style="text-decoration: none">
<img src="https://assets.bitwarden.com/email/v1/bwi-external-link-16px.png"
alt="External Link Icon"
width="16px"
style="vertical-align: middle;"
/>
</span>
</a>`
: "";
return this.renderMJML(
`
<mj-section background-color="#fff" padding="10px 10px 10px 10px">
<mj-group css-class="mj-bw-icon-row">
<mj-column width="15%" vertical-align="top">
<mj-image
src="${this.getAttribute("icon-src")}"
alt="${this.getAttribute("icon-alt")}"
width="48px"
padding="0px"
border-radius="8px"
/>
</mj-column>
<mj-column width="85%" vertical-align="top">
<mj-text css-class="mj-bw-icon-row-text" padding="5px 10px 0px 10px">
` +
headAnchorElement +
`
</mj-text>
<mj-text css-class="mj-bw-icon-row-text" padding="5px 10px 0px 10px">
${this.getAttribute("text")}
</mj-text>
<mj-text css-class="mj-bw-icon-row-text" padding="5px 10px 0px 10px">
` +
footAnchorElement +
`
</mj-text>
</mj-column>
</mj-group>
</mj-section>
`,
);
}
}
module.exports = MjBwIconRow;

View File

@@ -0,0 +1,51 @@
const { BodyComponent } = require("mjml-core");
class MjBwLearnMoreFooter extends BodyComponent {
static dependencies = {
// Tell the validator which tags are allowed as our component's parent
"mj-column": ["mj-bw-learn-more-footer"],
"mj-wrapper": ["mj-bw-learn-more-footer"],
// Tell the validator which tags are allowed as our component's children
"mj-bw-learn-more-footer": [],
};
static allowedAttributes = {};
static defaultAttributes = {};
componentHeadStyle = (breakpoint) => {
return `
@media only screen and (max-width:${breakpoint}) {
.mj-bw-learn-more-footer-responsive-img {
display: none !important;
}
}
`;
};
render() {
return this.renderMJML(
`
<mj-section border-radius="0px 0px 4px 4px" background-color="#f6f6f6" padding="5px 10px 10px 10px">
<mj-column width="70%">
<mj-text line-height="24px">
<p style="font-size: 18px; line-height: 28px; font-weight: bold;">
Learn more about Bitwarden
</p>
Find user guides, product documentation, and videos on the
<a href="https://bitwarden.com/help/" class="link"> Bitwarden Help Center</a>.
</mj-text>
</mj-column>
<mj-column width="30%">
<mj-image
src="https://assets.bitwarden.com/email/v1/spot-community.png"
css-class="mj-bw-learn-more-footer-responsive-img"
width="94px"
/>
</mj-column>
</mj-section>
`,
);
}
}
module.exports = MjBwLearnMoreFooter;

View File

@@ -0,0 +1,60 @@
<mjml>
<mj-head>
<mj-include path="../../../components/head.mjml" />
</mj-head>
<mj-body css-class="border-fix">
<!-- Blue Header Section -->
<mj-wrapper css-class="border-fix" padding="20px 20px 10px 20px">
<mj-bw-hero
img-src="https://assets.bitwarden.com/email/v1/account-fill.png"
title="Welcome to Bitwarden!"
sub-title="Let's get set up to autofill."
/>
</mj-wrapper>
<!-- Main Content -->
<mj-wrapper padding="5px 20px 10px 20px">
<mj-section background-color="#fff" padding="15px 10px 10px 10px">
<mj-column>
<mj-text font-size="16px" line-height="24px" padding="10px 15px">
An administrator from <b>{{OrganizationName}}</b> will approve you
before you can share passwords. While you wait for approval, get
started with Bitwarden Password Manager:
</mj-text>
</mj-column>
</mj-section>
<mj-bw-icon-row
icon-src="https://assets.bitwarden.com/email/v1/icon-browser-extension.png"
icon-alt="Browser Extension Icon"
head-url-text="Get the browser extension"
head-url="https://bitwarden.com/download/"
text="With the Bitwarden extension, you can fill passwords with one click."
/>
<mj-bw-icon-row
icon-src="https://assets.bitwarden.com/email/v1/icon-install.png"
icon-alt="Install Icon"
head-url-text="Add passwords to your vault"
head-url="https://bitwarden.com/help/import-data/"
text="Quickly transfer existing passwords to Bitwarden using the importer."
/>
<mj-bw-icon-row
icon-src="https://assets.bitwarden.com/email/v1/icon-devices.png"
icon-alt="Devices Icon"
head-url-text="Download Bitwarden on all devices"
head-url="https://bitwarden.com/download/"
text="Take your passwords with you anywhere."
/>
<mj-section background-color="#fff" padding="0 20px 20px 20px">
</mj-section>
</mj-wrapper>
<!-- Learn More Section -->
<mj-wrapper padding="5px 20px 10px 20px">
<mj-bw-learn-more-footer />
</mj-wrapper>
<!-- Footer -->
<mj-include path="../../../components/footer.mjml" />
</mj-body>
</mjml>

View File

@@ -0,0 +1,59 @@
<mjml>
<mj-head>
<mj-include path="../../../components/head.mjml" />
</mj-head>
<mj-body css-class="border-fix">
<!-- Blue Header Section -->
<mj-wrapper css-class="border-fix" padding="20px 20px 10px 20px">
<mj-bw-hero
img-src="https://assets.bitwarden.com/email/v1/account-fill.png"
title="Welcome to Bitwarden!"
sub-title="Let's get set up to autofill."
/>
</mj-wrapper>
<!-- Main Content -->
<mj-wrapper padding="5px 20px 10px 20px">
<mj-section background-color="#fff" padding="15px 10px 10px 10px">
<mj-column>
<mj-text font-size="16px" line-height="24px" padding="10px 15px">
Follow these simple steps to get up and running with Bitwarden
Password Manager:
</mj-text>
</mj-column>
</mj-section>
<mj-bw-icon-row
icon-src="https://assets.bitwarden.com/email/v1/icon-browser-extension.png"
icon-alt="Browser Extension Icon"
head-url-text="Get the browser extension"
head-url="https://bitwarden.com/download/"
text="With the Bitwarden extension, you can fill passwords with one click."
/>
<mj-bw-icon-row
icon-src="https://assets.bitwarden.com/email/v1/icon-install.png"
icon-alt="Install Icon"
head-url-text="Add passwords to your vault"
head-url="https://bitwarden.com/help/import-data/"
text="Quickly transfer existing passwords to Bitwarden using the importer."
/>
<mj-bw-icon-row
icon-src="https://assets.bitwarden.com/email/v1/icon-devices.png"
icon-alt="Devices Icon"
head-url-text="Download Bitwarden on all devices"
head-url="https://bitwarden.com/download/"
text="Take your passwords with you anywhere."
/>
<mj-section background-color="#fff" padding="0 20px 20px 20px">
</mj-section>
</mj-wrapper>
<!-- Learn More Section -->
<mj-wrapper padding="5px 20px 10px 20px">
<mj-bw-learn-more-footer />
</mj-wrapper>
<!-- Footer -->
<mj-include path="../../../components/footer.mjml" />
</mj-body>
</mjml>

View File

@@ -0,0 +1,60 @@
<mjml>
<mj-head>
<mj-include path="../../../components/head.mjml" />
</mj-head>
<mj-body css-class="border-fix">
<!-- Blue Header Section -->
<mj-wrapper css-class="border-fix" padding="20px 20px 10px 20px">
<mj-bw-hero
img-src="https://assets.bitwarden.com/email/v1/account-fill.png"
title="Welcome to Bitwarden!"
sub-title="Let's get set up to autofill."
/>
</mj-wrapper>
<!-- Main Content -->
<mj-wrapper padding="5px 20px 10px 20px">
<mj-section background-color="#fff" padding="15px 10px 10px 10px">
<mj-column>
<mj-text font-size="16px" line-height="24px" padding="10px 15px">
An administrator from <b>{{OrganizationName}}</b> will need to confirm
you before you can share passwords. Get started with Bitwarden
Password Manager:
</mj-text>
</mj-column>
</mj-section>
<mj-bw-icon-row
icon-src="https://assets.bitwarden.com/email/v1/icon-browser-extension.png"
icon-alt="Browser Extension Icon"
head-url-text="Get the browser extension"
head-url="https://bitwarden.com/download/"
text="With the Bitwarden extension, you can fill passwords with one click."
/>
<mj-bw-icon-row
icon-src="https://assets.bitwarden.com/email/v1/icon-install.png"
icon-alt="Install Icon"
head-url-text="Add passwords to your vault"
head-url="https://bitwarden.com/help/import-data/"
text="Quickly transfer existing passwords to Bitwarden using the importer."
/>
<mj-bw-icon-row
icon-src="https://assets.bitwarden.com/email/v1/icon-autofill.png"
icon-alt="Autofill Icon"
head-url-text="Try Bitwarden autofill"
head-url="https://bitwarden.com/help/auto-fill-browser/"
text="Fill your passwords securely with one click."
/>
<mj-section background-color="#fff" padding="0 20px 20px 20px">
</mj-section>
</mj-wrapper>
<!-- Learn More Section -->
<mj-wrapper padding="5px 20px 10px 20px">
<mj-bw-learn-more-footer />
</mj-wrapper>
<!-- Footer -->
<mj-include path="../../../components/footer.mjml" />
</mj-body>
</mjml>

View File

@@ -55,7 +55,7 @@
<!-- Learn More Section -->
<mj-wrapper padding="5px 20px 10px 20px">
<mj-include path="../../components/learn-more-footer.mjml" />
<mj-bw-learn-more-footer />
</mj-wrapper>
<!-- Footer -->

View File

@@ -24,6 +24,8 @@
</mj-section>
</mj-wrapper>
<mj-include path="../../components/footer.mjml" />
<mj-wrapper>
<mj-bw-learn-more-footer />
</mj-wrapper>
</mj-body>
</mjml>

View File

@@ -22,7 +22,7 @@
</mj-text>
</mj-column>
</mj-section>
<mj-include path="../components/learn-more-footer.mjml" />
<mj-bw-learn-more-footer />
</mj-wrapper>
<mj-include path="../components/footer.mjml" />