1
0
mirror of https://github.com/bitwarden/server synced 2025-12-23 03:33:35 +00:00

Initial scaffolding of emails (#1686)

* Initial scaffolding of emails

* Work on adding models for FamilyForEnterprise emails

* Switch verbage

* Put preliminary copy in emails

* Skip test
This commit is contained in:
Justin Baur
2021-11-08 11:47:58 -05:00
parent 005774102a
commit 143be4273b
22 changed files with 393 additions and 0 deletions

View File

@@ -0,0 +1,16 @@
{{#>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">
<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> has offered to sponsor a family organization for you with Bitwarden.
</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" 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;">
Redeem
</a>
</td>
</tr>
</table>
{{/FullHtmlLayout}}

View File

@@ -0,0 +1,5 @@
{{#>BasicTextLayout}}
{{OrganizationName}} has offered to sponsor a family organization for you with Bitwarden. To redeem please click the following link:
{{Url}}
{{/BasicTextLayout}}

View File

@@ -0,0 +1,9 @@
{{#>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">
You have redeemed a family organization sponsorship from {{OrganizationName}}.
</td>
</tr>
</table>
{{/FullHtmlLayout}}

View File

@@ -0,0 +1,3 @@
{{#>BasicTextLayout}}
You have redeemed a family organization sponsorship from {{OrganizationName}}.
{{/BasicTextLayout}}

View File

@@ -0,0 +1,9 @@
{{#>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">
You have redeemed a Families for Enterprise sponsorship from {{OrganizationName}}.
</td>
</tr>
</table>
{{/FullHtmlLayout}}

View File

@@ -0,0 +1,3 @@
{{#>BasicTextLayout}}
A user in your organization has redeemed a family invitation.
{{/BasicTextLayout}}

View File

@@ -0,0 +1,16 @@
{{#>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">
Your Families for Enterprise sponsorship requires reconfirmation.
</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" 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;">
Reconfirm
</a>
</td>
</tr>
</table>
{{/FullHtmlLayout}}

View File

@@ -0,0 +1,5 @@
{{#>BasicTextLayout}}
Your Families for Enterprise sponsorship requires reconfirmation. To redeem please click the following link:
{{Url}}
{{/BasicTextLayout}}

View File

@@ -0,0 +1,9 @@
{{#>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">
Your Families for Enterprise sponsorship has ended and you will lose premium access at the end of the current billing cycle.
</td>
</tr>
</table>
{{/FullHtmlLayout}}

View File

@@ -0,0 +1,3 @@
{{#>BasicTextLayout}}
Your Families for Enterprise sponsorship has ended and you will lose premium access at the end of the current billing cycle.
{{/BasicTextLayout}}

View File

@@ -0,0 +1,9 @@
{{#>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">
Your Families for Enterprise sponsorship will revert back to your existing payment method at the end of the current billing cycle.
</td>
</tr>
</table>
{{/FullHtmlLayout}}

View File

@@ -0,0 +1,3 @@
{{#>BasicTextLayout}}
Your Families for Enterprise sponsorship will revert back to your existing payment method at the end of the current billing cycle.
{{/BasicTextLayout}}

View File

@@ -0,0 +1,8 @@
namespace Bit.Core.Models.Mail.FamiliesForEnterprise
{
public class FamiliesForEnterpriseInviteRedeemableViewModel : BaseMailModel
{
public string OrganizationName { get; set; }
public string Url { get; set; }
}
}

View File

@@ -0,0 +1,7 @@
namespace Bit.Core.Models.Mail.FamiliesForEnterprise
{
public class FamiliesForEnterpriseInviteRedeemedToFamilyUserViewModel : BaseMailModel
{
public string OrganizationName { get; set; }
}
}

View File

@@ -0,0 +1,7 @@
namespace Bit.Core.Models.Mail.FamiliesForEnterprise
{
public class FamiliesForEnterpriseInviteRedeemedToOrgUserViewModel : BaseMailModel
{
public string OrganizationName { get; set; }
}
}

View File

@@ -0,0 +1,7 @@
namespace Bit.Core.Models.Mail.FamiliesForEnterprise
{
public class FamiliesForEnterpriseReconfirmationRequiredViewModel : BaseMailModel
{
}
}

View File

@@ -0,0 +1,7 @@
namespace Bit.Core.Models.Mail.FamiliesForEnterprise
{
public class FamiliesForEnterpriseSponsorshipEndingViewModel : BaseMailModel
{
}
}

View File

@@ -0,0 +1,7 @@
namespace Bit.Core.Models.Mail.FamiliesForEnterprise
{
public class FamiliesForEnterpriseSponsorshipRevertingViewModel : BaseMailModel
{
}
}

View File

@@ -49,5 +49,13 @@ namespace Bit.Core.Services
Task SendProviderConfirmedEmailAsync(string providerName, string email);
Task SendProviderUserRemoved(string providerName, string email);
Task SendUpdatedTempPasswordEmailAsync(string email, string userName);
// TODO: Change signature to hold data needed for email
Task SendFamiliesForEnterpriseInviteRedeemableEmailAsync(string email, string organizationName, string token);
// NOTE: Not married to these next two names
Task SendFamiliesForEnterpriseInviteRedeemedToFamilyUserEmailAsync(string email);
Task SendFamiliesForEnterpriseInviteRedeemedToOrgUserEmailAsync(string email, string organizationName);
Task SendFamiliesForEnterpriseReconfirmationRequiredEmailAsync(string email);
Task SendFamiliesForEnterpriseSponsorshipRevertingEmailAsync(string email);
Task SendFamiliesForEnterpriseSponsorshipEndingEmailAsync(string email);
}
}

View File

@@ -9,6 +9,7 @@ using System.Net;
using Bit.Core.Utilities;
using System.Linq;
using System.Reflection;
using Bit.Core.Models.Mail.FamiliesForEnterprise;
using Bit.Core.Models.Mail.Provider;
using Bit.Core.Models.Table.Provider;
using HandlebarsDotNet;
@@ -755,5 +756,93 @@ namespace Bit.Core.Services
message.Category = "UpdatedTempPassword";
await _mailDeliveryService.SendEmailAsync(message);
}
public async Task SendFamiliesForEnterpriseInviteRedeemableEmailAsync(string email, string organizationName, string token)
{
// TODO: Complete emails
var message = CreateDefaultMessage("A Family Organization Invite Is Redeemable", email);
// NOTE: If somehow cloud vault changes this will need to change/be injected
var url = CoreHelpers.ExtendQuery(new Uri($"https://vault.bitwarden.com/#/sponsored/families-for-enterprise"),
new Dictionary<string, string>
{
["sponsorshipToken"] = token,
});
var model = new FamiliesForEnterpriseInviteRedeemableViewModel
{
Url = url.ToString(),
OrganizationName = organizationName,
};
await AddMessageContentAsync(message, "FamiliesForEnterprise.FamiliesForEnterpriseInviteRedeemable", model);
message.Category = "FamiliesForEnterpriseInviteRedeemable";
await _mailDeliveryService.SendEmailAsync(message);
}
public async Task SendFamiliesForEnterpriseInviteRedeemedToFamilyUserEmailAsync(string email)
{
// TODO: Complete emails
var message = CreateDefaultMessage("You Have Redeemed A Family Organization Sponsorship", email);
var model = new FamiliesForEnterpriseInviteRedeemedToFamilyUserViewModel
{
};
await AddMessageContentAsync(message, "FamiliesForEnterprise.FamiliesForEnterpriseInviteRedeemedToFamilyUser", model);
message.Category = "FamilyForEnterpriseInviteRedeemedToFamilyUser";
await _mailDeliveryService.SendEmailAsync(message);
}
public async Task SendFamiliesForEnterpriseInviteRedeemedToOrgUserEmailAsync(string email, string organizationName)
{
// TODO: Complete emails
var message = CreateDefaultMessage("A User Has Redeemeed Your Sponsorship", email);
var model = new FamiliesForEnterpriseInviteRedeemedToOrgUserViewModel
{
OrganizationName = organizationName,
};
await AddMessageContentAsync(message, "FamiliesForEnterprise.FamiliesForEnterpriseInviteRedeemedToOrgUser", model);
message.Category = "FamilyForEnterpriseInviteRedeemedToOrgUser";
await _mailDeliveryService.SendEmailAsync(message);
}
public async Task SendFamiliesForEnterpriseReconfirmationRequiredEmailAsync(string email)
{
// TODO: Complete emails
var message = CreateDefaultMessage("Your Sponsorship Requires Reconfirmation", email);
var model = new FamiliesForEnterpriseReconfirmationRequiredViewModel
{
};
await AddMessageContentAsync(message, "FamiliesForEnterprise.FamiliesForEnterpriseReconfirmationRequired", model);
message.Category = "FamiliesForEnterpriseReconfirmationRequired";
await _mailDeliveryService.SendEmailAsync(message);
}
public async Task SendFamiliesForEnterpriseSponsorshipRevertingEmailAsync(string email)
{
// TODO: Complete emails
var message = CreateDefaultMessage("A Family Organization Sponsorship Is Reverting", email);
var model = new FamiliesForEnterpriseSponsorshipRevertingViewModel
{
};
await AddMessageContentAsync(message, "FamiliesForEnterprise.FamiliesForEnterpriseSponsorshipReverting", model);
message.Category = "FamiliesForEnterpriseSponsorshipReverting";
await _mailDeliveryService.SendEmailAsync(message);
}
public async Task SendFamiliesForEnterpriseSponsorshipEndingEmailAsync(string email)
{
// TODO: Complete emails
var message = CreateDefaultMessage("A Family Organization Sponsorship Is Ending", email);
var model = new FamiliesForEnterpriseSponsorshipEndingViewModel
{
};
await AddMessageContentAsync(message, "FamiliesForEnterprise.FamiliesForEnterpriseSponsorshipEnding", model);
message.Category = "FamiliesForEnterpriseSponsorshipEnding";
await _mailDeliveryService.SendEmailAsync(message);
}
}
}

View File

@@ -200,5 +200,35 @@ namespace Bit.Core.Services
{
return Task.FromResult(0);
}
public Task SendFamiliesForEnterpriseInviteRedeemableEmailAsync(string email, string organizationName, string token)
{
return Task.FromResult(0);
}
public Task SendFamiliesForEnterpriseInviteRedeemedToFamilyUserEmailAsync(string email)
{
return Task.FromResult(0);
}
public Task SendFamiliesForEnterpriseInviteRedeemedToOrgUserEmailAsync(string email, string organizationName)
{
return Task.FromResult(0);
}
public Task SendFamiliesForEnterpriseReconfirmationRequiredEmailAsync(string email)
{
return Task.FromResult(0);
}
public Task SendFamiliesForEnterpriseSponsorshipRevertingEmailAsync(string email)
{
return Task.FromResult(0);
}
public Task SendFamiliesForEnterpriseSponsorshipEndingEmailAsync(string email)
{
return Task.FromResult(0);
}
}
}