diff --git a/src/Core/AdminConsole/Services/Implementations/OrganizationDomainService.cs b/src/Core/AdminConsole/Services/Implementations/OrganizationDomainService.cs index 4ce33f3b5b..9b99cf71f0 100644 --- a/src/Core/AdminConsole/Services/Implementations/OrganizationDomainService.cs +++ b/src/Core/AdminConsole/Services/Implementations/OrganizationDomainService.cs @@ -17,6 +17,7 @@ public class OrganizationDomainService : IOrganizationDomainService private readonly TimeProvider _timeProvider; private readonly ILogger _logger; private readonly IGlobalSettings _globalSettings; + private readonly IFeatureService _featureService; public OrganizationDomainService( IOrganizationDomainRepository domainRepository, @@ -26,7 +27,8 @@ public class OrganizationDomainService : IOrganizationDomainService IVerifyOrganizationDomainCommand verifyOrganizationDomainCommand, TimeProvider timeProvider, ILogger logger, - IGlobalSettings globalSettings) + IGlobalSettings globalSettings, + IFeatureService featureService) { _domainRepository = domainRepository; _organizationUserRepository = organizationUserRepository; @@ -36,6 +38,7 @@ public class OrganizationDomainService : IOrganizationDomainService _timeProvider = timeProvider; _logger = logger; _globalSettings = globalSettings; + _featureService = featureService; } public async Task ValidateOrganizationsDomainAsync() @@ -90,8 +93,16 @@ public class OrganizationDomainService : IOrganizationDomainService //Send email to administrators if (adminEmails.Count > 0) { - await _mailService.SendUnverifiedOrganizationDomainEmailAsync(adminEmails, - domain.OrganizationId.ToString(), domain.DomainName); + if (_featureService.IsEnabled(FeatureFlagKeys.AccountDeprovisioning)) + { + await _mailService.SendUnclaimedOrganizationDomainEmailAsync(adminEmails, + domain.OrganizationId.ToString(), domain.DomainName); + } + else + { + await _mailService.SendUnverifiedOrganizationDomainEmailAsync(adminEmails, + domain.OrganizationId.ToString(), domain.DomainName); + } } _logger.LogInformation(Constants.BypassFiltersEventId, "Expired domain: {domainName}", domain.DomainName); diff --git a/src/Core/MailTemplates/Handlebars/OrganizationDomainUnclaimed.html.hbs b/src/Core/MailTemplates/Handlebars/OrganizationDomainUnclaimed.html.hbs new file mode 100644 index 0000000000..cc42898c29 --- /dev/null +++ b/src/Core/MailTemplates/Handlebars/OrganizationDomainUnclaimed.html.hbs @@ -0,0 +1,27 @@ +{{#>FullHtmlLayout}} + + + + + + + + + + + + + +
+ The domain {{DomainName}} in your Bitwarden organization could not be claimed. +
+ Check the corresponding record in your domain host. Then reclaim this domain in Bitwarden to use it for your organization. +
+ The domain will be removed from your organization in 7 days if it is not claimed. +
+ + Manage Domains + +
+
+{{/FullHtmlLayout}} diff --git a/src/Core/MailTemplates/Handlebars/OrganizationDomainUnclaimed.text.hbs b/src/Core/MailTemplates/Handlebars/OrganizationDomainUnclaimed.text.hbs new file mode 100644 index 0000000000..4f205c5054 --- /dev/null +++ b/src/Core/MailTemplates/Handlebars/OrganizationDomainUnclaimed.text.hbs @@ -0,0 +1,10 @@ +{{#>BasicTextLayout}} +The domain {{DomainName}} in your Bitwarden organization could not be claimed. + +Check the corresponding record in your domain host. Then reclaim this domain in Bitwarden to use it for your organization. + +The domain will be removed from your organization in 7 days if it is not claimed. + +{{Url}} + +{{/BasicTextLayout}} diff --git a/src/Core/Services/IMailService.cs b/src/Core/Services/IMailService.cs index c6c9dc7948..0f69d8daaf 100644 --- a/src/Core/Services/IMailService.cs +++ b/src/Core/Services/IMailService.cs @@ -85,6 +85,7 @@ public interface IMailService Task SendFailedLoginAttemptsEmailAsync(string email, DateTime utcNow, string ip); Task SendFailedTwoFactorAttemptsEmailAsync(string email, DateTime utcNow, string ip); Task SendUnverifiedOrganizationDomainEmailAsync(IEnumerable adminEmails, string organizationId, string domainName); + Task SendUnclaimedOrganizationDomainEmailAsync(IEnumerable adminEmails, string organizationId, string domainName); Task SendSecretsManagerMaxSeatLimitReachedEmailAsync(Organization organization, int maxSeatCount, IEnumerable ownerEmails); Task SendSecretsManagerMaxServiceAccountLimitReachedEmailAsync(Organization organization, int maxSeatCount, IEnumerable ownerEmails); Task SendTrustedDeviceAdminApprovalEmailAsync(string email, DateTime utcNow, string ip, string deviceTypeAndIdentifier); diff --git a/src/Core/Services/Implementations/HandlebarsMailService.cs b/src/Core/Services/Implementations/HandlebarsMailService.cs index c220df18a1..22341111f3 100644 --- a/src/Core/Services/Implementations/HandlebarsMailService.cs +++ b/src/Core/Services/Implementations/HandlebarsMailService.cs @@ -1068,6 +1068,19 @@ public class HandlebarsMailService : IMailService await _mailDeliveryService.SendEmailAsync(message); } + public async Task SendUnclaimedOrganizationDomainEmailAsync(IEnumerable adminEmails, string organizationId, string domainName) + { + var message = CreateDefaultMessage("Domain not claimed", adminEmails); + var model = new OrganizationDomainUnverifiedViewModel + { + Url = $"{_globalSettings.BaseServiceUri.VaultWithHash}/organizations/{organizationId}/settings/domain-verification", + DomainName = domainName + }; + await AddMessageContentAsync(message, "OrganizationDomainUnclaimed", model); + message.Category = "UnclaimedOrganizationDomain"; + await _mailDeliveryService.SendEmailAsync(message); + } + public async Task SendSecretsManagerMaxSeatLimitReachedEmailAsync(Organization organization, int maxSeatCount, IEnumerable ownerEmails) { diff --git a/src/Core/Services/NoopImplementations/NoopMailService.cs b/src/Core/Services/NoopImplementations/NoopMailService.cs index e8ea8d9863..4ce188c86b 100644 --- a/src/Core/Services/NoopImplementations/NoopMailService.cs +++ b/src/Core/Services/NoopImplementations/NoopMailService.cs @@ -273,6 +273,11 @@ public class NoopMailService : IMailService return Task.FromResult(0); } + public Task SendUnclaimedOrganizationDomainEmailAsync(IEnumerable adminEmails, string organizationId, string domainName) + { + return Task.FromResult(0); + } + public Task SendSecretsManagerMaxSeatLimitReachedEmailAsync(Organization organization, int maxSeatCount, IEnumerable ownerEmails) {