Sending Emails in .NET Core Applications
Sending emails are common in applications. For example, when user registers, we need to send account activation emails. This post summarize the approaches we can use to send emails in .NET Core 1.x and 2.x.
.NET Core 1.x
.NET Core 1.x is based on .NET Standard 1.x libraries. SmtpClient is not implemented yet. Thus we had to use third party libraries to send emails. For example, MailKit. In Azure, you can also choose SendGrid to send emails.
MailKit
Mailkit project is available in GitHub.
Sample Code
/// <summary>
/// Send email
/// </summary>
/// <param name="sender"></param>
/// <param name="recepients"></param>
/// <param name="subject"></param>
/// <param name="body"></param>
/// <param name="isHtml"></param>
/// <param name="config"></param>
/// <returns></returns>
public static async Task<(bool success, string errorMsg)> SendEmailAsync(MailboxAddress sender, MailboxAddress[] recepients, string subject, string body, bool isHtml = true, SmtpConfig config = null)
{
MimeMessage message = new MimeMessage();
message.From.Add(sender);
message.To.AddRange(recepients);
message.Subject = subject;
message.Body = isHtml ? new BodyBuilder { HtmlBody = body }.ToMessageBody() : new TextPart("plain") { Text = body };
try
{
if (config == null)
if (Configuration != null)
config = Configuration;
using (var client = new SmtpClient())
{
if (!config.UseSSL)
client.ServerCertificateValidationCallback = (object sender2, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) => true;
await client.ConnectAsync(config.Host, config.Port, config.UseSSL).ConfigureAwait(false);
client.AuthenticationMechanisms.Remove("XOAUTH2");
if (!string.IsNullOrWhiteSpace(config.Username))
await client.AuthenticateAsync(config.Username, config.Password).ConfigureAwait(false);
await client.SendAsync(message).ConfigureAwait(false);
await client.DisconnectAsync(true).ConfigureAwait(false);
}
return (true, null);
}
catch (Exception ex)
{
if (LoggerFactory != null)
LoggerFactory.CreateLogger<EmailHelpers>().LogError(LoggingEvents.SEND_EMAIL_ERROR, ex, "An error occurred while sending email");
return (false, ex.Message);
}
}
.NET Core 2.x
SmtpClient is already migrated to .NET Standard 2. Thus we can use built-in library to send emails.
Sample Code
/// <summary>
/// Send email
/// </summary>
/// <param name="sender"></param>
/// <param name="recepients"></param>
/// <param name="subject"></param>
/// <param name="body"></param>
/// <param name="isHtml"></param>
/// <param name="config"></param>
/// <returns></returns>
public async Task<(bool success, string errorMsg)> SendEmailAsync(MailAddress sender, MailAddress[] recepients, string subject, string body, bool isHtml = true, MailAddress[] bccList = null)
{
MailMessage message = new MailMessage
{
From = sender
};
message.Subject = subject;
message.IsBodyHtml = isHtml;
message.Body = body;
message.SubjectEncoding = Encoding.UTF8;
message.BodyEncoding = Encoding.UTF8;
foreach (var recepient in recepients)
message.To.Add(recepient);
if (bccList != null)
{
foreach (var recepient in recepients)
message.Bcc.Add(recepient);
}
var emailMessage = AddEmailMessageToStore(message);
try
{
using (var client = new SmtpClient())
{
var config = configService.EmailConfig;
if (config.EnableSSl)
client.EnableSsl = true;
client.Host = config.Host;
client.Port = config.Port;
client.DeliveryMethod = SmtpDeliveryMethod.Network;
client.Credentials = new NetworkCredential(config.UserName, rootConfig[config.PasswordConfigurationName]);
await client.SendMailAsync(message);
emailMessage.IsSent = true;
emailMessage.IsSuccessful = true;
emailMessage.DateSent = DateTime.Now;
emailMessage.DateModified = DateTime.Now;
SaveEmailMessage(emailMessage);
}
return (true, null);
}
catch (Exception ex)
{
if (loggerFactory != null)
loggerFactory.CreateLogger<EmailSenderService>().LogError(LoggingEvents.SEND_EMAIL_ERROR, ex, "An error occurred while sending email");
emailMessage.IsSent = false;
emailMessage.IsSuccessful = false;
emailMessage.Comment = ex.ToString();
emailMessage.DateModified = DateTime.Now;
SaveEmailMessage(emailMessage);
return (false, ex.Message);
}
}
.NET Core 3.x
Refer to .NET Core 2.x examples.
Other approaches
Many email service provider also provides direct APIs or SDK that can be used to sent email directly without using SMTP.
For instance, Microsoft 365 or Office 365 users can use Microsoft Graph APIs to send emails directly once the client is authenticated correctly.