Skip to content

Commit 3ac4522

Browse files
committed
Added setting to disable email notifications
1 parent 9a83a04 commit 3ac4522

File tree

7 files changed

+172
-10
lines changed

7 files changed

+172
-10
lines changed

Scripts/Set-SenderRecipientCredentials.ps1

Lines changed: 50 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,46 @@ Set-SenderRecipientCredentials -SubscriptionName "<subscription name>" `
4747
-Verbose
4848
4949
#>
50+
51+
function Skip-SenderRecipientCredentials {
52+
[CmdletBinding()]
53+
param(
54+
[Parameter(Mandatory=$True)]
55+
[string] $SubscriptionName,
56+
[Parameter(Mandatory=$True)]
57+
[string] $SolutionAbbreviation,
58+
[Parameter(Mandatory=$True)]
59+
[string] $EnvironmentAbbreviation
60+
)
61+
62+
$defaultValue = "not-set"
63+
$defaultSecret = New-Object System.Security.SecureString
64+
$defaultValue.ToCharArray() | ForEach-Object { $defaultSecret.AppendChar($_) }
65+
66+
Set-SenderRecipientCredentials `
67+
-SubscriptionName $SubscriptionName `
68+
-SolutionAbbreviation $SolutionAbbreviation `
69+
-EnvironmentAbbreviation $EnvironmentAbbreviation `
70+
-SecureSenderUsername $defaultSecret `
71+
-SecureSenderPassword $defaultSecret `
72+
-SecureSyncCompletedCCEmailAddresses $defaultValue `
73+
-SecureSyncDisabledCCEmailAddresses $defaultValue `
74+
-SecureSupportEmailAddresses $defaultValue `
75+
-GmmGraphAppHasMailApplicationPermissions $false
76+
77+
$dataResourceGroupName = "$SolutionAbbreviation-data-$EnvironmentAbbreviation"
78+
$appConfigName = "$SolutionAbbreviation-appConfig-$EnvironmentAbbreviation"
79+
$appConfigObject = Get-AzAppConfigurationStore -ResourceGroupName $dataResourceGroupName -Name $appConfigName;
80+
81+
Set-AzAppConfigurationKeyValue -Endpoint $appConfigObject.Endpoint `
82+
-Key "Mail:SkipMailNotifications" `
83+
-Value "true" `
84+
-ContentType "boolean" `
85+
-Etag { tag1="Mail" }
86+
87+
Write-Host "Set Mail:SkipMailNotifications key with the value 'true'";
88+
}
89+
5090
function Set-SenderRecipientCredentials {
5191
[CmdletBinding()]
5292
param(
@@ -147,13 +187,13 @@ function Set-SenderRecipientCredentials {
147187

148188
#endregion
149189

190+
$dataResourceGroupName = "$SolutionAbbreviation-data-$EnvironmentAbbreviation"
191+
$appConfigName = "$SolutionAbbreviation-appConfig-$EnvironmentAbbreviation"
192+
$appConfigObject = Get-AzAppConfigurationStore -ResourceGroupName $dataResourceGroupName -Name $appConfigName;
193+
150194
#region If GMM Graph App has Application permission for Mail.Send, add app config value to indicate it
151195
if($GmmGraphAppHasMailApplicationPermissions) {
152196

153-
$dataResourceGroupName = "$SolutionAbbreviation-data-$EnvironmentAbbreviation"
154-
$appConfigName = "$SolutionAbbreviation-appConfig-$EnvironmentAbbreviation"
155-
$appConfigObject = Get-AzAppConfigurationStore -ResourceGroupName $dataResourceGroupName -Name $appConfigName;
156-
157197
Set-AzAppConfigurationKeyValue -Endpoint $appConfigObject.Endpoint `
158198
-Key "Mail:IsMailApplicationPermissionGranted" `
159199
-Value "true" `
@@ -164,6 +204,12 @@ function Set-SenderRecipientCredentials {
164204

165205
}
166206

207+
Set-AzAppConfigurationKeyValue -Endpoint $appConfigObject.Endpoint `
208+
-Key "Mail:SkipMailNotifications" `
209+
-Value "false" `
210+
-ContentType "boolean" `
211+
-Etag { tag1="Mail" }
212+
167213
#endregion
168214

169215
Write-Verbose "Set-SenderRecipientCredentials completed."

Service/GroupMembershipManagement/DIConcreteTypes/MailConfig.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,14 @@ public class MailConfig : IMailConfig
1010
public bool IsAdaptiveCardEnabled { get; set; }
1111
public bool GMMHasSendMailApplicationPermissions { get; set; }
1212
public string SenderAddress { get; set; }
13+
public bool SkipEmailNotifications { get; set; }
1314

14-
public MailConfig(bool isAdaptiveCardEnabled, bool gmmHasSendMailApplicationPermissions, string senderAddress)
15+
public MailConfig(bool isAdaptiveCardEnabled, bool gmmHasSendMailApplicationPermissions, string senderAddress, bool skipEmailNotifications)
1516
{
1617
IsAdaptiveCardEnabled = isAdaptiveCardEnabled;
1718
GMMHasSendMailApplicationPermissions = gmmHasSendMailApplicationPermissions;
1819
SenderAddress = senderAddress;
20+
SkipEmailNotifications = skipEmailNotifications;
1921
}
2022

2123
public MailConfig()

Service/GroupMembershipManagement/Hosts.FunctionBase/CommonStartup.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,8 @@ public override void Configure(IFunctionsHostBuilder builder)
157157
var configuration = services.GetService<IConfiguration>();
158158
return new MailConfig(configuration.GetValue<bool>("Mail:IsAdaptiveCardEnabled"),
159159
configuration.GetValue("Mail:IsMailApplicationPermissionGranted", false),
160-
configuration.GetValue<string>("senderAddress"));
160+
configuration.GetValue<string>("senderAddress"),
161+
configuration.GetValue("Mail:SkipMailNotifications", false));
161162
});
162163

163164
builder.Services.AddSingleton<IMailRepository>(services =>

Service/GroupMembershipManagement/Hosts/Notifier/Services.Notifier.Tests/NotifierServiceTests.cs

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,13 @@
2525
using DIConcreteTypes;
2626
using Repositories.Logging;
2727
using Models.Entities;
28+
using Repositories.Mail;
29+
using Microsoft.Graph;
30+
using Microsoft.Azure.Documents.SystemFunctions;
31+
using Microsoft.Graph.Me.SendMail;
32+
using static Microsoft.Graph.Me.SendMail.SendMailRequestBuilder;
33+
using System.Threading;
34+
using Microsoft.Kiota.Abstractions;
2835

2936
namespace Services.Notifier.Tests
3037
{
@@ -250,5 +257,69 @@ public async Task SendNormalThresholdEmailAsync_SendsEmail_WithExpectedParameter
250257
_mailRepository.Verify(x => x.SendMailAsync(It.IsAny<EmailMessage>(), It.IsAny<Guid?>()), Times.Once());
251258

252259
}
260+
261+
[TestMethod]
262+
public async Task SendEmailWhenEmailsHaveBeenDisabled()
263+
{
264+
265+
var requestAdapter = new Mock<IRequestAdapter>();
266+
requestAdapter.SetupProperty(x => x.BaseUrl).SetReturnsDefault("https://graph.microsoft.com/v1.0");
267+
var graphServiceClient = new Mock<GraphServiceClient>(requestAdapter.Object, "https://graph.microsoft.com/v1.0");
268+
269+
var mailConfig = new MailConfig(true, false, "not-set", true);
270+
var mailRepository = new MailRepository(graphServiceClient.Object,
271+
mailConfig,
272+
_localizationRepository,
273+
_loggerMock.Object,
274+
"abc",
275+
_graphGroupRepository.Object,
276+
new Mock<IDatabaseSettingsRepository>().Object);
277+
278+
_notifierService = new NotifierService(_loggerMock.Object,
279+
mailRepository,
280+
_mailAddresses.Object,
281+
_localizationRepository,
282+
_thresholdNotificationService.Object,
283+
_notificationRepository.Object,
284+
_graphGroupRepository.Object,
285+
_notificationTypesRepository.Object,
286+
_jobNotificationRepository.Object,
287+
_thresholdConfig.Object,
288+
_gmmResources.Object,
289+
_telemetryClient
290+
);
291+
292+
SyncJob job = SampleDataHelper.CreateSampleSyncJobs(1, GroupMembership).First();
293+
var notificationTypeId = 1;
294+
295+
string[] additionalContentParameters = new string[] { "Param1", "Param2" };
296+
var messageContent = new Dictionary<string, Object>
297+
{
298+
{ "SyncJob", job },
299+
{ "AdditionalContentParameters", additionalContentParameters }
300+
};
301+
string subjectTemplate = "DisabledJobEmailSubject";
302+
string contentTemplate = "SyncDisabledNoGroupEmailBody";
303+
_notificationTypesRepository.Setup(repo => repo.GetNotificationTypeByNotificationTypeNameAsync(contentTemplate))
304+
.ReturnsAsync(new NotificationType { Id = notificationTypeId, Name = contentTemplate, Disabled = false });
305+
306+
_jobNotificationRepository.Setup(repo => repo.IsNotificationDisabledForJobAsync(job.Id, notificationTypeId))
307+
.ReturnsAsync(false);
308+
309+
string serializedMessageContent = JsonSerializer.Serialize(messageContent);
310+
OrchestratorRequest request = new OrchestratorRequest
311+
{
312+
MessageType = nameof(NotificationMessageType.SyncStartedNotification),
313+
MessageBody = serializedMessageContent,
314+
SubjectTemplate = subjectTemplate,
315+
ContentTemplate = contentTemplate
316+
};
317+
318+
await _notifierService.SendEmailAsync(request.MessageType, request.MessageBody, request.SubjectTemplate, request.ContentTemplate);
319+
_loggerMock.Verify(x => x.LogMessageAsync(It.Is<LogMessage>(m => m.Message.Equals("Email notifications are disabled.")),
320+
VerbosityLevel.INFO,
321+
It.IsAny<string>(),
322+
It.IsAny<string>()), Times.Once());
323+
}
253324
}
254325
}

Service/GroupMembershipManagement/Repositories.Contracts/InjectConfig/IMailConfig.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,6 @@ public interface IMailConfig
88
public bool IsAdaptiveCardEnabled { get; }
99
public bool GMMHasSendMailApplicationPermissions { get; set; }
1010
public string SenderAddress { get; set; }
11+
public bool SkipEmailNotifications { get; set; }
1112
}
1213
}

Service/GroupMembershipManagement/Repositories.Mail/Documentation/SetSenderAddressForEmailNotification.md

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# Set sender address for email notification
22

3+
Follow the steps below to set the sender's credentials that will be used to send email notifications. If you don't want to use email notifications see [Skip email notifications](#skip-email-notifications).
4+
35
1) Open the Azure Portal from the tenant where the Graph App is created in
46
2) Add Mail.Send Delegated Permission in `<SolutionAbbreviation>-Graph-<EnvironmentAbbreviation>` application
57

@@ -58,4 +60,32 @@
5860
* key = "Mail:IsMailApplicationPermissionGranted"
5961
* value = "true"
6062
61-
3) If the key-value pair above does not exist (maybe the Set-SenderReceipientCredentials script failed at the end) then add it
63+
3) If the key-value pair above does not exist (maybe the Set-SenderReceipientCredentials script failed at the end) then add it
64+
65+
## Skip email notifications
66+
67+
If you decide not to use email notifications follow these steps. From Powershell 7 command prompt run:
68+
69+
```
70+
. ./Set-SenderRecipientCredentials.ps1
71+
72+
Skip-SenderRecipientCredentials `
73+
-SubscriptionName "<SubscriptionName>" `
74+
-SolutionAbbreviation "<SolutionAbbreviation>" `
75+
-EnvironmentAbbreviation "<EnvironmentAbbreviation>" `
76+
```
77+
78+
The script will populate default values for sender's username and password required by GMM deployment to succeed, and it also indicates GMM to not send any email notifications by setting Mail:SkipMailNotifications to true in App Configuration settings.
79+
80+
If at a later time you decide to use email notifications you will need to follow steps from [Set sender address for email notification](#set-sender-address-for-email-notification). Keep in mind that re-running these scripts creates a new version of the senderUsername and senderPassword secrets in your prereqs keyvault. You will need to update the Notifier's function settings to use the latest version of the secrets.
81+
82+
Notifier's function sender credentials settings that need to be updated:
83+
```
84+
"name": "senderAddress",
85+
"value": "@Microsoft.KeyVault(SecretUri=https://<solutionAbbreviation>-prereqs-<environmentAbbreviation>.vault.azure.net/secrets/senderUsername/<version>)"
86+
87+
"name": "senderPassword",
88+
"value": "@Microsoft.KeyVault(SecretUri=https://<solutionAbbreviation>-prereqs-<environmentAbbreviation>.vault.azure.net/secrets/senderPassword/<version>)"
89+
```
90+
91+
`<version>` - Needs to be replaced with the latest version for both secrets in the prereqs keyvault.

Service/GroupMembershipManagement/Repositories.Mail/MailRepository.cs

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,17 @@ public MailRepository(GraphServiceClient graphClient, IMailConfig mailAdaptiveCa
4141

4242
public async Task SendMailAsync(EmailMessage emailMessage, Guid? runId)
4343
{
44+
if (_mailConfig.SkipEmailNotifications)
45+
{
46+
await _loggingRepository.LogMessageAsync(new LogMessage
47+
{
48+
RunId = runId,
49+
Message = "Email notifications are disabled."
50+
});
51+
52+
return;
53+
}
54+
4455
if (emailMessage is null)
4556
{
4657
throw new ArgumentNullException(nameof(emailMessage));
@@ -75,7 +86,7 @@ public async Task SendMailAsync(EmailMessage emailMessage, Guid? runId)
7586

7687
try
7788
{
78-
if(_mailConfig.GMMHasSendMailApplicationPermissions)
89+
if (_mailConfig.GMMHasSendMailApplicationPermissions)
7990
{
8091
var body = new Microsoft.Graph.Users.Item.SendMail.SendMailPostRequestBody
8192
{
@@ -139,8 +150,8 @@ public async Task<Message> GetAdaptiveCardMessage(EmailMessage emailMessage)
139150

140151
string groupId = emailMessage?.AdditionalContentParams[0];
141152
string destinationGroupName = string.IsNullOrEmpty(emailMessage?.DestinationGroupName) ? "" : emailMessage.DestinationGroupName;
142-
var urlSetting = await _settingsRepository.GetSettingByKeyAsync(SettingKey.UIUrl);
143-
var dashboardUrlSetting = await _settingsRepository.GetSettingByKeyAsync(SettingKey.DashboardUrl);
153+
var urlSetting = await _settingsRepository.GetSettingByKeyAsync(SettingKey.UIUrl);
154+
var dashboardUrlSetting = await _settingsRepository.GetSettingByKeyAsync(SettingKey.DashboardUrl);
144155

145156
string UIUrl = urlSetting?.SettingValue ?? "";
146157
string dashboardUrl = dashboardUrlSetting?.SettingValue ?? "";

0 commit comments

Comments
 (0)