Problem
How to send emails in .NET Core using Azure SendGrid
service.
Solution
Create a class library and add NuGet package: Sendgrid
.
Add a class to encapsulate settings and server response:
public class AzureEmailSettings
{
public AzureEmailSettings(string apiKey)
{
if (string.IsNullOrEmpty(apiKey))
throw new ArgumentException("Api Key must be set");
this.ApiKey = apiKey;
}
public string ApiKey { get; }
}
public class ResponseMessage
{
public ResponseMessage(string statusCode)
{
this.StatusCode = statusCode;
}
public string StatusCode { get; }
}
Add a class to encapsulate an email message (see also the previous post on builder pattern):
public sealed class EmailMessage
{
private readonly List<string> to;
private readonly List<string> cc;
private readonly List<string> bcc;
private readonly List<string> attachments;
public EmailMessage(string subject, string from, string body, List<string> to,
List<string> cc, List<string> bcc, List<string> attachments)
{
if (string.IsNullOrEmpty(subject))
throw new ArgumentException("Subject must be set");
if (string.IsNullOrEmpty(from))
throw new ArgumentException("From must be set");
if (string.IsNullOrEmpty(body))
throw new ArgumentException("Body must be set");
if (to.Count == 0)
throw new ArgumentException("At least one To must be set");
this.Subject = subject;
this.From = from;
this.Body = body;
this.to = to;
this.cc = cc;
this.bcc = bcc;
this.attachments = attachments;
}
public string Subject { get; }
public string From { get; }
public string Body { get; }
public IReadOnlyList<string> To => to;
public IReadOnlyList<string> CC => cc;
public IReadOnlyList<string> BCC => bcc;
public IReadOnlyList<string> Attachments => attachments;
}
Add a class to wrap functionality of sending email messages:
public class AzureEmailSender : IAzureEmailSender
{
private readonly AzureEmailSettings settings;
public AzureEmailSender(AzureEmailSettings settings)
{
this.settings = settings;
}
public async Task<ResponseMessage> SendAsync(EmailMessage message)
{
var msg = new SendGridMessage();
msg.Subject = message.Subject;
msg.From = new EmailAddress(message.From);
msg.PlainTextContent = message.Body;
msg.AddTos(message.To.Select(s => new EmailAddress(s)).ToList());
if (message.CC.Count > 0)
msg.AddCcs(message.CC.Select(s => new EmailAddress(s)).ToList());
if (message.BCC.Count > 0)
msg.AddBccs(message.BCC.Select(s => new EmailAddress(s)).ToList());
if (message.Attachments.Count > 0)
msg.AddAttachments(message.Attachments.Select(s => new Attachment
{
Filename = s,
Content = Convert.ToBase64String(System.IO.File.ReadAllBytes(s))
}).ToList());
var client = new SendGridClient(this.settings.ApiKey);
var response = await client.SendEmailAsync(msg);
return new ResponseMessage(response.StatusCode.ToString());
}
}
To use the above class:
var message = EmailMessageBuilder
.Init()
.AddSubject(subject)
.AddFrom(from)
.AddBody(body)
.AddTo(to)
.Build();
IAzureEmailSender sender = new AzureEmailSender(new AzureEmailSettings(apiKey));
var response = sender.SendAsync(message).Result;
Console.WriteLine(response.StatusCode);
Note: The sample code includes the builder for email message.
Discussion
The sample code will require you to setup Azure account and SendGrid
account. Instructions for these could be found here.
You’ll also need API Key, which can be created here using your Azure SendGrid
username and password. More details can be found at this link.