Browse Source
Scaffolds MJML and adds some initial templates and components. Of interest are: * src/Core/MailTemplates/Mjml/components/hero.js demonstrates how to create a custom MJML component. In our case it's a hero component with our logo, a title, a call to action button and an image. * src/Core/MailTemplates/Mjml/components/head.mjml defines some common styling. * src/Core/MailTemplates/Mjml/components/footer.mjml social links and footer.pull/6091/head
13 changed files with 2468 additions and 0 deletions
@ -0,0 +1,5 @@ |
|||||||
|
{ |
||||||
|
"packages": [ |
||||||
|
"components/hero" |
||||||
|
] |
||||||
|
} |
||||||
@ -0,0 +1,19 @@ |
|||||||
|
# Email templates |
||||||
|
|
||||||
|
This directory contains MJML templates for emails sent by the application. MJML is a markup language designed to reduce the pain of coding responsive email templates. |
||||||
|
|
||||||
|
## Usage |
||||||
|
|
||||||
|
```bash |
||||||
|
npm ci |
||||||
|
|
||||||
|
# Build once |
||||||
|
npm run build |
||||||
|
|
||||||
|
# To build on changes |
||||||
|
npm run watch |
||||||
|
``` |
||||||
|
|
||||||
|
## Development |
||||||
|
|
||||||
|
MJML supports components and you can create your own components by adding them to `.mjmlconfig`. |
||||||
@ -0,0 +1,4 @@ |
|||||||
|
# TODO: This should probably be replaced with a node script building every file in `emails/` |
||||||
|
|
||||||
|
npx mjml emails/invite.mjml -o out/invite.html |
||||||
|
npx mjml emails/two-factor.mjml -o out/two-factor.html |
||||||
@ -0,0 +1,53 @@ |
|||||||
|
<mj-section> |
||||||
|
<mj-column> |
||||||
|
<mj-social icon-size="30px" inner-padding="10px" padding="0"> |
||||||
|
<mj-social-element |
||||||
|
href="https://twitter.com/bitwarden" |
||||||
|
src="https://bitwarden.com/images/mail-twitter.png" |
||||||
|
></mj-social-element> |
||||||
|
|
||||||
|
<mj-social-element |
||||||
|
href="https://www.reddit.com/r/Bitwarden/" |
||||||
|
src="https://bitwarden.com/images/mail-reddit.png" |
||||||
|
></mj-social-element> |
||||||
|
|
||||||
|
<mj-social-element |
||||||
|
href="https://community.bitwarden.com/" |
||||||
|
src="https://bitwarden.com/images/mail-discourse.png" |
||||||
|
></mj-social-element> |
||||||
|
|
||||||
|
<mj-social-element |
||||||
|
href="https://github.com/bitwarden" |
||||||
|
src="https://bitwarden.com/images/mail-github.png" |
||||||
|
></mj-social-element> |
||||||
|
|
||||||
|
<mj-social-element |
||||||
|
href="https://www.youtube.com/channel/UCId9a_jQqvJre0_dE2lE_Rw" |
||||||
|
src="https://bitwarden.com/images/mail-youtube.png" |
||||||
|
></mj-social-element> |
||||||
|
|
||||||
|
<mj-social-element |
||||||
|
href="https://www.linkedin.com/company/bitwarden1/" |
||||||
|
src="https://bitwarden.com/images/mail-linkedin.png" |
||||||
|
></mj-social-element> |
||||||
|
|
||||||
|
<mj-social-element |
||||||
|
href="https://www.facebook.com/bitwarden/" |
||||||
|
src="https://bitwarden.com/images/mail-facebook.png" |
||||||
|
></mj-social-element> |
||||||
|
</mj-social> |
||||||
|
|
||||||
|
<mj-text align="center" font-size="12px" line-height="16px" color="#5A6D91"> |
||||||
|
<p style="margin-bottom: 5px"> |
||||||
|
© 2025 Bitwarden Inc. 1 N. Calle Cesar Chavez, Suite 102, Santa |
||||||
|
Barbara, CA, USA |
||||||
|
</p> |
||||||
|
<p style="margin-top: 5px"> |
||||||
|
Always confirm you are on a trusted Bitwarden domain before logging |
||||||
|
in:<br /> |
||||||
|
<a href="#">bitwarden.com</a> | |
||||||
|
<a href="#">Learn why we include this</a> |
||||||
|
</p> |
||||||
|
</mj-text> |
||||||
|
</mj-column> |
||||||
|
</mj-section> |
||||||
@ -0,0 +1,16 @@ |
|||||||
|
<mj-attributes> |
||||||
|
<mj-all |
||||||
|
font-family="'Helvetica Neue', Helvetica, Arial, sans-serif" |
||||||
|
font-size="16px" |
||||||
|
/> |
||||||
|
<mj-button background-color="#175ddc" /> |
||||||
|
<mj-text color="#333" /> |
||||||
|
<mj-body background-color="#e6e9ef" width="660px" /> |
||||||
|
</mj-attributes> |
||||||
|
<mj-style inline="inline"> |
||||||
|
.link { text-decoration: none; color: #175ddc; font-weight: 600 } |
||||||
|
</mj-style> |
||||||
|
<mj-style> |
||||||
|
.border-fix > table { border-collapse:separate !important; } .border-fix > |
||||||
|
table > tbody > tr > td { border-radius: 3px; } |
||||||
|
</mj-style> |
||||||
@ -0,0 +1,64 @@ |
|||||||
|
const { BodyComponent } = require("mjml-core"); |
||||||
|
class MjBwHero extends BodyComponent { |
||||||
|
static dependencies = { |
||||||
|
// Tell the validator which tags are allowed as our component's parent
|
||||||
|
"mj-column": ["mj-bw-hero"], |
||||||
|
"mj-wrapper": ["mj-bw-hero"], |
||||||
|
// Tell the validator which tags are allowed as our component's children
|
||||||
|
"mj-bw-hero": [], |
||||||
|
}; |
||||||
|
|
||||||
|
static allowedAttributes = { |
||||||
|
"img-src": "string", |
||||||
|
title: "string", |
||||||
|
"button-text": "string", |
||||||
|
"button-url": "string", |
||||||
|
}; |
||||||
|
|
||||||
|
static defaultAttributes = {}; |
||||||
|
|
||||||
|
render() { |
||||||
|
return this.renderMJML(` |
||||||
|
<mj-section |
||||||
|
full-width="full-width" |
||||||
|
background-color="#175ddc" |
||||||
|
border-radius="4px 4px 0 0" |
||||||
|
> |
||||||
|
<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 |
||||||
|
href="${this.getAttribute("button-url")}" |
||||||
|
background-color="#fff" |
||||||
|
color="#1A41AC" |
||||||
|
border-radius="20px" |
||||||
|
align="left" |
||||||
|
> |
||||||
|
${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="0" |
||||||
|
/> |
||||||
|
</mj-column> |
||||||
|
</mj-section> |
||||||
|
`);
|
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
module.exports = MjBwHero; |
||||||
@ -0,0 +1,11 @@ |
|||||||
|
<mj-section> |
||||||
|
<mj-column> |
||||||
|
<mj-image |
||||||
|
align="center" |
||||||
|
padding="10px 25px" |
||||||
|
src="https://bitwarden.com/images/logo-horizontal-blue.png" |
||||||
|
width="250px" |
||||||
|
height="39px" |
||||||
|
></mj-image> |
||||||
|
</mj-column> |
||||||
|
</mj-section> |
||||||
@ -0,0 +1,49 @@ |
|||||||
|
<mjml> |
||||||
|
<mj-head> |
||||||
|
<mj-include path="../components/head.mjml" /> |
||||||
|
</mj-head> |
||||||
|
|
||||||
|
<mj-body> |
||||||
|
<mj-wrapper css-class="border-fix" padding="20px 20px"> |
||||||
|
<mj-bw-hero |
||||||
|
img-src="https://assets.bitwarden.com/email/v1/business.png" |
||||||
|
title="A Bitwarden member has invited you to Bitwarden Password Manager" |
||||||
|
button-text="Finish account setup" |
||||||
|
button-url="#" |
||||||
|
/> |
||||||
|
|
||||||
|
<mj-section> |
||||||
|
<mj-column> |
||||||
|
<mj-button href="#">Join Organization Now</mj-button> |
||||||
|
|
||||||
|
<mj-text> |
||||||
|
This invitation expires on |
||||||
|
<b>Tuesday, January 23, 2024 2:59PM UTC</b>. |
||||||
|
</mj-text> |
||||||
|
</mj-column> |
||||||
|
</mj-section> |
||||||
|
<mj-section background-color="#fbfbfb"> |
||||||
|
<mj-column width="70%"> |
||||||
|
<mj-text line-height="24px"> |
||||||
|
<h3 style="font-size: 20px; margin: 0; line-height: 28px"> |
||||||
|
We’re here for you! |
||||||
|
</h3> |
||||||
|
If you have any questions, search the Bitwarden |
||||||
|
<a href="#" class="link">Help</a> |
||||||
|
site or |
||||||
|
<a href="#" class="link">contact us</a>. |
||||||
|
</mj-text> |
||||||
|
</mj-column> |
||||||
|
<mj-column width="30%"> |
||||||
|
<mj-image |
||||||
|
src="https://assets.bitwarden.com/email/v1/chat.png" |
||||||
|
height="77px" |
||||||
|
width="94px" |
||||||
|
/> |
||||||
|
</mj-column> |
||||||
|
</mj-section> |
||||||
|
</mj-wrapper> |
||||||
|
|
||||||
|
<mj-include path="../components/footer.mjml" /> |
||||||
|
</mj-body> |
||||||
|
</mjml> |
||||||
@ -0,0 +1,27 @@ |
|||||||
|
<mjml> |
||||||
|
<mj-head> |
||||||
|
<mj-include path="../components/head.mjml" /> |
||||||
|
</mj-head> |
||||||
|
|
||||||
|
<mj-body background-color="#f6f6f6"> |
||||||
|
<mj-include path="../components/logo.mjml" /> |
||||||
|
|
||||||
|
<mj-wrapper |
||||||
|
background-color="#fff" |
||||||
|
border="1px solid #e9e9e9" |
||||||
|
css-class="border-fix" |
||||||
|
padding="0" |
||||||
|
> |
||||||
|
<mj-section> |
||||||
|
<mj-column> |
||||||
|
<mj-text> |
||||||
|
<p>Your two-step verification code is: <b>{{Token}}</b></p> |
||||||
|
<p>Use this code to complete logging in with Bitwarden.</p> |
||||||
|
</mj-text> |
||||||
|
</mj-column> |
||||||
|
</mj-section> |
||||||
|
</mj-wrapper> |
||||||
|
|
||||||
|
<mj-include path="../components/footer.mjml" /> |
||||||
|
</mj-body> |
||||||
|
</mjml> |
||||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,30 @@ |
|||||||
|
{ |
||||||
|
"name": "@bitwarden/mjml-emails", |
||||||
|
"version": "1.0.0", |
||||||
|
"description": "Email templates for Bitwarden", |
||||||
|
"private": true, |
||||||
|
"type": "commonjs", |
||||||
|
"repository": { |
||||||
|
"type": "git", |
||||||
|
"url": "git+https://github.com/bitwarden/server.git" |
||||||
|
}, |
||||||
|
"author": "Bitwarden Inc. <hello@bitwarden.com> (https://bitwarden.com)", |
||||||
|
"license": "SEE LICENSE IN LICENSE.txt", |
||||||
|
"bugs": { |
||||||
|
"url": "https://github.com/bitwarden/server/issues" |
||||||
|
}, |
||||||
|
"homepage": "https://bitwarden.com", |
||||||
|
"scripts": { |
||||||
|
"build": "./build.sh", |
||||||
|
"watch": "nodemon --exec ./build.sh --watch ./components --watch ./emails --ext js,mjml", |
||||||
|
"prettier": "prettier --cache --write ." |
||||||
|
}, |
||||||
|
"dependencies": { |
||||||
|
"mjml": "4.15.3", |
||||||
|
"mjml-core": "4.15.3" |
||||||
|
}, |
||||||
|
"devDependencies": { |
||||||
|
"nodemon": "3.1.10", |
||||||
|
"prettier": "3.5.3" |
||||||
|
} |
||||||
|
} |
||||||
Loading…
Reference in new issue