How to send ASP.NET Core Identity emails with Twilio SendGrid
Tags: dotnet, aspnet, csharp, sendgrid
Published: 2022-03-16 00:59:41

---
title: How to send ASP.NET Core Identity emails with Twilio SendGrid
published: true
date: 2022-03-15 00:00:00 UTC
tags: dotnet, aspnet, csharp, sendgrid
canonical_url: https://www.twilio.com/blog/how-to-send-asp-net-core-identity-emails-with-twilio-sendgrid
cover_image: https://swimburger.net/media/5vvftkdj/send-asp-net-core-identity-emails-with-twilio-sendgrid-canonical.png?anchor=center&mode=crop&width=1000&height=420
---

**This blog post was written for [Twilio](https://www.twilio.com/) and [originally published at the Twilio blog](https://www.twilio.com/blog/how-to-send-asp-net-core-identity-emails-with-twilio-sendgrid).**

As part of [ASP.NET Identity](https://docs.microsoft.com/en-us/aspnet/identity/overview/getting-started/introduction-to-aspnet-identity), ASP.NET Core provides a bunch of features for account management, authentication, and authorization. ASP.NET Identity also sends emails to confirm email addresses and reset passwords, but it's up to you to implement how those emails are sent.

In this tutorial, you will learn how to send ASP.NET Identity emails using Twilio SendGrid.

## Prerequisites

You will need these things to follow along:

- An OS that supports .NET (Windows/macOS/Linux)
- [.NET 6 SDK](https://dotnet.microsoft.com/en-us/download/dotnet/6.0)
- A code editor or IDE (I recommend [VS Code](https://code.visualstudio.com/Download) with [the C# plugin](https://marketplace.visualstudio.com/items?itemName=ms-dotnettools.csharp), [Visual Studio](https://visualstudio.microsoft.com/), or [JetBrains Rider](https://www.jetbrains.com/rider/))
- A Twilio SendGrid account. Sign up [here](https://signup.sendgrid.com/) to send up to 100 emails per day completely free of charge.

You can find [the source code for this tutorial on GitHub](https://github.com/Swimburger/AspNetIdentityEmailsWithSendGrid). Use it if you run into any issues, or [submit an issue](https://github.com/Swimburger/AspNetIdentityEmailsWithSendGrid/issues), if you run into problems.

## Configure your SendGrid account to send emails

There are two things you need to configure before you can send emails: First, you’ll need to set up **Sender Authentication**. This will verify that you own the email address or domain that you will send emails from. Second, you’ll need to create a **SendGrid API Key** with permission to send emails.

### Sender Authentication

To quickly get started, you will use **Single Sender Verification** for this tutorial. This verifies that you own the email address that the application will send emails from. Single Sender Verification is great **for testing purposes** , but it is not recommended for production.

Twilio recommends [Domain Authentication](https://docs.sendgrid.com/ui/account-and-settings/how-to-set-up-domain-authentication/) for production environments. An authenticated domain proves to email providers that you own the domain, and removes the "via sendgrid.net" text that inbox providers would otherwise append to your from address.

To set up Single Sender Verification, click the **Settings** tab in the left menu. Once the settings tab opens, click **Sender Authentication**.

![Side-navigation with a Settings group and multiple links in the group. The link "Sender Authentication" is highlighted.](https://twilio-cms-prod.s3.amazonaws.com/images/89-OHWsJrii_pWqv99VotxeeEkTNKPHmZttC8ilbYirYRJ.width-500.png)

Then, click **Get Started** under the **Single Sender Verification** section.

![A button saying "Get Started" to verify an individual email address.](https://twilio-cms-prod.s3.amazonaws.com/images/L9gCJJ4DWFz0xFlrHe4dpbuYDLo95DtpkwQU8QS8w7I5xM.width-500.png)

This opens a form in the right-side panel. Fill out the form with your information and email address.

![A form to create a sender. The form asks for contact information including the email address that will be used to send emails from.](https://twilio-cms-prod.s3.amazonaws.com/images/z8hZb79XasAcMQokZHY5ZRYSe3Mf0vL4lRkxXFBVRs2JCO.width-500.png)

Click **Create** after filling out the form. Another panel will appear on the right, asking you to confirm your email address in your email inbox.Go to your personal email inbox, open the email from SendGrid, and click Verify Single Sender.

![An email from SendGrid with a button saying "Verify Single Sender".](https://twilio-cms-prod.s3.amazonaws.com/images/pODzYdFfTGS5tuhHgwBb4AREdyYMP9rFk3tB1BJm3tyHEo.width-500.png)

Your email address has been verified. You can now use it to send emails!

### Create a SendGrid API key to send emails

Back on the SendGrid website, click **API Keys** under the **Settings tab** , then click **Create API Key** in the top right-hand corner. This opens another form in the right-side panel. 

Give your API Key a useful name. You can assign different permissions to the API Key. For optimal security, you should only give the minimum amount of permissions that you need.

Next, click Restricted Access.

![A form to create an API Key. The form asks for a name for the key and what permissions to grant to the key.](https://twilio-cms-prod.s3.amazonaws.com/images/DTVGaWLkgiX7mXeaWEf2OST5dMg722ZKdPO8FQve19qvTR.width-500.png)

Scroll down to the **Mail Send** accordion item and click on it to reveal the permissions underneath. Drag the slider to the right for the **Mail Send** permission.

![A list of permissions that you can control using a slider bar next to each permission. The "Mail Send" accordion item is expanded to reveal the "Mail Send" permission underneath.](https://twilio-cms-prod.s3.amazonaws.com/images/iOb9SAfeX4IRe6a7YRldCs8xzKupf7oQravH9M7qd4KLpZ.width-500.png)

Scroll to the bottom of the form and click **Create & View**. The API key will now be displayed on your screen. 

You will not be able to retrieve the API key again once you leave this screen, so make sure you copy the API Key somewhere safe.

![API key is displayed to copy and store elsewhere. Key will not be shown again.](https://twilio-cms-prod.s3.amazonaws.com/images/fAo1HbK1BhAMqDaBIhFSKkIXNpvr_hBn-3bX40cJ-DD_Ef.width-500.png)

With the sender verified and the API Key created, you’re ready to write some code!

## Send Identity emails using Twilio SendGrid

You'll be running a couple commands in this tutorial, but if you prefer using an IDE, there should be equivalent actions for Visual Studio and JetBrains Rider. Open your preferred shell to follow along with the provided commands.

If you already have a web application with ASP.NET Core Identity, skip the next step. In your shell, run the following .NET CLI command to create the project:

```bash
dotnet new webapp -o WebAppIdentity -au Individual
```

This command will generate an ASP.NET Core project with Identity and put it in the _WebAppIdentity_ folder.

Then, navigate to the new project directory in your shell:

```bash
cd WebAppIdentity
```

If you would start the project now, and try to register a new account, the web application will tell you that an email sender has not been configured. Also, it will display a link that would normally be sent to your inbox, to confirm your email, to simulate the process.

![The Register confirmation page which would normally tell you to confirm your email by going to your mail inbox, but now simply provides the confirmation link on the page.](https://twilio-cms-prod.s3.amazonaws.com/images/WRtgNp00McwWUkA7F0CrPRdffdoYkY958VPw030f3xPhpP.width-500.png)

However, the real page will be shown when you register the email sender. To do this, you have to first create a class that implements the `IEmailSender` interface, and then register the class in ASP.NET Core's dependency injection container.

To do this, create a new file in the project's root directory, named _SendGridEmailSender.cs_, with the following code:

```csharp
using Microsoft.AspNetCore.Identity.UI.Services;

namespace WebAppIdentity;

public class SendGridEmailSender : IEmailSender
{
  public async Task SendEmailAsync(string toEmail, string subject, string message)
  {
    throw new NotImplementedException();
  }
}
```

The `SendGridEmailSender` implements the `IEmailSender` interface. The interface only expects you to implement one method, `SendEmailAsync`. This method will be used by ASP.NET Identity to send your emails.

To implement `SendEmailAsync` method using SendGrid, you'll first need to install the [SendGrid library for C# and .NET](https://github.com/sendgrid/sendgrid-csharp). Head back to your shell and run the following command to install the library via the [SendGrid NuGet package](https://www.nuget.org/packages/SendGrid/):

```bash
dotnet add package SendGrid
```

Update the _SendGridEmailSender.cs_ file with the following code:

```csharp
using Microsoft.AspNetCore.Identity.UI.Services;
using SendGrid;
using SendGrid.Helpers.Mail;

namespace WebAppIdentity;

public class SendGridEmailSender : IEmailSender
{
    private readonly IConfiguration configuration;
    private readonly ILogger logger;

    public SendGridEmailSender(IConfiguration configuration, ILogger<SendGridEmailSender> logger)
    {
        this.configuration = configuration;
        this.logger = logger;
    }

    public async Task SendEmailAsync(string toEmail, string subject, string message)
    {
        string sendGridApiKey = configuration["SendGridApiKey"];
        if (string.IsNullOrEmpty(sendGridApiKey))
        {
            throw new Exception("The 'SendGridApiKey' is not configured");
        }
        
        var client = new SendGridClient(sendGridApiKey);
        var msg = new SendGridMessage()
        {
            From = new EmailAddress("[YOUR_EMAIL_ADDRESS]", "[YOUR_WEBSITE_NAME]"),
            Subject = subject,
            PlainTextContent = message,
            HtmlContent = message
        };
        msg.AddTo(new EmailAddress(toEmail));

        var response = await client.SendEmailAsync(msg);
        if (response.IsSuccessStatusCode)
        {
            logger.LogInformation("Email queued successfully");
        }
        else
        {
            logger.LogError("Failed to send email");
            // Adding more information related to the failed email could be helpful in debugging failure,
            // but be careful about logging PII, as it increases the chance of leaking PII
        }
    }
}
```

Replace `[YOUR_EMAIL_ADDRESS]` with the email address you verified with SendGrid earlier, and replace `[YOUR_WEBSITE_NAME]` with any name. The name will be displayed to the recipient of the emails, so using the name of your website or service would make sense here.

To send emails with SendGrid, you'll need to get the SendGrid API key from the application's configuration, which is why `IConfiguration configuration` has been added to the constructor parameters. You'll also want to log whether the emails are sent successfully, which is why the `ILogger<SendGridEmailSender> logger` parameter has been added to the constructor.

Both of these parameters will be injected by ASP.NET Core's dependency injection container, and then stored as fields of the class.

In `SendEmailAsync`, the SendGrid API key is retrieved from the application's configuration and used to create a new `SendGridClient`. Then, a `SendGridMessage` is created, passing in all the parameters passed into the `SendGridMessage` method.  

That message is then sent using the `SendGridClient`. If the email has been submitted to SendGrid's API successfully, "Email queued successfully" will be logged, otherwise "Failed to send email" is logged as an error.

The project now expects the 'SendGridApiKey' to be configured, but it isn't yet. You could configure the API key in a variety of ways, but because it is a secret, you should avoid storing it in your source code. That's why .NET introduced the [Secret Manager tool](https://docs.microsoft.com/en-us/aspnet/core/security/app-secrets) to store secrets for local development. Initialize the Secret Manager tool for your project by running the following command:

```bash
dotnet user-secrets init
```

Run the following command to configure 'SendGridApiKey' using the Secret Manager:

```bash
dotnet user-secrets set SendGridApiKey [YOUR_SENDGRID_API_KEY]
```

Replace `[YOUR_SENDGRID_API_KEY]` with the SendGrid API key you took note of earlier.

With the API key configured, the `SendGridEmailSender` is ready to be registered. Update the _Program.cs_ file to register the `SendGridEmailSender` as a service:

```csharp
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using Microsoft.AspNetCore.Identity.UI.Services;
using WebAppIdentity;
using WebAppIdentity.Data;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
builder.Services.AddDbContext<ApplicationDbContext>(options =>
    options.UseSqlite(connectionString));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();

builder.Services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
    .AddEntityFrameworkStores<ApplicationDbContext>();
builder.Services.AddRazorPages();

builder.Services.AddTransient<IEmailSender, SendGridEmailSender>();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseMigrationsEndPoint();
}
else
{
    app.UseExceptionHandler("/Error");
    // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();

app.UseAuthentication();
app.UseAuthorization();

app.MapRazorPages();

app.Run();
```

That's it! 

Save both files and start your project using the .NET CLI:

```bash
dotnet run
```

Take note of the console logs and you’ll see a line with the format: `Now listening on: https://localhost:XXXX`. Navigate to your web application with this URL in a web browser, click the Register link, fill out the form, and click **Register**. The next page will tell you to check your email to confirm your account.

Open your email inbox, open the "Confirm your email" email, and click the link in the email to confirm your email address. By clicking the link, your web application will be opened in a new tab and say "Thank you for confirming your email.".

![An email to confirm your email containing a confirmation link.](https://twilio-cms-prod.s3.amazonaws.com/images/EJS7pYQgQsWzQWa5stHGseleO688T5_DNzegAgPVeq0R7O.width-500.png)

Great job!

Alternatively, you can [send emails using SMTP and SendGrid SMTP relay, as shown in this tutorial](https://www.twilio.com/blog/send-email-in-csharp-dotnet-using-smtp-and-sendgrid).

Stop the project by pressing `ctrl + c` in your shell.

## Add SendGridClient to ASP.NET's Dependency Injection container

SendGrid offers an additional package to easily integrate SendGrid into ASP.NET's dependency injection (DI) container. Instead of creating the `SendGridClient` manually in the `SendGridEmailSender` class, with this package, you can let the DI container inject an instance of `ISendGridClient` into the constructor. 

Add the [SendGrid dependency injection NuGet package](https://www.nuget.org/packages/SendGrid.Extensions.DependencyInjection/) using the following command:

```bash
dotnet add package SendGrid.Extensions.DependencyInjection
```

Next, register SendGrid as a service using the `builder.Services.AddSendGrid` method, by updating the _Program.cs_ file as below:

```csharp
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using Microsoft.AspNetCore.Identity.UI.Services;
using SendGrid.Extensions.DependencyInjection;
using WebAppIdentity;
using WebAppIdentity.Data;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
builder.Services.AddDbContext<ApplicationDbContext>(options =>
    options.UseSqlite(connectionString));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();

builder.Services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
    .AddEntityFrameworkStores<ApplicationDbContext>();
builder.Services.AddRazorPages();

builder.Services.AddSendGrid(options =>
    options.ApiKey = builder.Configuration.GetValue<string>("SendGridApiKey")
                     ?? throw new Exception("The 'SendGridApiKey' is not configured")
);
builder.Services.AddTransient<IEmailSender, SendGridEmailSender>();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseMigrationsEndPoint();
}
else
{
    app.UseExceptionHandler("/Error");
    // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();

app.UseAuthentication();
app.UseAuthorization();

app.MapRazorPages();

app.Run();
```

Now, in the _SendGridEmailSender.cs_ file, you can delete the lines to create the `SendGridClient` and accept an instance of `ISendGridClient` via the constructor instead. Here's what the updated file looks like:

```csharp
using Microsoft.AspNetCore.Identity.UI.Services;
using SendGrid;
using SendGrid.Helpers.Mail;

namespace WebAppIdentity;

public class SendGridEmailSender : IEmailSender
{
    private readonly ISendGridClient sendGridClient;
    private readonly ILogger logger;

    public SendGridEmailSender(ISendGridClient sendGridClient, ILogger<SendGridEmailSender> logger)
    {
        this.sendGridClient = sendGridClient;
        this.logger = logger;
    }

    public async Task SendEmailAsync(string toEmail, string subject, string message)
    {
        var msg = new SendGridMessage()
        {
            From = new EmailAddress("[YOUR_EMAIL_ADDRESS]", "[YOUR_WEBSITE_NAME]"),
            Subject = subject,
            PlainTextContent = message,
            HtmlContent = message
        };
        msg.AddTo(new EmailAddress(toEmail));

        var response = await sendGridClient.SendEmailAsync(msg);
        if (response.IsSuccessStatusCode)
        {
            logger.LogInformation("Email queued successfully");
        }
        else
        {
            logger.LogError("Failed to send email");
            // Adding more information related to the failed email could be helpful in debugging failure,
            // but be careful about logging PII, as it increases the chance of leaking PII
        }
    }
}

```

When you run the project again, you'll see that everything still works, as before, but in addition to injecting `ISendGridClient` into the `SendGridEmailSender` class, you can accept `ISendGridClient` anywhere in your application that supports dependency injection.

## Sending identity emails in ASP.NET Core with SendGrid

ASP.NET Core provides a straightforward interface, `IEmailSender`, to let developers implement their own email integration. When you implement `IEmailSender` and register it as a service, ASP.NET Core Identity will start using your implementation to send confirmation and password reset emails. You can quickly implement the `IEmailSender` using SendGrid's .NET library.

## Additional resources

Check out the following resources for more information on the topics and tools presented in this tutorial:

[Account confirmation and password recovery in ASP.NET Core](https://docs.microsoft.com/en-us/aspnet/core/security/authentication/accconfirm) – If you want to learn more about the emails for confirming email address and recovering password, check out this Microsoft documentation.

[SendGrid C# .NET SDK on GitHub](https://github.com/sendgrid/sendgrid-csharp) – This GitHub repository contains helpful documentation on how to integrate with SendGrid using .NET using SendGrid's .NET library.

[Configure Console app on Microsoft Docs](https://docs.microsoft.com/en-us/dotnet/core/extensions/configuration#configure-console-apps) – You used environment variables to store the API Key in this tutorial, but it is recommended to use .NET's configuration APIs. Learn how to configure .NET console applications using the host builder.

[Source Code to this tutorial on GitHub](https://github.com/Swimburger/AspNetIdentityEmailsWithSendGrid) – Use this source code if you run into any issues, or submit an issue on this GitHub repo if you run into problems.