Skip to content

Commit

Permalink
Added MicrosoftGraph implementation for OAuth. (#170)
Browse files Browse the repository at this point in the history
  • Loading branch information
Thijs153 authored Dec 17, 2024
1 parent 6cebe58 commit 85e510f
Show file tree
Hide file tree
Showing 6 changed files with 134 additions and 0 deletions.
7 changes: 7 additions & 0 deletions VirtoCommerce.NotificationsModule.sln
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VirtoCommerce.Notifications
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "VirtoCommerce.NotificationsModule.Data.PostgreSql", "src\VirtoCommerce.NotificationsModule.Data.PostgreSql\VirtoCommerce.NotificationsModule.Data.PostgreSql.csproj", "{21509C88-133B-4375-B14F-F7CCAE90125D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VirtoCommerce.NotificationsModule.MicrosoftGraph", "src\VirtoCommerce.NotificationsModule.MicrosoftGraph\VirtoCommerce.NotificationsModule.MicrosoftGraph.csproj", "{F19BBFE0-BEB3-4ED3-95F7-833EBA2679FB}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -99,6 +101,10 @@ Global
{21509C88-133B-4375-B14F-F7CCAE90125D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{21509C88-133B-4375-B14F-F7CCAE90125D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{21509C88-133B-4375-B14F-F7CCAE90125D}.Release|Any CPU.Build.0 = Release|Any CPU
{F19BBFE0-BEB3-4ED3-95F7-833EBA2679FB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F19BBFE0-BEB3-4ED3-95F7-833EBA2679FB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F19BBFE0-BEB3-4ED3-95F7-833EBA2679FB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F19BBFE0-BEB3-4ED3-95F7-833EBA2679FB}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand All @@ -118,6 +124,7 @@ Global
{E1219855-4C36-4C0A-BAAD-DEF7848C324E} = {EC6E4F2D-850E-44B1-9E77-4D1A8F830A19}
{5E1291F9-197A-4FD7-9999-B07AC284172F} = {EC6E4F2D-850E-44B1-9E77-4D1A8F830A19}
{21509C88-133B-4375-B14F-F7CCAE90125D} = {EC6E4F2D-850E-44B1-9E77-4D1A8F830A19}
{F19BBFE0-BEB3-4ED3-95F7-833EBA2679FB} = {EC6E4F2D-850E-44B1-9E77-4D1A8F830A19}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {EF86C9C2-2D08-4D54-BDB2-9529400059E6}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
using System;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Azure.Identity;
using Microsoft.Extensions.Options;
using Microsoft.Graph;
using Microsoft.Graph.Models;
using Microsoft.Graph.Users.Item.SendMail;
using VirtoCommerce.NotificationsModule.Core.Exceptions;
using VirtoCommerce.NotificationsModule.Core.Model;
using VirtoCommerce.NotificationsModule.Core.Services;
using VirtoCommerce.Platform.Core.Common;

namespace VirtoCommerce.NotificationsModule.MicrosoftGraph;

public class MicrosoftGraphEmailNotificationMessageSender(
IOptions<MicrosoftGraphSenderOptions> microsoftGraphOptions,
IOptions<EmailSendingOptions> emailSendingOptions)
: INotificationMessageSender
{
public const string Name = "MicrosoftGraph";

private readonly MicrosoftGraphSenderOptions _microsoftGraphOptions = microsoftGraphOptions.Value;
private readonly EmailSendingOptions _emailSendingOptions = emailSendingOptions.Value;

public virtual bool CanSend(NotificationMessage message) => message is EmailNotificationMessage;

public async Task SendNotificationAsync(NotificationMessage message)
{
var emailNotificationMessage = message as EmailNotificationMessage
?? throw new ArgumentException($"The message is not {nameof(EmailNotificationMessage)} type");

try
{
var graphMessage = new Message
{
Subject = emailNotificationMessage.Subject,
Body = new ItemBody { ContentType = BodyType.Html, Content = emailNotificationMessage.Body },
From = NewRecipient(emailNotificationMessage.From ?? _emailSendingOptions.DefaultSender),
ToRecipients = [NewRecipient(emailNotificationMessage.To)],
CcRecipients = emailNotificationMessage.CC?.Select(NewRecipient).ToList(),
BccRecipients = emailNotificationMessage.BCC?.Select(NewRecipient).ToList()
};

if (!emailNotificationMessage.Attachments.IsNullOrEmpty())
{
graphMessage.Attachments ??= [];
foreach (var attachment in emailNotificationMessage.Attachments)
{
graphMessage.Attachments.Add(new FileAttachment
{
ContentType = attachment.MimeType,
Name = attachment.FileName,
Size = Convert.ToInt32(attachment.Size),
ContentBytes = await File.ReadAllBytesAsync(attachment.FileName),
});
}
}

var request = new SendMailPostRequestBody { SaveToSentItems = false, Message = graphMessage };

var options = new TokenCredentialOptions { AuthorityHost = AzureAuthorityHosts.AzurePublicCloud };
var clientSecretCredential = new ClientSecretCredential(
_microsoftGraphOptions.TenantId,
_microsoftGraphOptions.ApplicationId,
_microsoftGraphOptions.SecretValue,
options
);
var scopes = new[] { "https://graph.microsoft.com/.default" };

var microsoftGraphClient = new GraphServiceClient(clientSecretCredential, scopes);
await microsoftGraphClient.Users[emailNotificationMessage.From].SendMail.PostAsync(request);
}
catch (Exception ex)
{
throw new SentNotificationException(ex);
}
}

private static Recipient NewRecipient(string emailAddress) => new()
{
EmailAddress = new EmailAddress { Address = emailAddress }
};
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace VirtoCommerce.NotificationsModule.MicrosoftGraph;

public class MicrosoftGraphSenderOptions
{
public string ApplicationId { get; set; }

public string TenantId { get; set; }

public string SecretValue { get; set; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<noWarn>1591</noWarn>
<IsPackable>True</IsPackable>
<PublishRepositoryUrl>true</PublishRepositoryUrl>
<EmbedUntrackedSources>true</EmbedUntrackedSources>
<IncludeSymbols>true</IncludeSymbols>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Azure.Core" Version="1.41.0" />
<PackageReference Include="Azure.Identity" Version="1.12.1" />
<PackageReference Include="Microsoft.Graph" Version="5.56.0" />
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="8.0.0" PrivateAssets="All" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\VirtoCommerce.NotificationsModule.Core\VirtoCommerce.NotificationsModule.Core.csproj" />
</ItemGroup>

</Project>
7 changes: 7 additions & 0 deletions src/VirtoCommerce.NotificationsModule.Web/Module.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
using VirtoCommerce.NotificationsModule.Data.SqlServer;
using VirtoCommerce.NotificationsModule.LiquidRenderer;
using VirtoCommerce.NotificationsModule.LiquidRenderer.Filters;
using VirtoCommerce.NotificationsModule.MicrosoftGraph;
using VirtoCommerce.NotificationsModule.SendGrid;
using VirtoCommerce.NotificationsModule.Smtp;
using VirtoCommerce.NotificationsModule.TemplateLoader.FileSystem;
Expand Down Expand Up @@ -104,6 +105,12 @@ public void Initialize(IServiceCollection serviceCollection)
serviceCollection.AddTransient<INotificationMessageSender, SendGridEmailNotificationMessageSender>();
break;
}
case MicrosoftGraphEmailNotificationMessageSender.Name:
{
serviceCollection.AddOptions<MicrosoftGraphSenderOptions>().Bind(Configuration.GetSection($"Notifications:{MicrosoftGraphEmailNotificationMessageSender.Name}")).ValidateDataAnnotations();
serviceCollection.AddTransient<INotificationMessageSender, MicrosoftGraphEmailNotificationMessageSender>();
break;
}
}

serviceCollection.AddOptions<SmsSendingOptions>().Bind(Configuration.GetSection("Notifications")).ValidateDataAnnotations();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
<ProjectReference Include="..\VirtoCommerce.NotificationsModule.Data.SqlServer\VirtoCommerce.NotificationsModule.Data.SqlServer.csproj" />
<ProjectReference Include="..\VirtoCommerce.NotificationsModule.Data\VirtoCommerce.NotificationsModule.Data.csproj" />
<ProjectReference Include="..\VirtoCommerce.NotificationsModule.LiquidRenderer\VirtoCommerce.NotificationsModule.LiquidRenderer.csproj" />
<ProjectReference Include="..\VirtoCommerce.NotificationsModule.MicrosoftGraph\VirtoCommerce.NotificationsModule.MicrosoftGraph.csproj" />
<ProjectReference Include="..\VirtoCommerce.NotificationsModule.SendGrid\VirtoCommerce.NotificationsModule.SendGrid.csproj" />
<ProjectReference Include="..\VirtoCommerce.NotificationsModule.Smtp\VirtoCommerce.NotificationsModule.Smtp.csproj" />
<ProjectReference Include="..\VirtoCommerce.NotificationsModule.TemplateLoader.FileSystem\VirtoCommerce.NotificationsModule.TemplateLoader.FileSystem.csproj" />
Expand Down

0 comments on commit 85e510f

Please sign in to comment.