SendGrid integration
parent
924824437f
commit
991cb525f0
|
@ -28,7 +28,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Correo.NetSmtpClient", "src
|
|||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Correo.Abstractions", "src\Correo.Abstractions\Correo.Abstractions.csproj", "{ED8048DC-8509-4085-97F0-F9D9A59A689A}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Correo.MailKit", "src\Correo.MailKit\Correo.MailKit.csproj", "{325B77E1-D752-4578-8BF7-793905C38DCD}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Correo.MailKit", "src\Correo.MailKit\Correo.MailKit.csproj", "{325B77E1-D752-4578-8BF7-793905C38DCD}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Correo.SendGrid", "src\Correo.SendGrid\Correo.SendGrid.csproj", "{1457426A-CD47-4201-BE3C-A40B38FCB1FA}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
|
@ -64,6 +66,10 @@ Global
|
|||
{325B77E1-D752-4578-8BF7-793905C38DCD}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{325B77E1-D752-4578-8BF7-793905C38DCD}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{325B77E1-D752-4578-8BF7-793905C38DCD}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{1457426A-CD47-4201-BE3C-A40B38FCB1FA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{1457426A-CD47-4201-BE3C-A40B38FCB1FA}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{1457426A-CD47-4201-BE3C-A40B38FCB1FA}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{1457426A-CD47-4201-BE3C-A40B38FCB1FA}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
@ -76,6 +82,7 @@ Global
|
|||
{76793477-8219-4FFB-AA08-3F2224EC4968} = {245E2FBE-DFDF-40B4-94B7-5DDA216E58AD}
|
||||
{ED8048DC-8509-4085-97F0-F9D9A59A689A} = {245E2FBE-DFDF-40B4-94B7-5DDA216E58AD}
|
||||
{325B77E1-D752-4578-8BF7-793905C38DCD} = {245E2FBE-DFDF-40B4-94B7-5DDA216E58AD}
|
||||
{1457426A-CD47-4201-BE3C-A40B38FCB1FA} = {245E2FBE-DFDF-40B4-94B7-5DDA216E58AD}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {86FCF989-26FC-41E9-8A23-9485606D619D}
|
||||
|
|
|
@ -9,5 +9,6 @@
|
|||
<MediatRPackageVersion>9.0.0</MediatRPackageVersion>
|
||||
<NBBPackageVersion>6.0.30</NBBPackageVersion>
|
||||
<MailKitPackageVersion>3.4.3</MailKitPackageVersion>
|
||||
<SendGridPackageVersion>9.28.1</SendGridPackageVersion>
|
||||
</PropertyGroup>
|
||||
</Project>
|
|
@ -0,0 +1,18 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="$(MicrosoftExtensionsPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="$(MicrosoftExtensionsPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="$(MicrosoftExtensionsPackageVersion)" />
|
||||
<PackageReference Include="SendGrid" Version="$(SendGridPackageVersion)" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Correo.Abstractions\Correo.Abstractions.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
|
@ -0,0 +1,16 @@
|
|||
using Correo.Abstractions;
|
||||
using Correo.SendGrid.Models;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace Correo.SendGrid
|
||||
{
|
||||
public static class DependencyInjectionExtensions
|
||||
{
|
||||
public static void AddSendGridService(this IServiceCollection services, IConfigurationSection configuration)
|
||||
{
|
||||
services.Configure<SendGridOptions>(configuration);
|
||||
services.AddTransient<IMailer, SendGridService>();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
using Correo.Abstractions;
|
||||
using SendGrid.Helpers.Mail;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Correo.SendGrid.Extensions
|
||||
{
|
||||
internal static class ModelExtensions
|
||||
{
|
||||
private static EmailAddress ToEmailAddress(this EmailMessage.MailAddress address)
|
||||
=> new EmailAddress(address.Address, address.DisplayName);
|
||||
|
||||
private static List<EmailAddress> ToEmailAddressList(this IEnumerable<EmailMessage.MailAddress> addresses)
|
||||
=> addresses.Select(z => new EmailAddress(z.Address, z.DisplayName)).ToList();
|
||||
|
||||
public static SendGridMessage ToSendGridMessage(this EmailMessage message)
|
||||
{
|
||||
var subject = message.Subject;
|
||||
var plainContent = !message.IsBodyHtml ? message.Body : null;
|
||||
var htmlContent = message.IsBodyHtml ? message.Body : null;
|
||||
var from = message.From.ToEmailAddress();
|
||||
var to = message.To.First().ToEmailAddress();
|
||||
var mailMessage = MailHelper.CreateSingleEmail(from, to, subject, plainContent, htmlContent);
|
||||
|
||||
if (message.To.Count() > 1)
|
||||
{
|
||||
var tos = message.To.Skip(1).Select(z => new EmailAddress(z.Address, z.DisplayName)).ToList();
|
||||
mailMessage.AddTos(tos);
|
||||
}
|
||||
|
||||
if (message.Cc != null && message.Cc.Any())
|
||||
mailMessage.AddCcs(message.Cc.ToEmailAddressList());
|
||||
|
||||
if (message.Bcc != null && message.Bcc.Any())
|
||||
mailMessage.AddBccs(message.Bcc.ToEmailAddressList());
|
||||
|
||||
return mailMessage;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
namespace Correo.SendGrid.Models
|
||||
{
|
||||
internal record Error
|
||||
{
|
||||
public string Message { get; init; }
|
||||
public string Field { get; init; }
|
||||
public string Help { get; init; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
namespace Correo.SendGrid.Models
|
||||
{
|
||||
internal record SendGridOptions
|
||||
{
|
||||
public string ApiKey { get; init; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
using Correo.Abstractions;
|
||||
using Correo.Abstractions.Extensions;
|
||||
using Correo.SendGrid.Extensions;
|
||||
using Correo.SendGrid.Models;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Newtonsoft.Json;
|
||||
using SendGrid;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Correo.SendGrid
|
||||
{
|
||||
internal class SendGridService : IMailer
|
||||
{
|
||||
private readonly IOptions<SendGridOptions> _optionsAccessor;
|
||||
private readonly SendGridClient _client;
|
||||
private readonly ILogger<SendGridService> _logger;
|
||||
|
||||
public SendGridService(IOptions<SendGridOptions> optionsAccessor, ILogger<SendGridService> logger)
|
||||
{
|
||||
_optionsAccessor = optionsAccessor;
|
||||
_logger = logger;
|
||||
_client = new SendGridClient(_optionsAccessor.Value.ApiKey);
|
||||
}
|
||||
|
||||
public void SendEmail(EmailMessage message)
|
||||
{
|
||||
var mailMessage = message.ToSendGridMessage();
|
||||
_client.SendEmailAsync(mailMessage).GetAwaiter().GetResult();
|
||||
Log(message);
|
||||
}
|
||||
|
||||
public async Task SendEmailAsync(EmailMessage message, CancellationToken token = default)
|
||||
{
|
||||
var mailMessage = message.ToSendGridMessage();
|
||||
var response = await _client.SendEmailAsync(mailMessage, token);
|
||||
if (response.IsSuccessStatusCode)
|
||||
Log(message);
|
||||
else
|
||||
{
|
||||
var body = await response.DeserializeResponseBodyAsync();
|
||||
var found = body.TryGetValue("errors", out var jsonData);
|
||||
if (found)
|
||||
{
|
||||
string errorsString = Convert.ToString(jsonData);
|
||||
var errors = JsonConvert.DeserializeObject<Error[]>(errorsString);
|
||||
var errorMessage = string.Join("; ", errors.Select(z => z.Message));
|
||||
throw new Exception(errorMessage);
|
||||
}
|
||||
|
||||
throw new Exception(response.StatusCode.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
private void Log(EmailMessage message)
|
||||
=> _logger.LogInformation($"Email sent: Subject: {message.Subject}; From: {message.From.Address}; To: {message.To.Log()}; Cc: {message.Cc.Log()}; Bcc: {message.Bcc.Log()};");
|
||||
}
|
||||
}
|
|
@ -18,6 +18,7 @@
|
|||
<ProjectReference Include="..\Correo.Application\Correo.Application.csproj" />
|
||||
<ProjectReference Include="..\Correo.MailKit\Correo.MailKit.csproj" />
|
||||
<ProjectReference Include="..\Correo.NetSmtpClient\Correo.NetSmtpClient.csproj" />
|
||||
<ProjectReference Include="..\Correo.SendGrid\Correo.SendGrid.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using Correo.MailKit;
|
||||
using Correo.NetSmtpClient;
|
||||
using Correo.SendGrid;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using System;
|
||||
|
@ -8,22 +9,24 @@ namespace Correo.Extensions
|
|||
{
|
||||
public static class SmtpExtensions
|
||||
{
|
||||
public static void AddSmtpClient(this IServiceCollection services, IConfiguration configuration)
|
||||
public static void AddSmtpService(this IServiceCollection services, IConfiguration configuration)
|
||||
{
|
||||
var configSection = configuration.GetSection("SmtpClient");
|
||||
var mediator = configSection.GetValue("Mediator", ".NET");
|
||||
|
||||
var mediator = configuration.GetValue("SmtpMediator", ".NET");
|
||||
if (mediator.Equals(".NET", StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
services.AddNetSmtpClient(configSection);
|
||||
services.AddNetSmtpClient(configuration.GetSection("SmtpClient"));
|
||||
}
|
||||
else if (mediator.Equals("MailKit", StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
services.AddMailKitSmtpClient(configSection);
|
||||
services.AddMailKitSmtpClient(configuration.GetSection("SmtpClient"));
|
||||
}
|
||||
else if (mediator.Equals("SendGrid", StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
services.AddSendGridService(configuration.GetSection("SmtpService"));
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new NotImplementedException($"SmtpClient:Mediator={mediator} is not implemented.");
|
||||
throw new NotImplementedException($"SmtpMediator '{mediator}' is not implemented.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@ namespace Correo.Extensions
|
|||
services.AddMessaging(configuration);
|
||||
|
||||
// Add SMTP client
|
||||
services.AddSmtpClient(configuration);
|
||||
services.AddSmtpService(configuration);
|
||||
|
||||
// Application services
|
||||
services.AddApplicationServices(configuration);
|
||||
|
|
|
@ -29,8 +29,8 @@
|
|||
"Address": "noreply@homelab.com",
|
||||
"Name": "HomeLab"
|
||||
},
|
||||
"SmtpMediator": ".NET", //.NET, MailKit, SendGrid
|
||||
"SmtpClient": {
|
||||
"Mediator": ".NET", //.NET, MailKit
|
||||
"Server": "smtp.gmail.com",
|
||||
"Port": "587",
|
||||
"UseAuthentication": true,
|
||||
|
@ -41,5 +41,8 @@
|
|||
},
|
||||
"EnableSsl": true,
|
||||
"TrustServer": false
|
||||
},
|
||||
"SmtpService": {
|
||||
"ApiKey": "xxxxxxxxxxx"
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue