Receber por email
← Voltar para o catálogo

dotnet-email-service-sendgrid

Implements email service abstraction with SendGrid provider. Includes template support, localization, async sending, and domain event integration for transactional emails.

66estrelas
Atualizado há 5 meses

Ver no GitHub ↗

Como adicionar

/plugin marketplace add ronnythedev/dotnet-clean-architecture-skills

O comando exato pode variar conforme o repositório. Confira o README no GitHub.

Para o autor da skill

Cole no README do seu repo

Mostra que sua skill está catalogada na Skillteca, gera backlink e tráfego rastreável.

[![Skillteca](https://www.skillteca.com.br/api/badge/dotnet-email-service-sendgrid/svg)](https://www.skillteca.com.br/skills/dotnet-email-service-sendgrid)

Skills relacionadas

Ver todas de Desenvolvimento →

Alerta por categoria

Receba novas skills de Desenvolvimento toda segunda

1 email curto, só com as skills novas de Desenvolvimento. 4 minutos de leitura, sem spam, cancela com 1 clique.

Você confirma o email no primeiro envio. Sem spam. Cancela com 1 clique.

Ler descrição completa

Email Service Integration

Overview

Abstracted email service with template support:

  • Interface in Application - IEmailService
  • SendGrid implementation - Production-ready provider
  • Template support - Dynamic content with placeholders
  • Localization - Multiple language templates
  • Domain event integration - Send on user actions

Quick Reference

| Component | Purpose | |-----------|---------| | IEmailService | Email abstraction interface | | SendGridEmailService | SendGrid implementation | | EmailOptions | Configuration settings | | EmailTemplate | Template definitions |

Template: Email Service Interface

// src/{name}.application/Abstractions/Email/IEmailService.cs
namespace {name}.application.abstractions.email;

public interface IEmailService
{
    Task SendAsync(
        string to,
        string subject,
        string htmlBody,
        CancellationToken cancellationToken = default);

    Task SendTemplateAsync(
        string to,
        string templateId,
        object templateData,
        CancellationToken cancellationToken = default);

    Task SendWelcomeEmailAsync(
        string to,
        string userName,
        string language = "en",
        CancellationToken cancellationToken = default);

    Task SendPasswordResetEmailAsync(
        string to,
        string resetCode,
        string language = "en",
        CancellationToken cancellationToken = default);

    Task SendAssessmentReadyEmailAsync(
        string to,
        string userName,
        string assessmentName,
        string language = "en",
        CancellationToken cancellationToken = default);
}

Template: Email Options

// src/{name}.infrastructure/Email/EmailOptions.cs
namespace {name}.infrastructure.email;

public sealed class EmailOptions
{
    public const string SectionName = "Email";

    public string ApiKey { get; init; } = string.Empty;
    public string FromEmail { get; init; } = string.Empty;
    public string FromName { get; init; } = string.Empty;
    public bool EnableSending { get; init; } = true;

    // SendGrid template IDs
    public EmailTemplateIds Templates { get; init; } = new();
}

public sealed class EmailTemplateIds
{
    public string WelcomeEn { get; init; } = string.Empty;
    public string WelcomeEs { get; init; } = string.Empty;
    public string PasswordResetEn { get; init; } = string.Empty;
    public string PasswordResetEs { get; init; } = string.Empty;
    public string AssessmentReadyEn { get; init; } = string.Empty;
    public string AssessmentReadyEs { get; init; } = string.Empty;
}

Template: SendGrid Implementation

// src/{name}.infrastructure/Email/SendGridEmailService.cs
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using SendGrid;
using SendGrid.Helpers.Mail;
using {name}.application.abstractions.email;

namespace {name}.infrastructure.email;

internal sealed class SendGridEmailService : IEmailService
{
    private readonly ISendGridClient _client;
    private readonly EmailOptions _options;
    private readonly ILogger<SendGridEmailService> _logger;

    public SendGridEmailService(
        IOptions<EmailOptions> options,
        ILogger<SendGridEmailService> logger)
    {
        _options = options.Value;
        _client = new SendGridClient(_options.ApiKey);
        _logger = logger;
    }

    public async Task SendAsync(
        string to,
        string subject,
        string htmlBody,
        CancellationToken cancellationToken = default)
    {
        if (!_options.EnableSending)
        {
            _logger.LogInformation(
                "Email sending disabled. Would send to {To}: {Subject}",
                to, subject);
            return;
        }

        var message = new SendGridMessage
        {
            From = new EmailAddress(_options.FromEmail, _options.FromName),
            Subject = subject,
            HtmlContent = htmlBody
        };
        message.AddTo(new EmailAddress(to));

        var response = await _client.SendEmailAsync(message, cancellationToken);

        if (!response.IsSuccessStatusCode)
        {
            var body = await response.Body.ReadAsStringAsync(cancellationToken);
            _logger.LogError(
                "Failed to send email to {To}. Status: {Status}, Body: {Body}",
                to, response.StatusCode, body);
            throw new EmailSendException($"Failed to send email: {response.StatusCode}");
        }

        _logger.LogInformation("Email sent to {To}: {Subject}", to, subject);
    }

    public async Task SendTemplateAsync(
        string to,
        string templateId,
        object templateData,
        CancellationToken cancellationToken = default)
    {
        if (!_options.EnableSending)
        {
            _logger.LogInformation(
                "Email sending disabled. Would send template {TemplateId} to {To}",
                templateId, to);
            return;
        }

        var message = new SendGridMessage
        {
            From = new EmailAddress(_options.FromEmail, _options.FromName),
            TemplateId = templateId
        };
        message.AddTo(new EmailAddress(to));
        message.SetTemplateData(templateData);

        var response = await _client.SendEmailAsync(message, cancellationToken);

        if (!response.IsSuccessStatusCode)
        {
            _logger.LogError(
                "Failed to send template email to {To}. Template: {TemplateId}",
                to, templateId);
            throw new EmailSendException($"Failed to send email: {response.StatusCode}");
        }

        _logger.LogInformation(
            "Template email sent to {To}. Template: {TemplateId}",
            to, templateId);
    }

    public async Task SendWelcomeEmailAsync(
        string to,
        string userName,
        string language = "en",
        CancellationToken cancellationToken = default)
    {
        var templateId = language.ToLower() switch
        {
            "es" => _options.Templates.WelcomeEs,
            _ => _options.Templates.WelcomeEn
        };

        await SendTemplateAsync(to, templateId, new
        {
            user_name = userName,
            login_url = "https://app.example.com/login"
        }, cancellationToken);
    }

    public async Task SendPasswordResetEmailAsync(
        string to,
        string resetCode,
        string language = "en",
        CancellationToken cancellationToken = default)
    {
        var templateId = language.ToLower() switch
        {
            "es" => _options.Templates.PasswordResetEs,
            _ => _options.Templates.PasswordResetEn
        };

        await SendTemplateAsync(to, templateId, new
        {
            reset_code = resetCode,
            reset_url = $"https://app.example.com/reset-password?code={resetCode}",
            expiration_hours = 24
        }, cancellationToken);
    }

    public async Task SendAssessmentReadyEmailAsync(
        string to,
        string userName,
        string assessmentName,
        string language = "en",
        CancellationToken cancellationToken = default)
    {
        var templateId = language.ToLower() switch
        {
            "es" => _options.Templates.AssessmentReadyEs,
            _ => _options.Templates.AssessmentReadyEn
        };

        await SendTemplateAsync(to, templateId, new
        {
            user_name = userName,
            assessment_name = assessmentName,
            assessment_url = "https://app.example.com/assessments"
        }, cancellationToken);
    }
}

public class EmailSendException : Exception
{
    public EmailSendException(string message) : base(message) { }
}

Template: Domain Event Handler

// src/{name}.application/Users/EventHandlers/UserCreatedSendWelcomeEmailHandler.cs
using MediatR;
using Microsoft.Extensions.Logging;
using {name}.application.abstractions.email;
using {name}.domain.users.events;

names
Compartilhar X LinkedIn