Как отправлять электронные письма ASP.NET Core Identity с помощью Twilio SendGrid

Эта статья была написана для компании Twilio и первоначально опубликована в блоге Twilio.

Как часть ASP.NET Identity, ASP.NET Core предоставляет множество функций для управления учетными записями, аутентификации и авторизации. ASP.NET Identity также отправляет электронные письма для подтверждения адресов электронной почты и сброса паролей, но то, как будут отправляться эти письма, зависит от вас.

В этом руководстве вы узнаете, как отправлять электронные письма ASP.NET Identity с помощью Twilio SendGrid.

Необходимые условия

Для работы вам понадобятся следующие вещи:

  • ОС, поддерживающая .NET (Windows/macOS/Linux)
  • .NET 6 SDK
  • Редактор кода или IDE (я рекомендую VS Code с плагином C#, Visual Studio или JetBrains Rider)
  • Учетная запись Twilio SendGrid. Зарегистрируйтесь здесь, чтобы отправлять до 100 писем в день совершенно бесплатно.

Исходный код этого руководства вы можете найти на GitHub. Используйте его, если у вас возникнут какие-либо проблемы, или отправьте проблему, если у вас возникнут проблемы.

Настройка аккаунта SendGrid для отправки электронных писем

Есть две вещи, которые необходимо настроить, прежде чем вы сможете отправлять электронные письма: Во-первых, вам нужно настроить аутентификацию отправителя. Это позволит убедиться, что вы являетесь владельцем адреса электронной почты или домена, с которого вы будете отправлять электронные письма. Во-вторых, вам нужно будет создать API-ключ SendGrid с правами на отправку писем.

Аутентификация отправителя

Чтобы быстро начать работу, в этом руководстве вы будете использовать проверку одного отправителя. Это подтверждает, что вы являетесь владельцем адреса электронной почты, с которого приложение будет отправлять электронные письма. Single Sender Verification отлично подходит для тестирования, но не рекомендуется для производства.

Twilio рекомендует использовать аутентификацию домена в производственных средах. Аутентифицированный домен доказывает поставщикам электронной почты, что вы являетесь владельцем домена, и удаляет текст «via sendgrid.net», который в противном случае поставщики добавили бы к вашему адресу from.

Чтобы настроить проверку единого отправителя, перейдите на вкладку Настройки в левом меню. Когда откроется вкладка настроек, нажмите Аутентификация отправителя.

Затем нажмите кнопку Начать работу в разделе Проверка одного отправителя.

Откроется форма в правой части панели. Заполните форму, указав свои данные и адрес электронной почты.

После заполнения формы нажмите Создать. Справа появится еще одна панель с просьбой подтвердить адрес электронной почты в вашем почтовом ящике. Перейдите в ваш личный почтовый ящик, откройте письмо от SendGrid и нажмите Проверить единого отправителя.

Ваш адрес электронной почты был подтвержден. Теперь вы можете использовать его для отправки писем!

Создание API-ключа SendGrid для отправки электронных писем

Вернувшись на сайт SendGrid, выберите API Keys на вкладке Settings, затем нажмите Create API Key в правом верхнем углу. Откроется еще одна форма в правой панели.

Дайте своему API-ключу полезное имя. Вы можете назначить различные разрешения для ключа API. Для оптимальной безопасности следует назначать только минимальное количество разрешений, которое вам необходимо.

Далее нажмите Ограниченный доступ.

Прокрутите вниз до элемента аккордеона Mail Send и щелкните по нему, чтобы открыть расположенные под ним разрешения. Перетащите ползунок вправо для разрешения Mail Send.

Прокрутите форму в самый низ и нажмите кнопку Создать и просмотреть. Теперь ключ API будет отображаться на вашем экране.

Вы не сможете получить API-ключ, как только покинете этот экран, поэтому обязательно скопируйте API-ключ в безопасное место.

После проверки отправителя и создания API-ключа вы можете приступать к написанию кода!

Отправка идентификационных писем с помощью Twilio SendGrid

В этом руководстве вы будете выполнять несколько команд, но если вы предпочитаете использовать IDE, то для Visual Studio и JetBrains Rider есть эквивалентные действия. Откройте оболочку, которую вы предпочитаете, чтобы выполнить предложенные команды.

Если у вас уже есть веб-приложение с ASP.NET Core Identity, пропустите следующий шаг. В оболочке выполните следующую команду .NET CLI для создания проекта:

dotnet new webapp -o WebAppIdentity -au Individual
Войти в полноэкранный режим Выйти из полноэкранного режима

Эта команда создаст проект ASP.NET Core с Identity и поместит его в папку WebAppIdentity.

Затем перейдите в каталог нового проекта в вашей оболочке:

cd WebAppIdentity
Войти в полноэкранный режим Выйти из полноэкранного режима

Если вы запустите проект сейчас и попытаетесь зарегистрировать новый аккаунт, веб-приложение сообщит вам, что отправитель электронной почты не настроен. Кроме того, для имитации процесса будет показана ссылка, которая обычно отправляется в ваш почтовый ящик для подтверждения электронной почты.

Однако настоящая страница будет показана, когда вы зарегистрируете отправителя электронной почты. Для этого сначала нужно создать класс, реализующий интерфейс IEmailSender, а затем зарегистрировать класс в контейнере инъекции зависимостей ASP.NET Core.

Для этого создайте новый файл в корневом каталоге проекта с именем SendGridEmailSender.cs со следующим кодом:

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();
  }
}
Вход в полноэкранный режим Выход из полноэкранного режима

SendGridEmailSender реализует интерфейс IEmailSender. Этот интерфейс ожидает от вас реализации только одного метода, SendEmailAsync. Этот метод будет использоваться ASP.NET Identity для отправки ваших писем.

Чтобы реализовать метод SendEmailAsync с помощью SendGrid, вам сначала нужно установить библиотеку SendGrid для C# и .NET. Вернитесь в свою оболочку и выполните следующую команду для установки библиотеки с помощью пакета SendGrid NuGet:

dotnet add package SendGrid
Войти в полноэкранный режим Выйти из полноэкранного режима

Обновите файл SendGridEmailSender.cs следующим кодом:

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
        }
    }
}
Войти в полноэкранный режим Выйти из полноэкранного режима

Замените [YOUR_EMAIL_ADDRESS] адресом электронной почты, который вы проверили в SendGrid ранее, и замените [YOUR_WEBSITE_NAME] любым именем. Имя будет отображаться у получателя электронных писем, поэтому здесь имеет смысл использовать название вашего сайта или сервиса.

Чтобы отправлять электронные письма с помощью SendGrid, вам потребуется получить ключ API SendGrid из конфигурации приложения, поэтому в параметры конструктора добавлен IConfiguration configuration. Вы также захотите регистрировать, успешно ли отправлены электронные письма, поэтому в конструктор был добавлен параметр ILogger<SendGridEmailSender> logger.

Оба этих параметра будут инжектированы контейнером инъекции зависимостей ASP.NET Core, а затем сохранены как поля класса.

В SendEmailAsync ключ API SendGrid извлекается из конфигурации приложения и используется для создания нового SendGridClient. Затем создается SendGridMessage, передавая все параметры, переданные в метод SendGridMessage.

Затем это сообщение отправляется с помощью SendGridClient. Если письмо было отправлено в API SendGrid успешно, в журнал будет занесено сообщение «Email queued successfully», в противном случае в журнал будет занесена ошибка «Failed to send email».

Теперь проект ожидает, что ‘SendGridApiKey’ будет настроен, но это еще не так. Вы можете настроить API-ключ различными способами, но поскольку он является секретным, вам не следует хранить его в исходном коде. Именно поэтому в .NET появился инструмент Secret Manager для хранения секретов для локальной разработки. Инициализируйте инструмент Secret Manager для вашего проекта, выполнив следующую команду:

dotnet user-secrets init
Войти в полноэкранный режим Выйти из полноэкранного режима

Выполните следующую команду для настройки ‘SendGridApiKey’ с помощью менеджера секретов:

dotnet user-secrets set SendGridApiKey [YOUR_SENDGRID_API_KEY]
Войти в полноэкранный режим Выйти из полноэкранного режима

Замените [YOUR_SENDGRID_API_KEY] на ключ API SendGrid, который вы записали ранее.

С настроенным ключом API, SendGridEmailSender готов к регистрации. Обновите файл Program.cs, чтобы зарегистрировать SendGridEmailSender в качестве службы:

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();
Войдите в полноэкранный режим Выход из полноэкранного режима

Вот и все!

Сохраните оба файла и запустите проект с помощью .NET CLI:

dotnet run
Вход в полноэкранный режим Выйти из полноэкранного режима

Обратите внимание на журналы консоли, и вы увидите строку с форматом: Now listening on: https://localhost:XXXX. Перейдите к вашему веб-приложению с этим URL в веб-браузере, нажмите на ссылку Register, заполните форму и нажмите Register. На следующей странице вам будет предложено проверить электронную почту для подтверждения учетной записи.

Откройте почтовый ящик, откройте письмо «Confirm your email» и нажмите на ссылку в письме, чтобы подтвердить свой адрес электронной почты. После нажатия на ссылку ваше веб-приложение откроется в новой вкладке с надписью «Thank you for confirming your email.».

Отличная работа!

В качестве альтернативы вы можете отправлять электронные письма с помощью SMTP и SMTP-реле SendGrid, как показано в этом руководстве.

Остановите проект, нажав ctrl + c в вашей оболочке.

Добавьте SendGridClient в контейнер инъекции зависимостей ASP.NET

SendGrid предлагает дополнительный пакет для легкой интеграции SendGrid в контейнер инъекции зависимостей (DI) ASP.NET. Вместо того чтобы создавать SendGridClient вручную в классе SendGridEmailSender, с помощью этого пакета вы можете позволить DI-контейнеру внедрить экземпляр ISendGridClient в конструктор.

Добавьте пакет NuGet для инъекции зависимостей SendGrid с помощью следующей команды:

dotnet add package SendGrid.Extensions.DependencyInjection
Войти в полноэкранный режим Выйти из полноэкранного режима

Затем зарегистрируйте SendGrid в качестве службы с помощью метода builder.Services.AddSendGrid, обновив файл Program.cs, как показано ниже:

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();
Вход в полноэкранный режим Выйти из полноэкранного режима

Теперь в файле SendGridEmailSender.cs можно удалить строки для создания SendGridClient и вместо этого принять экземпляр ISendGridClient через конструктор. Вот как выглядит обновленный файл:

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
        }
    }
}

Вход в полноэкранный режим Выход из полноэкранного режима

Когда вы снова запустите проект, вы увидите, что все работает, как и раньше, но в дополнение к инъекции ISendGridClient в класс SendGridEmailSender, вы можете принять ISendGridClient в любом месте вашего приложения, которое поддерживает инъекцию зависимостей.

Отправка идентификационных писем в ASP.NET Core с помощью SendGrid

ASP.NET Core предоставляет простой интерфейс, IEmailSender, чтобы разработчики могли реализовать свою собственную интеграцию электронной почты. Когда вы реализуете IEmailSender и зарегистрируете его как службу, ASP.NET Core Identity начнет использовать вашу реализацию для отправки писем подтверждения и сброса пароля. Вы можете быстро реализовать IEmailSender, используя библиотеку SendGrid для .NET.

Дополнительные ресурсы

Просмотрите следующие ресурсы для получения дополнительной информации по темам и инструментам, представленным в этом руководстве:

Подтверждение учетной записи и восстановление пароля в ASP.NET Core — Если вы хотите узнать больше об электронных письмах для подтверждения адреса электронной почты и восстановления пароля, ознакомьтесь с этой документацией Microsoft.

SendGrid C# .NET SDK на GitHub — Этот репозиторий GitHub содержит полезную документацию о том, как интегрироваться с SendGrid с помощью .NET, используя библиотеку SendGrid .NET.

Configure Console app on Microsoft Docs — В этом руководстве вы использовали переменные среды для хранения ключа API, но рекомендуется использовать API конфигурации .NET. Узнайте, как настраивать консольные приложения .NET с помощью конструктора хостов.

Исходный код этого руководства на GitHub — Используйте этот исходный код, если у вас возникнут проблемы, или отправьте проблему в эту репозиторию GitHub, если у вас возникнут проблемы.

Оставьте комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *