diff --git a/src/Senders/FluentEmail.SendGrid/IFluentEmailExtensions.cs b/src/Senders/FluentEmail.SendGrid/IFluentEmailExtensions.cs new file mode 100644 index 00000000..459acaa0 --- /dev/null +++ b/src/Senders/FluentEmail.SendGrid/IFluentEmailExtensions.cs @@ -0,0 +1,18 @@ +using FluentEmail.Core; +using FluentEmail.Core.Models; +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading.Tasks; + +namespace FluentEmail.SendGrid +{ + public static class IFluentEmailExtensions + { + public static async Task SendWithTemplateAsync(this IFluentEmail email, string templateId, object templateData) + { + var sendGridSender = email.Sender as ISendGridSender; + return await sendGridSender.SendWithTemplateAsync(email, templateId, templateData); + } + } +} diff --git a/src/Senders/FluentEmail.SendGrid/ISendGridSender.cs b/src/Senders/FluentEmail.SendGrid/ISendGridSender.cs new file mode 100644 index 00000000..3dd989f4 --- /dev/null +++ b/src/Senders/FluentEmail.SendGrid/ISendGridSender.cs @@ -0,0 +1,27 @@ +using FluentEmail.Core; +using FluentEmail.Core.Interfaces; +using FluentEmail.Core.Models; +using SendGrid; +using SendGrid.Helpers.Mail; +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace FluentEmail.SendGrid +{ + public interface ISendGridSender : ISender + { + /// + /// SendGrid specific extension method that allows you to use a template instead of a message body. + /// For more information, see: https://sendgrid.com/docs/ui/sending-email/how-to-send-an-email-with-dynamic-transactional-templates/. + /// + /// Fluent email. + /// SendGrid template ID. + /// SendGrid template data. + /// Optional cancellation token. + /// A SendResponse object. + Task SendWithTemplateAsync(IFluentEmail email, string templateId, object templateData, CancellationToken? token = null); + } +} diff --git a/src/Senders/FluentEmail.SendGrid/SendGridSender.cs b/src/Senders/FluentEmail.SendGrid/SendGridSender.cs index f421b0be..c0fb9b11 100644 --- a/src/Senders/FluentEmail.SendGrid/SendGridSender.cs +++ b/src/Senders/FluentEmail.SendGrid/SendGridSender.cs @@ -13,7 +13,7 @@ namespace FluentEmail.SendGrid { - public class SendGridSender : ISender + public class SendGridSender : ISendGridSender { private readonly string _apiKey; private readonly bool _sandBoxMode; @@ -30,8 +30,41 @@ public SendResponse Send(IFluentEmail email, CancellationToken? token = null) public async Task SendAsync(IFluentEmail email, CancellationToken? token = null) { - var sendGridClient = new SendGridClient(_apiKey); + var mailMessage = await BuildSendGridMessage(email); + + if (email.Data.IsHtml) + { + mailMessage.HtmlContent = email.Data.Body; + } + else + { + mailMessage.PlainTextContent = email.Data.Body; + } + + if (!string.IsNullOrEmpty(email.Data.PlaintextAlternativeBody)) + { + mailMessage.PlainTextContent = email.Data.PlaintextAlternativeBody; + } + + var sendResponse = await SendViaSendGrid(mailMessage, token); + + return sendResponse; + } + public async Task SendWithTemplateAsync(IFluentEmail email, string templateId, object templateData, CancellationToken? token = null) + { + var mailMessage = await BuildSendGridMessage(email); + + mailMessage.SetTemplateId(templateId); + mailMessage.SetTemplateData(templateData); + + var sendResponse = await SendViaSendGrid(mailMessage, token); + + return sendResponse; + } + + private async Task BuildSendGridMessage(IFluentEmail email) + { var mailMessage = new SendGridMessage(); mailMessage.SetSandBoxMode(_sandBoxMode); @@ -57,7 +90,10 @@ public async Task SendAsync(IFluentEmail email, CancellationToken? mailMessage.AddHeaders(email.Data.Headers.ToDictionary(kvp => kvp.Key, kvp => kvp.Value)); } - mailMessage.Categories = email.Data.Tags.ToList(); + if(email.Data.Tags != null && email.Data.Tags.Any()) + { + mailMessage.Categories = email.Data.Tags.ToList(); + } if (email.Data.IsHtml) { @@ -94,11 +130,6 @@ public async Task SendAsync(IFluentEmail email, CancellationToken? break; } - if (!string.IsNullOrEmpty(email.Data.PlaintextAlternativeBody)) - { - mailMessage.PlainTextContent = email.Data.PlaintextAlternativeBody; - } - if (email.Data.Attachments.Any()) { foreach (var attachment in email.Data.Attachments) @@ -109,6 +140,12 @@ public async Task SendAsync(IFluentEmail email, CancellationToken? } } + return mailMessage; + } + + private async Task SendViaSendGrid(SendGridMessage mailMessage, CancellationToken? token = null) + { + var sendGridClient = new SendGridClient(_apiKey); var sendGridResponse = await sendGridClient.SendEmailAsync(mailMessage, token.GetValueOrDefault()); var sendResponse = new SendResponse(); diff --git a/test/FluentEmail.Core.Tests/SendGridSenderTests.cs b/test/FluentEmail.Core.Tests/SendGridSenderTests.cs index 803f21bc..95867f07 100644 --- a/test/FluentEmail.Core.Tests/SendGridSenderTests.cs +++ b/test/FluentEmail.Core.Tests/SendGridSenderTests.cs @@ -42,6 +42,27 @@ public async Task CanSendEmail() Assert.IsTrue(response.Successful); } + [Test, Ignore("No sendgrid credentials")] + public async Task CanSendTemplateEmail() + { + const string subject = "SendMail Test"; + const string templateId = "123456-insert-your-own-id-here"; + object templateData = new + { + Name = toName, + ArbitraryValue = "The quick brown fox jumps over the lazy dog." + }; + + var email = Email + .From(fromEmail, fromName) + .To(toEmail, toName) + .Subject(subject); + + var response = await email.SendWithTemplateAsync(templateId, templateData); + + Assert.IsTrue(response.Successful); + } + [Test, Ignore("No sendgrid credentials")] public async Task CanSendEmailWithReplyTo() {