Stefan Holm Olsen

Send Optimizely notifications with SendGrid API, not SMTP

If your Optimizely site already sends transaction emails through an email platform API, why not do the same with Optimizely notifications?

When Optimizely CMS sends emails with notifications and Forms submissions, it uses the default SMTP connection. If none is configured, no email is sent. In Optimizely DXP a SendGrid account is normally used with a regular SMTP connection.

But why not use the SendGrid Web API instead of SMTP? It is slightly quicker and more modern.

A simple integration

Luckily, Optimizely has made the mail sender in a way that can very easily be replaced.

First, we need to install the official SendGrid NuGet package:

dotnet add package SendGrid

Then we need a new class to implement the ISmtpClient interface:

using System.Linq;
using System.Threading.Tasks;
using EPiServer.Notification.Internal;
using MimeKit;
using SendGrid;
using SendGrid.Helpers.Mail;
 
namespace DemoSite.Notifications;
 
public class SendGridSender : ISmtpClient
{
    public async Task SendAsync(MimeMessage message)
    {
        var from = message.From.OfType<MailboxAddress>().First();
 
        // TODO: Find your SendGrid API key and pass it here.
        var sendGridClient = new SendGridClient("Your API key");
 
        var sendGridMessage = new SendGridMessage
        {
            From = new EmailAddress(from.Address, from.Name),
            Subject = message.Subject,
            HtmlContent = message.HtmlBody,
            PlainTextContent = message.TextBody
        };
 
        sendGridMessage
.AddTos(message.To.OfType<MailboxAddress>()
.Select(x => new EmailAddress(x.Address, x.Name))
.ToList());
 
        await sendGridClient.SendEmailAsync(sendGridMessage);
    }
}

And finally, an initialization module to register the new implementation instead of the built-in one. Like this:

using EPiServer.Framework;
using EPiServer.Framework.Initialization;
using EPiServer.Initialization.Internal;
using EPiServer.Notification.Internal;
using EPiServer.ServiceLocation;
 
namespace DemoSite.Notifications;
 
[ModuleDependency(typeof(QueryableNotificationUsersInitialization))]
public class NotificationInitialization : IConfigurableModule
{
  public void ConfigureContainer(ServiceConfigurationContext context) =>
context.Services.AddTransient(typeof(ISmtpClient), _ => new SendGridSender());
 
    public void Initialize(InitializationEngine context) { }
 
    public void Uninitialize(InitializationEngine context) { }
}

Whenever Optimizely needs to send an email, it will use your SendGrid account using their Web API.

This trick can also be applied with other mail platform APIs, like Mandrill, Mailgun, Hubspot and others. Even Gmail and Outlook can be used.