mirror of
https://github.com/bitwarden/server.git
synced 2024-11-25 12:45:18 +01: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:
parent
005774102a
commit
143be4273b
@ -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}}
|
@ -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}}
|
@ -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}}
|
@ -0,0 +1,3 @@
|
||||
{{#>BasicTextLayout}}
|
||||
You have redeemed a family organization sponsorship from {{OrganizationName}}.
|
||||
{{/BasicTextLayout}}
|
@ -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}}
|
@ -0,0 +1,3 @@
|
||||
{{#>BasicTextLayout}}
|
||||
A user in your organization has redeemed a family invitation.
|
||||
{{/BasicTextLayout}}
|
@ -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}}
|
@ -0,0 +1,5 @@
|
||||
{{#>BasicTextLayout}}
|
||||
Your Families for Enterprise sponsorship requires reconfirmation. To redeem please click the following link:
|
||||
|
||||
{{Url}}
|
||||
{{/BasicTextLayout}}
|
@ -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}}
|
@ -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}}
|
@ -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}}
|
@ -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}}
|
@ -0,0 +1,8 @@
|
||||
namespace Bit.Core.Models.Mail.FamiliesForEnterprise
|
||||
{
|
||||
public class FamiliesForEnterpriseInviteRedeemableViewModel : BaseMailModel
|
||||
{
|
||||
public string OrganizationName { get; set; }
|
||||
public string Url { get; set; }
|
||||
}
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
namespace Bit.Core.Models.Mail.FamiliesForEnterprise
|
||||
{
|
||||
public class FamiliesForEnterpriseInviteRedeemedToFamilyUserViewModel : BaseMailModel
|
||||
{
|
||||
public string OrganizationName { get; set; }
|
||||
}
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
namespace Bit.Core.Models.Mail.FamiliesForEnterprise
|
||||
{
|
||||
public class FamiliesForEnterpriseInviteRedeemedToOrgUserViewModel : BaseMailModel
|
||||
{
|
||||
public string OrganizationName { get; set; }
|
||||
}
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
namespace Bit.Core.Models.Mail.FamiliesForEnterprise
|
||||
{
|
||||
public class FamiliesForEnterpriseReconfirmationRequiredViewModel : BaseMailModel
|
||||
{
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
namespace Bit.Core.Models.Mail.FamiliesForEnterprise
|
||||
{
|
||||
public class FamiliesForEnterpriseSponsorshipEndingViewModel : BaseMailModel
|
||||
{
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
namespace Bit.Core.Models.Mail.FamiliesForEnterprise
|
||||
{
|
||||
public class FamiliesForEnterpriseSponsorshipRevertingViewModel : BaseMailModel
|
||||
{
|
||||
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,14 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
using Bit.Core.Models.Business;
|
||||
using Bit.Core.Models.Table;
|
||||
using Bit.Core.Models.Table.Provider;
|
||||
using Bit.Core.Services;
|
||||
using Bit.Core.Settings;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using NSubstitute;
|
||||
using Xunit;
|
||||
|
||||
@ -27,6 +35,131 @@ namespace Bit.Core.Test.Services
|
||||
);
|
||||
}
|
||||
|
||||
[Fact(Skip = "Only for local development")]
|
||||
public async Task SendAllEmails()
|
||||
{
|
||||
// This test is only opt in and is more for development purposes.
|
||||
// This will send all emails to the test email address so that they can be viewed.
|
||||
var namedParameters = new Dictionary<(string, Type), object>
|
||||
{
|
||||
// TODO: Swith to use env variable
|
||||
{ ("email", typeof(string)), "test@bitwarden.com" },
|
||||
{ ("user", typeof(User)), new User
|
||||
{
|
||||
Id = Guid.NewGuid(),
|
||||
Email = "test@bitwarden.com",
|
||||
}},
|
||||
{ ("userId", typeof(Guid)), Guid.NewGuid() },
|
||||
{ ("token", typeof(string)), "test_token" },
|
||||
{ ("fromEmail", typeof(string)), "test@bitwarden.com" },
|
||||
{ ("toEmail", typeof(string)), "test@bitwarden.com" },
|
||||
{ ("newEmailAddress", typeof(string)), "test@bitwarden.com" },
|
||||
{ ("hint", typeof(string)), "Test Hint" },
|
||||
{ ("organizationName", typeof(string)), "Test Organization Name" },
|
||||
{ ("orgUser", typeof(OrganizationUser)), new OrganizationUser
|
||||
{
|
||||
Id = Guid.NewGuid(),
|
||||
Email = "test@bitwarden.com",
|
||||
OrganizationId = Guid.NewGuid(),
|
||||
|
||||
}},
|
||||
{ ("token", typeof(ExpiringToken)), new ExpiringToken("test_token", DateTime.UtcNow.AddDays(1))},
|
||||
{ ("organization", typeof(Organization)), new Organization
|
||||
{
|
||||
Id = Guid.NewGuid(),
|
||||
Name = "Test Organization Name",
|
||||
Seats = 5
|
||||
}},
|
||||
{ ("initialSeatCount", typeof(int)), 5},
|
||||
{ ("ownerEmails", typeof(IEnumerable<string>)), new [] { "test@bitwarden.com" }},
|
||||
{ ("maxSeatCount", typeof(int)), 5 },
|
||||
{ ("userIdentifier", typeof(string)), "test_user" },
|
||||
{ ("adminEmails", typeof(IEnumerable<string>)), new [] { "test@bitwarden.com" }},
|
||||
{ ("returnUrl", typeof(string)), "https://bitwarden.com/" },
|
||||
{ ("amount", typeof(decimal)), 1.00M },
|
||||
{ ("dueDate", typeof(DateTime)), DateTime.UtcNow.AddDays(1) },
|
||||
{ ("items", typeof(List<string>)), new List<string> { "test@bitwarden.com" }},
|
||||
{ ("mentionInvoices", typeof(bool)), true },
|
||||
{ ("emails", typeof(IEnumerable<string>)), new [] { "test@bitwarden.com" }},
|
||||
{ ("deviceType", typeof(string)), "Mobile" },
|
||||
{ ("timestamp", typeof(DateTime)), DateTime.UtcNow.AddDays(1)},
|
||||
{ ("ip", typeof(string)), "127.0.0.1" },
|
||||
{ ("emergencyAccess", typeof(EmergencyAccess)), new EmergencyAccess
|
||||
{
|
||||
Id = Guid.NewGuid(),
|
||||
Email = "test@bitwarden.com",
|
||||
}},
|
||||
{ ("granteeEmail", typeof(string)), "test@bitwarden.com" },
|
||||
{ ("grantorName", typeof(string)), "Test User" },
|
||||
{ ("initiatingName", typeof(string)), "Test" },
|
||||
{ ("approvingName", typeof(string)), "Test Name" },
|
||||
{ ("rejectingName", typeof(string)), "Test Name" },
|
||||
{ ("provider", typeof(Provider)), new Provider
|
||||
{
|
||||
Id = Guid.NewGuid(),
|
||||
}},
|
||||
{ ("name", typeof(string)), "Test Name" },
|
||||
{ ("ea", typeof(EmergencyAccess)), new EmergencyAccess
|
||||
{
|
||||
Id = Guid.NewGuid(),
|
||||
Email = "test@bitwarden.com",
|
||||
}},
|
||||
{ ("userName", typeof(string)), "testUser" },
|
||||
{ ("orgName", typeof(string)), "Test Org Name" },
|
||||
{ ("providerName", typeof(string)), "testProvider" },
|
||||
{ ("providerUser", typeof(ProviderUser)), new ProviderUser
|
||||
{
|
||||
ProviderId = Guid.NewGuid(),
|
||||
Id = Guid.NewGuid(),
|
||||
}},
|
||||
};
|
||||
|
||||
var globalSettings = new GlobalSettings
|
||||
{
|
||||
Mail = new GlobalSettings.MailSettings
|
||||
{
|
||||
Smtp = new GlobalSettings.MailSettings.SmtpSettings
|
||||
{
|
||||
Host = "localhost",
|
||||
TrustServer = true,
|
||||
Port = 10250,
|
||||
},
|
||||
ReplyToEmail = "noreply@bitwarden.com",
|
||||
},
|
||||
SiteName = "Bitwarden",
|
||||
};
|
||||
|
||||
var mailDeliveryService = new MailKitSmtpMailDeliveryService(globalSettings, Substitute.For<ILogger<MailKitSmtpMailDeliveryService>>());
|
||||
|
||||
var handlebarsService = new HandlebarsMailService(globalSettings, mailDeliveryService, new BlockingMailEnqueuingService());
|
||||
|
||||
var sendMethods = typeof(IMailService).GetMethods(BindingFlags.Public | BindingFlags.Instance)
|
||||
.Where(m => m.Name.StartsWith("Send") && m.Name != "SendEnqueuedMailMessageAsync");
|
||||
|
||||
foreach (var sendMethod in sendMethods)
|
||||
{
|
||||
await InvokeMethod(sendMethod);
|
||||
}
|
||||
|
||||
async Task InvokeMethod(MethodInfo method)
|
||||
{
|
||||
var parameters = method.GetParameters();
|
||||
var args = new object[parameters.Length];
|
||||
|
||||
for(var i = 0; i < parameters.Length; i++)
|
||||
{
|
||||
if (!namedParameters.TryGetValue((parameters[i].Name, parameters[i].ParameterType), out var value))
|
||||
{
|
||||
throw new InvalidOperationException($"Couldn't find a parameter for name '{parameters[i].Name}' and type '{parameters[i].ParameterType.FullName}'");
|
||||
}
|
||||
|
||||
args[i] = value;
|
||||
}
|
||||
|
||||
await (Task)method.Invoke(handlebarsService, args);
|
||||
}
|
||||
}
|
||||
|
||||
// Remove this test when we add actual tests. It only proves that
|
||||
// we've properly constructed the system under test.
|
||||
[Fact]
|
||||
|
Loading…
Reference in New Issue
Block a user