mirror of
https://github.com/bitwarden/server.git
synced 2024-11-21 12:05:42 +01:00
[PM-1095][PM-1104] Update email template (#2746)
* [SG-994] Add import Open Sans font to full template * [SG-994] Update organization user invite email template to new UI * [SG-994] update alt text for mobile app download buttons * [SG-994] Update copy. Add hyperlinks to stores. * [SG-944] Improve layout responsiveness * [PM-1095][PM-1104] Add new template for title and contact us. Add new template for user organization invite * [PM-1095][PM-1104] Remove wrong text from free invite * [PM-1104][PM-1095] Add bold class. Add margin. * [PM-1104][PM-1095] Change font type to previously used * [PM-1104][PM-1095] Remove Open Sans font * [PM-1104][PM-1095] Improve browsers rendering compatibility * [PM-1104][PM-1095] Fixed margins * [PM-1095][PM-1104] Remove unnecessary string sanitise.
This commit is contained in:
parent
3d0ca908ff
commit
2e3e96a25c
@ -5,7 +5,6 @@
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||
<title>Bitwarden</title>
|
||||
</head>
|
||||
|
||||
<body style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; height: 100%; line-height: 25px; width: 100% !important; margin: 0;" bgcolor="#f6f6f6">
|
||||
<style type="text/css">
|
||||
body {
|
||||
@ -47,7 +46,18 @@
|
||||
background-color: #f6f6f6;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 600px) {
|
||||
.white-title {
|
||||
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
box-sizing: border-box;
|
||||
font-size: 24px;
|
||||
line-height: 32px;
|
||||
font-weight: 700;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-webkit-text-size-adjust: none;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 350px) {
|
||||
body {
|
||||
padding: 0 !important;
|
||||
}
|
||||
@ -91,17 +101,60 @@
|
||||
.indented {
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
.title-header-text {
|
||||
width: 100%;
|
||||
display: block;
|
||||
padding-top: 75px;
|
||||
padding-bottom: 0px;
|
||||
padding-left: 35px;
|
||||
padding-right: 20px;
|
||||
}
|
||||
|
||||
.title-header-image {
|
||||
width: 100%;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.footer-image {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.footer-text {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (min-width: 600px) {
|
||||
@media only screen and (min-width: 350px) {
|
||||
.title-header-text {
|
||||
width: 65%;
|
||||
display: inline-block;
|
||||
padding-top: 75px;
|
||||
padding-bottom: 75px;
|
||||
padding-left: 35px;
|
||||
padding-right: 20px;
|
||||
}
|
||||
|
||||
.title-header-image {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
{{! Fix for Apple Mail }}
|
||||
.content-table {
|
||||
width: 600px !important;
|
||||
}
|
||||
|
||||
.footer-image {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.footer-text {
|
||||
width: 65%;
|
||||
}
|
||||
}
|
||||
|
||||
/* Component styling - these are explicitly applied via classes so that they can be
|
||||
gradually introduced as we update templates.*/
|
||||
gradually introduced as we update templates.*/
|
||||
a.inline-link {
|
||||
font-weight: bold;
|
||||
color: #175DDC;
|
||||
@ -119,54 +172,58 @@
|
||||
|
||||
</style>
|
||||
{{! Yahoo center fix }}
|
||||
<table width="100%" cellpadding="0" cellspacing="0" bgcolor="#f6f6f6"><tr><td class="container" width="100%" align="center">
|
||||
{{! 600px container }}
|
||||
<table cellpadding="0" cellspacing="0" width="100%" class="content-table">
|
||||
<tr>
|
||||
<td></td> {{! Left column (center fix) }}
|
||||
<td class="content" align="center" valign="top" width="600" style="padding-bottom: 20px;">
|
||||
<table class="header" cellpadding="0" cellspacing="0" width="100%">
|
||||
<tr>
|
||||
<td valign="middle" class="aligncenter middle logo" style="padding: 20px 0 10px;" align="center">
|
||||
<img src="https://bitwarden.com/images/logo-horizontal-blue.png" alt="" width="250" height="39" />
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table class="main" cellpadding="0" cellspacing="0" style="border: 1px solid #e9e9e9; border-radius: 3px;" bgcolor="white">
|
||||
<tr>
|
||||
<td class="content-wrap" style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; color: #333; line-height: 25px; margin: 0; -webkit-font-smoothing: antialiased; padding: 20px; -webkit-text-size-adjust: none;" valign="top">
|
||||
<table width="100%" cellpadding="0" cellspacing="0" bgcolor="#f6f6f6">
|
||||
<tr>
|
||||
<td class="container" width="100%" align="center">
|
||||
{{! 600px container }}
|
||||
<table cellpadding="0" cellspacing="0" width="100%" class="content-table">
|
||||
<tr>
|
||||
<td></td> {{! Left column (center fix) }}
|
||||
<td class="content" align="center" valign="top" width="600" style="padding-bottom: 20px;">
|
||||
<table class="header" cellpadding="0" cellspacing="0" width="100%">
|
||||
<tr>
|
||||
<td valign="middle" class="aligncenter middle logo" style="padding: 20px 0 10px;" align="center">
|
||||
<img src="https://bitwarden.com/images/logo-horizontal-blue.png" alt="" width="250" height="39" />
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table class="main" cellpadding="0" cellspacing="0" style="border: 1px solid #e9e9e9; border-radius: 3px;" bgcolor="white">
|
||||
<tr>
|
||||
<td class="content-wrap" style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; color: #333; line-height: 25px; margin: 0; -webkit-font-smoothing: antialiased; padding: 20px; -webkit-text-size-adjust: none;" valign="top">
|
||||
|
||||
{{>@partial-block}}
|
||||
{{>@partial-block}}
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table class="footer" cellpadding="0" cellspacing="0" width="100%" style="margin: 0; width: 100%;">
|
||||
<tr>
|
||||
<td class="aligncenter social-icons" align="center" style="margin: 0; padding: 15px 0 0 0;" valign="top">
|
||||
<table cellpadding="0" cellspacing="0" style="margin: 0 auto;">
|
||||
<tr>
|
||||
<td style="margin: 0; padding: 0 10px;" valign="top"><a href="https://twitter.com/bitwarden" target="_blank"><img src="https://bitwarden.com/images/mail-twitter.png" alt="Twitter" width="30" height="30" /></a></td>
|
||||
<td style="margin: 0; padding: 0 10px;" valign="top"><a href="https://www.reddit.com/r/Bitwarden/" target="_blank"><img src="https://bitwarden.com/images/mail-reddit.png" alt="Reddit" width="30" height="30" /></a></td>
|
||||
<td style="margin: 0; padding: 0 10px;" valign="top"><a href="https://community.bitwarden.com/" target="_blank"><img src="https://bitwarden.com/images/mail-discourse.png" alt="CommunityForums" width="30" height="30" /></a></td>
|
||||
<td style="margin: 0; padding: 0 10px;" valign="top"><a href="https://github.com/bitwarden" target="_blank"><img src="https://bitwarden.com/images/mail-github.png" alt="GitHub" width="30" height="30" /></a></td>
|
||||
<td style="margin: 0; padding: 0 10px;" valign="top"><a href="https://www.youtube.com/channel/UCId9a_jQqvJre0_dE2lE_Rw" target="_blank"><img src="https://bitwarden.com/images/mail-youtube.png" alt="Youtube" width="30" height="30" /></a></td>
|
||||
<td style="margin: 0; padding: 0 10px;" valign="top"><a href="https://www.linkedin.com/company/bitwarden1/" target="_blank"><img src="https://bitwarden.com/images/mail-linkedin.png" alt="LinkedIn" width="30" height="30" /></a></td>
|
||||
<td style="margin: 0; padding: 0 10px;" valign="top"><a href="https://www.facebook.com/bitwarden/" target="_blank"><img src="https://bitwarden.com/images/mail-facebook.png" alt="Facebook" width="30" height="30" /></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="content-block" style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; color: #666666; line-height: 25px; margin: 0; -webkit-font-smoothing: antialiased; padding: 15px 0 0 0; -webkit-text-size-adjust: none; text-align: center;" valign="top">
|
||||
© {{CurrentYear}} Bitwarden Inc.
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
<td></td> {{! Right column (center fix) }}
|
||||
</tr>
|
||||
</table>
|
||||
</td></tr></table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table class="footer" cellpadding="0" cellspacing="0" width="100%" style="margin: 0; width: 100%;">
|
||||
<tr>
|
||||
<td class="aligncenter social-icons" align="center" style="margin: 0; padding: 15px 0 0 0;" valign="top">
|
||||
<table cellpadding="0" cellspacing="0" style="margin: 0 auto;">
|
||||
<tr>
|
||||
<td style="margin: 0; padding: 0 10px;" valign="top"><a href="https://twitter.com/bitwarden" target="_blank"><img src="https://bitwarden.com/images/mail-twitter.png" alt="Twitter" width="30" height="30" /></a></td>
|
||||
<td style="margin: 0; padding: 0 10px;" valign="top"><a href="https://www.reddit.com/r/Bitwarden/" target="_blank"><img src="https://bitwarden.com/images/mail-reddit.png" alt="Reddit" width="30" height="30" /></a></td>
|
||||
<td style="margin: 0; padding: 0 10px;" valign="top"><a href="https://community.bitwarden.com/" target="_blank"><img src="https://bitwarden.com/images/mail-discourse.png" alt="CommunityForums" width="30" height="30" /></a></td>
|
||||
<td style="margin: 0; padding: 0 10px;" valign="top"><a href="https://github.com/bitwarden" target="_blank"><img src="https://bitwarden.com/images/mail-github.png" alt="GitHub" width="30" height="30" /></a></td>
|
||||
<td style="margin: 0; padding: 0 10px;" valign="top"><a href="https://www.youtube.com/channel/UCId9a_jQqvJre0_dE2lE_Rw" target="_blank"><img src="https://bitwarden.com/images/mail-youtube.png" alt="Youtube" width="30" height="30" /></a></td>
|
||||
<td style="margin: 0; padding: 0 10px;" valign="top"><a href="https://www.linkedin.com/company/bitwarden1/" target="_blank"><img src="https://bitwarden.com/images/mail-linkedin.png" alt="LinkedIn" width="30" height="30" /></a></td>
|
||||
<td style="margin: 0; padding: 0 10px;" valign="top"><a href="https://www.facebook.com/bitwarden/" target="_blank"><img src="https://bitwarden.com/images/mail-facebook.png" alt="Facebook" width="30" height="30" /></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="content-block" style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; color: #666666; line-height: 25px; margin: 0; -webkit-font-smoothing: antialiased; padding: 15px 0 0 0; -webkit-text-size-adjust: none; text-align: center;" valign="top">
|
||||
© {{CurrentYear}} Bitwarden Inc.
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
<td></td> {{! Right column (center fix) }}
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -0,0 +1,26 @@
|
||||
{{#>FullHtmlLayout}}
|
||||
<div width="auto" cellpadding="0" cellspacing="0" style="padding:0; margin:-20px">
|
||||
<div style="display: block; min-height: 204px; background-color: #175DDC; margin: 0;">
|
||||
<div class="title-header-text" >
|
||||
<div style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 24px; color: #ffffff; line-height: 32px; font-weight: 400; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none;">
|
||||
{{TitleFirst}}<b class="white-title">{{TitleSecondBold}}</b>{{TitleThird}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="title-header-image" style="margin-left: auto; margin-right: 0px; vertical-align: bottom;">
|
||||
<img style="margin-left: auto; margin-right: 0px; display: block;" alt='' src='https://assets.bitwarden.com/email/v1/business.png' />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{>@partial-block}}
|
||||
|
||||
<div style="display:block;background-color: #FBFBFB;">
|
||||
<div class="footer-text" style="display: inline-block; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-style: normal; font-weight: 400; font-size: 16px; line-height: 24px; padding-left: 35px; padding-right: 35px; margin-top: 15px; margin-bottom: 20px; margin-left: auto; margin-right: auto; vertical-align: middle; ">
|
||||
<p style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-style: normal; font-weight: 600; font-size: 20px; line-height: 28px;">We’re here for you!</p>
|
||||
If you have any questions, search the Bitwarden <a style="text-decoration: none; color: #175DDC; font-weight: 600;" href="https://bitwarden.com/help/">Help</a> site or <a style="text-decoration: none; color: #175DDC; font-weight: 600;" href="https://bitwarden.com/contact/">contact us</a>.
|
||||
</div>
|
||||
<div style="display: inline-block; width:33%; margin-left: auto; margin-right: auto; vertical-align: middle; ">
|
||||
<img class="footer-image" src="https://assets.bitwarden.com/email/v1/chat.png" style="width: 94.73px; height: 77.25px; margin-left: auto; margin-right: 30px;" alt="" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{/FullHtmlLayout}}
|
@ -0,0 +1,11 @@
|
||||
{{#>FullTextLayout}}
|
||||
{{TitleFirst}} {{TitleSecondBold}} {{TitleThird}}
|
||||
|
||||
{{>@partial-block}}
|
||||
|
||||
|
||||
We’re here for you!
|
||||
If you have any questions, search the Bitwarden Help site or contact us.
|
||||
- https://bitwarden.com/help/
|
||||
- https://bitwarden.com/contact/
|
||||
{{/FullTextLayout}}
|
@ -1,14 +1,25 @@
|
||||
{{#>FullHtmlLayout}}
|
||||
<table width="100%" cellpadding="0" cellspacing="0" style="margin: 0; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; color: #333; line-height: 25px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none;">
|
||||
<tr style="margin: 0; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; color: #333; line-height: 25px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none;">
|
||||
<td class="content-block" style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; color: #333; line-height: 25px; margin: 0; -webkit-font-smoothing: antialiased; padding: 0 0 10px; -webkit-text-size-adjust: none;" valign="top">
|
||||
This email is to notify you that you have been confirmed as a user of <b style="margin: 0; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; color: #333; line-height: 25px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none;">{{OrganizationName}}</b>.
|
||||
</td>
|
||||
</tr>
|
||||
<tr style="margin: 0; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; color: #333; line-height: 25px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none;">
|
||||
<td class="content-block last" style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; color: #333; line-height: 25px; margin: 0; -webkit-font-smoothing: antialiased; padding: 0; -webkit-text-size-adjust: none;" valign="top">
|
||||
Any collections and logins being shared with you by this organization will now appear in your Bitwarden vault.
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
{{/FullHtmlLayout}}
|
||||
{{#>TitleContactUsHtmlLayout}}
|
||||
<div>
|
||||
<div style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-style: normal; font-weight: 400; font-size: 16px; line-height: 24px; margin-top: 30px; margin-bottom: 30px; margin-left: 35px; margin-right: 35px;">
|
||||
You may now access logins and other items this organizations has shared with you from your Bitwarden vault.
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div style="display: block;" align="center">
|
||||
<a href="https://vault.bitwarden.com/" clicktracking=off target="_blank" style="color: #ffffff; text-decoration: none; text-align: center; cursor: pointer; border-radius: 5px; background-color: #175DDC; border-color: #175DDC; border-style: solid; border-width: 10px 20px; margin: 0; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; line-height: 25px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none;">
|
||||
Go to vault
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-style: normal; font-weight: 400; font-size: 16px; line-height: 24px; margin-top: 30px; margin-bottom: 15px; margin-left: 35px; margin-right: 35px;">
|
||||
<b>Tip: </b>Use the Bitwarden mobile app to quickly save logins and auto-fill forms. Download from the <a style="text-decoration: none; color: #175DDC; font-weight: 600;" href="https://apps.apple.com/us/app/bitwarden-password-manager/id1137397744">App Store</a> or <a style="text-decoration: none; color: #175DDC; font-weight: 600;" href="https://play.google.com/store/apps/details?id=com.x8bit.bitwarden">Google Play</a>.
|
||||
</div>
|
||||
</div>
|
||||
<div style="margin-bottom: 15px;">
|
||||
<div style="display: block; box-sizing: border-box; clear: both; text-align: center;">
|
||||
<a href='https://play.google.com/store/apps/details?id=com.x8bit.bitwarden' target="_blank" style="display: inline-block; vertical-align: top; margin-left: 10px; margin-right: 10px; height: 60px; width: 150px; "><img style="height: 60px; width: 150px; display: inline-block;" alt='Android download' src='https://assets.bitwarden.com/email/v1/google-play-badge.png' /></a>
|
||||
<a href="https://apps.apple.com/us/app/bitwarden-password-manager/id1137397744" target="_blank" style="display: inline-block; height: 40px; width: 135px; margin-top:10px"><img style="height: 40px; width: 135px; display: inline-block;" alt="iOS download" src="https://assets.bitwarden.com/email/v1/App-store.png" /></a>
|
||||
</div>
|
||||
</div>
|
||||
{{/TitleContactUsHtmlLayout}}
|
||||
|
@ -1,5 +1,5 @@
|
||||
{{#>BasicTextLayout}}
|
||||
This email is to notify you that you have been confirmed as a user of {{OrganizationName}}.
|
||||
{{#>TitleContactUsTextLayout}}
|
||||
You may now access logins and other items this organizations has shared with you from your Bitwarden vault.
|
||||
|
||||
Any collections and logins being shared with you by this organization will now appear in your Bitwarden vault.
|
||||
{{/BasicTextLayout}}
|
||||
Tip: Use the Bitwarden mobile app to quickly save logins and auto-fill forms. Download from the App Store or Google Play.
|
||||
{{/TitleContactUsTextLayout}}
|
@ -1,24 +1,15 @@
|
||||
{{#>FullHtmlLayout}}
|
||||
<table width="100%" cellpadding="0" cellspacing="0" style="margin: 0; box-sizing: border-box; color: #333; line-height: 25px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none;">
|
||||
<tr style="margin: 0; box-sizing: border-box; color: #333; line-height: 25px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none;">
|
||||
<td class="content-block" style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; color: #333; line-height: 25px; margin: 0; -webkit-font-smoothing: antialiased; padding: 0 0 10px; -webkit-text-size-adjust: none; text-align: left;" valign="top" align="center">
|
||||
You have been invited to join the <b style="margin: 0; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; color: #333; line-height: 25px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none;">{{OrganizationName}}</b> organization. This link expires on <b>{{ExpirationDate}}.</b>
|
||||
</td>
|
||||
</tr>
|
||||
<tr style="margin: 0; box-sizing: border-box; color: #333; line-height: 25px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none;">
|
||||
<td class="content-block last" style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; color: #333; line-height: 25px; margin: 0; -webkit-font-smoothing: antialiased; padding: 0; -webkit-text-size-adjust: none; text-align: left;" valign="top" align="center">
|
||||
If you do not wish to join this organization, you can safely ignore this email.
|
||||
<br style="margin: 0; box-sizing: border-box; color: #333; line-height: 25px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none;" />
|
||||
<br style="margin: 0; box-sizing: border-box; color: #333; line-height: 25px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none;" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr style="margin: 0; box-sizing: border-box; color: #333; line-height: 25px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none;">
|
||||
<td class="content-block" style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; color: #333; line-height: 25px; margin: 0; -webkit-font-smoothing: antialiased; padding: 0 0 10px; -webkit-text-size-adjust: none; text-align: center;" valign="top" align="center">
|
||||
<a href="{{{Url}}}" clicktracking=off target="_blank" style="color: #ffffff; text-decoration: none; text-align: center; cursor: pointer; display: inline-block; border-radius: 5px; background-color: #175DDC; border-color: #175DDC; border-style: solid; border-width: 10px 20px; margin: 0; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; line-height: 25px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none;">
|
||||
Join Organization Now
|
||||
</a>
|
||||
<br style="margin: 0; box-sizing: border-box; color: #333; line-height: 25px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none;" />
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
{{/FullHtmlLayout}}
|
||||
{{#>TitleContactUsHtmlLayout}}
|
||||
<div>
|
||||
<div style="display: block; margin-top: 35px;" align="center">
|
||||
<a href="{{{Url}}}" clicktracking=off target="_blank" style="color: #ffffff; text-decoration: none; text-align: center; cursor: pointer; border-radius: 5px; background-color: #175DDC; border-color: #175DDC; border-style: solid; border-width: 10px 20px; margin: 0; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; line-height: 25px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none;">
|
||||
Join Organization Now
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div style="font-family:'Helvetica Neue', Helvetica, Arial, sans-serif; font-style: normal; font-weight: 400; font-size: 16px; line-height: 24px; margin-top: 30px; margin-bottom: 25px; margin-left: 35px; margin-right: 35px;">
|
||||
This invitation expires on <b>{{ExpirationDate}}</b>
|
||||
</div>
|
||||
</div>
|
||||
{{/TitleContactUsHtmlLayout}}
|
||||
|
||||
|
@ -1,10 +1,5 @@
|
||||
{{#>BasicTextLayout}}
|
||||
You have been invited to join the {{OrganizationName}} organization.
|
||||
|
||||
This link expires on {{ExpirationDate}}.
|
||||
|
||||
If you do not wish to join this organization, you can safely ignore this email.
|
||||
|
||||
{{#>TitleContactUsTextLayout}}
|
||||
{{{Url}}}
|
||||
|
||||
{{/BasicTextLayout}}
|
||||
This invitation expires on {{ExpirationDate}}.
|
||||
{{/TitleContactUsTextLayout}}
|
||||
|
9
src/Core/Models/Mail/BaseTitleContactUsMailModel.cs
Normal file
9
src/Core/Models/Mail/BaseTitleContactUsMailModel.cs
Normal file
@ -0,0 +1,9 @@
|
||||
namespace Bit.Core.Models.Mail;
|
||||
|
||||
public class BaseTitleContactUsMailModel : BaseMailModel
|
||||
{
|
||||
public string TitleFirst { get; set; }
|
||||
public string TitleSecondBold { get; set; }
|
||||
public string TitleThird { get; set; }
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
namespace Bit.Core.Models.Mail;
|
||||
|
||||
public class OrganizationUserConfirmedViewModel : BaseMailModel
|
||||
public class OrganizationUserConfirmedViewModel : BaseTitleContactUsMailModel
|
||||
{
|
||||
public string OrganizationName { get; set; }
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
namespace Bit.Core.Models.Mail;
|
||||
|
||||
public class OrganizationUserInvitedViewModel : BaseMailModel
|
||||
public class OrganizationUserInvitedViewModel : BaseTitleContactUsMailModel
|
||||
{
|
||||
public string OrganizationName { get; set; }
|
||||
public string OrganizationId { get; set; }
|
||||
|
@ -15,8 +15,8 @@ public interface IMailService
|
||||
Task SendTwoFactorEmailAsync(string email, string token);
|
||||
Task SendNoMasterPasswordHintEmailAsync(string email);
|
||||
Task SendMasterPasswordHintEmailAsync(string email, string hint);
|
||||
Task SendOrganizationInviteEmailAsync(string organizationName, OrganizationUser orgUser, ExpiringToken token);
|
||||
Task BulkSendOrganizationInviteEmailAsync(string organizationName, IEnumerable<(OrganizationUser orgUser, ExpiringToken token)> invites);
|
||||
Task SendOrganizationInviteEmailAsync(string organizationName, OrganizationUser orgUser, ExpiringToken token, bool isFreeOrg);
|
||||
Task BulkSendOrganizationInviteEmailAsync(string organizationName, IEnumerable<(OrganizationUser orgUser, ExpiringToken token)> invites, bool isFreeOrg);
|
||||
Task SendOrganizationMaxSeatLimitReachedEmailAsync(Organization organization, int maxSeatCount, IEnumerable<string> ownerEmails);
|
||||
Task SendOrganizationAutoscaledEmailAsync(Organization organization, int initialSeatCount, IEnumerable<string> ownerEmails);
|
||||
Task SendOrganizationAcceptedEmailAsync(Organization organization, string userIdentifier, IEnumerable<string> adminEmails);
|
||||
|
@ -191,6 +191,9 @@ public class HandlebarsMailService : IMailService
|
||||
var message = CreateDefaultMessage($"You Have Been Confirmed To {organizationName}", email);
|
||||
var model = new OrganizationUserConfirmedViewModel
|
||||
{
|
||||
TitleFirst = "You're confirmed as a member of ",
|
||||
TitleSecondBold = CoreHelpers.SanitizeForEmail(organizationName, false),
|
||||
TitleThird = "!",
|
||||
OrganizationName = CoreHelpers.SanitizeForEmail(organizationName, false),
|
||||
WebVaultUrl = _globalSettings.BaseServiceUri.VaultWithHash,
|
||||
SiteName = _globalSettings.SiteName
|
||||
@ -200,21 +203,24 @@ public class HandlebarsMailService : IMailService
|
||||
await _mailDeliveryService.SendEmailAsync(message);
|
||||
}
|
||||
|
||||
public Task SendOrganizationInviteEmailAsync(string organizationName, OrganizationUser orgUser, ExpiringToken token) =>
|
||||
BulkSendOrganizationInviteEmailAsync(organizationName, new[] { (orgUser, token) });
|
||||
public Task SendOrganizationInviteEmailAsync(string organizationName, OrganizationUser orgUser, ExpiringToken token, bool isFreeOrg) =>
|
||||
BulkSendOrganizationInviteEmailAsync(organizationName, new[] { (orgUser, token) }, isFreeOrg);
|
||||
|
||||
public async Task BulkSendOrganizationInviteEmailAsync(string organizationName, IEnumerable<(OrganizationUser orgUser, ExpiringToken token)> invites)
|
||||
public async Task BulkSendOrganizationInviteEmailAsync(string organizationName, IEnumerable<(OrganizationUser orgUser, ExpiringToken token)> invites, bool isFreeOrg)
|
||||
{
|
||||
MailQueueMessage CreateMessage(string email, object model)
|
||||
{
|
||||
var message = CreateDefaultMessage($"Join {organizationName}", email);
|
||||
return new MailQueueMessage(message, "OrganizationUserInvited", model);
|
||||
}
|
||||
|
||||
var freeOrgTitle = "A Bitwarden member invited you to an organization. Join now to start securing your passwords!";
|
||||
var messageModels = invites.Select(invite => CreateMessage(invite.orgUser.Email,
|
||||
new OrganizationUserInvitedViewModel
|
||||
{
|
||||
OrganizationName = CoreHelpers.SanitizeForEmail(organizationName, false),
|
||||
TitleFirst = isFreeOrg ? freeOrgTitle : "Join ",
|
||||
TitleSecondBold = isFreeOrg ? string.Empty : CoreHelpers.SanitizeForEmail(organizationName, false),
|
||||
TitleThird = isFreeOrg ? string.Empty : " on Bitwarden and start securing your passwords!",
|
||||
OrganizationName = CoreHelpers.SanitizeForEmail(organizationName, false) + invite.orgUser.Status,
|
||||
Email = WebUtility.UrlEncode(invite.orgUser.Email),
|
||||
OrganizationId = invite.orgUser.OrganizationId.ToString(),
|
||||
OrganizationUserId = invite.orgUser.Id.ToString(),
|
||||
@ -478,6 +484,10 @@ public class HandlebarsMailService : IMailService
|
||||
Handlebars.RegisterTemplate("FullHtmlLayout", fullHtmlLayoutSource);
|
||||
var fullTextLayoutSource = await ReadSourceAsync("Layouts.Full.text");
|
||||
Handlebars.RegisterTemplate("FullTextLayout", fullTextLayoutSource);
|
||||
var titleContactUsHtmlLayoutSource = await ReadSourceAsync("Layouts.TitleContactUs.html");
|
||||
Handlebars.RegisterTemplate("TitleContactUsHtmlLayout", titleContactUsHtmlLayoutSource);
|
||||
var titleContactUsTextLayoutSource = await ReadSourceAsync("Layouts.TitleContactUs.text");
|
||||
Handlebars.RegisterTemplate("TitleContactUsTextLayout", titleContactUsTextLayoutSource);
|
||||
|
||||
Handlebars.RegisterHelper("date", (writer, context, parameters) =>
|
||||
{
|
||||
|
@ -1193,7 +1193,7 @@ public class OrganizationService : IOrganizationService
|
||||
_dataProtector.Protect($"OrganizationUserInvite {orgUser.Id} {orgUser.Email} {CoreHelpers.ToEpocMilliseconds(DateTime.UtcNow)}");
|
||||
|
||||
await _mailService.BulkSendOrganizationInviteEmailAsync(organization.Name,
|
||||
orgUsers.Select(o => (o, new ExpiringToken(MakeToken(o), DateTime.UtcNow.AddDays(5)))));
|
||||
orgUsers.Select(o => (o, new ExpiringToken(MakeToken(o), DateTime.UtcNow.AddDays(5)))), organization.PlanType == PlanType.Free);
|
||||
}
|
||||
|
||||
private async Task SendInviteAsync(OrganizationUser orgUser, Organization organization)
|
||||
@ -1202,8 +1202,7 @@ public class OrganizationService : IOrganizationService
|
||||
var nowMillis = CoreHelpers.ToEpocMilliseconds(now);
|
||||
var token = _dataProtector.Protect(
|
||||
$"OrganizationUserInvite {orgUser.Id} {orgUser.Email} {nowMillis}");
|
||||
|
||||
await _mailService.SendOrganizationInviteEmailAsync(organization.Name, orgUser, new ExpiringToken(token, now.AddDays(5)));
|
||||
await _mailService.SendOrganizationInviteEmailAsync(organization.Name, orgUser, new ExpiringToken(token, now.AddDays(5)), organization.PlanType == PlanType.Free);
|
||||
}
|
||||
|
||||
public async Task<OrganizationUser> AcceptUserAsync(Guid organizationUserId, User user, string token,
|
||||
|
@ -52,12 +52,12 @@ public class NoopMailService : IMailService
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public Task SendOrganizationInviteEmailAsync(string organizationName, OrganizationUser orgUser, ExpiringToken token)
|
||||
public Task SendOrganizationInviteEmailAsync(string organizationName, OrganizationUser orgUser, ExpiringToken token, bool isFreeOrg)
|
||||
{
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public Task BulkSendOrganizationInviteEmailAsync(string organizationName, IEnumerable<(OrganizationUser orgUser, ExpiringToken token)> invites)
|
||||
public Task BulkSendOrganizationInviteEmailAsync(string organizationName, IEnumerable<(OrganizationUser orgUser, ExpiringToken token)> invites, bool isFreeOrg)
|
||||
{
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
@ -64,7 +64,7 @@ public class OrganizationServiceTests
|
||||
.CreateManyAsync(Arg.Is<IEnumerable<OrganizationUser>>(users => users.Count() == expectedNewUsersCount));
|
||||
await sutProvider.GetDependency<IMailService>().Received(1)
|
||||
.BulkSendOrganizationInviteEmailAsync(org.Name,
|
||||
Arg.Is<IEnumerable<(OrganizationUser, ExpiringToken)>>(messages => messages.Count() == expectedNewUsersCount));
|
||||
Arg.Is<IEnumerable<(OrganizationUser, ExpiringToken)>>(messages => messages.Count() == expectedNewUsersCount), org.PlanType == PlanType.Free);
|
||||
|
||||
// Send events
|
||||
await sutProvider.GetDependency<IEventService>().Received(1)
|
||||
@ -122,7 +122,7 @@ public class OrganizationServiceTests
|
||||
.CreateManyAsync(Arg.Is<IEnumerable<OrganizationUser>>(users => users.Count() == expectedNewUsersCount));
|
||||
await sutProvider.GetDependency<IMailService>().Received(1)
|
||||
.BulkSendOrganizationInviteEmailAsync(org.Name,
|
||||
Arg.Is<IEnumerable<(OrganizationUser, ExpiringToken)>>(messages => messages.Count() == expectedNewUsersCount));
|
||||
Arg.Is<IEnumerable<(OrganizationUser, ExpiringToken)>>(messages => messages.Count() == expectedNewUsersCount), org.PlanType == PlanType.Free);
|
||||
|
||||
// Sent events
|
||||
await sutProvider.GetDependency<IEventService>().Received(1)
|
||||
@ -217,7 +217,7 @@ public class OrganizationServiceTests
|
||||
|
||||
await sutProvider.GetDependency<IMailService>().Received(1)
|
||||
.BulkSendOrganizationInviteEmailAsync(organization.Name,
|
||||
Arg.Is<IEnumerable<(OrganizationUser, ExpiringToken)>>(v => v.Count() == invite.Emails.Distinct().Count()));
|
||||
Arg.Is<IEnumerable<(OrganizationUser, ExpiringToken)>>(v => v.Count() == invite.Emails.Distinct().Count()), organization.PlanType == PlanType.Free);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
@ -460,7 +460,7 @@ public class OrganizationServiceTests
|
||||
|
||||
await sutProvider.GetDependency<IMailService>().Received(1)
|
||||
.BulkSendOrganizationInviteEmailAsync(organization.Name,
|
||||
Arg.Is<IEnumerable<(OrganizationUser, ExpiringToken)>>(v => v.Count() == invites.SelectMany(i => i.invite.Emails).Count()));
|
||||
Arg.Is<IEnumerable<(OrganizationUser, ExpiringToken)>>(v => v.Count() == invites.SelectMany(i => i.invite.Emails).Count()), organization.PlanType == PlanType.Free);
|
||||
|
||||
await sutProvider.GetDependency<IEventService>().Received(1).LogOrganizationUserEventsAsync(Arg.Any<IEnumerable<(OrganizationUser, EventType, DateTime?)>>());
|
||||
}
|
||||
@ -494,7 +494,7 @@ public class OrganizationServiceTests
|
||||
|
||||
await sutProvider.GetDependency<IMailService>().Received(1)
|
||||
.BulkSendOrganizationInviteEmailAsync(organization.Name,
|
||||
Arg.Is<IEnumerable<(OrganizationUser, ExpiringToken)>>(v => v.Count() == invites.SelectMany(i => i.invite.Emails).Count()));
|
||||
Arg.Is<IEnumerable<(OrganizationUser, ExpiringToken)>>(v => v.Count() == invites.SelectMany(i => i.invite.Emails).Count()), organization.PlanType == PlanType.Free);
|
||||
|
||||
await sutProvider.GetDependency<IEventService>().Received(1).LogOrganizationUserEventsAsync(Arg.Any<IEnumerable<(OrganizationUser, EventType, EventSystemUser, DateTime?)>>());
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user