Añadir el envío de fondo para los correos electrónicos (Español (Spanish))

Añadir el envío de fondo para los correos electrónicos

Wednesday, 07 August 2024

//

5 minute read

El Comité recomienda al Estado Parte que adopte todas las medidas necesarias para garantizar la igualdad entre los géneros y el empoderamiento de la mujer.

En mi anterior post he detallado cómo enviar correos electrónicos usando FluentEmail y el cliente SMTP. Sin embargo, un problema con esto es el retraso en la transmisión de emails. Los servidores SMTP tienden a ser lentos y pueden tardar algún tiempo en enviar emails≥. Esto puede ser molesto para los usuarios y sentirse como un bloqueo en su aplicaciónM SK3

Una manera de evitar esto es enviar correos electrónicos en el fondo. De esta forma el usuario puede seguir usando la aplicación sin tener que esperar a que el correo se envíe. Este es un patrón común en las aplicaciones web y puede ser alcanzado utilizando un trabajo de fondo .

Las opciones de fondo en ASP.NET Core

En ASP.NET Core hay dos opciones principales M SK1a parte de opciones más avanzadas como Hangfire / Quartz)

  • IHostedService - esta opción le da una gestión básica del ciclo de vida para sus tareas de fondo. usted puede iniciar y detener el servicio y se ejecutará en el fondo
  • IHostedLifetime - esta opción te da más control sobre el ciclo de vida de tus tareas de fondo. También puedes iniciar y detener el servicio y éste se ejecutará en el fondo pero tienes más control audn startingM SK2 stopping , startedMST4 stopped etcMSC5

En este ejemplo I' utilice un simple IHostedService para enviar correos electrónicos en el fondo.

El Comité recomienda al Estado Parte que adopte todas las medidas necesarias para garantizar la igualdad entre los géneros y el empoderamiento de la mujer.

La fuente completa de este es a continuación.

Background Email Service
using System.Threading.Tasks.Dataflow;
using Mostlylucid.Email.Models;

namespace Mostlylucid.Email
{
    public class EmailSenderHostedService(EmailService emailService, ILogger<EmailSenderHostedService> logger)
        : IHostedService, IDisposable
    {
        private readonly BufferBlock<BaseEmailModel> _mailMessages = new();
        private Task _sendTask = Task.CompletedTask;
        private CancellationTokenSource cancellationTokenSource = new();

        public async Task SendEmailAsync(BaseEmailModel message)
        {
            await _mailMessages.SendAsync(message);
        }

        public Task StartAsync(CancellationToken cancellationToken)
        {
            logger.LogInformation("Starting background e-mail delivery");
            // Start the background task
            _sendTask = DeliverAsync(cancellationTokenSource.Token);
            return Task.CompletedTask;
        }

        public async Task StopAsync(CancellationToken cancellationToken)
        {
            logger.LogInformation("Stopping background e-mail delivery");

            // Cancel the token to signal the background task to stop
            await cancellationTokenSource.CancelAsync();

            // Wait until the background task completes or the cancellation token triggers
            await Task.WhenAny(_sendTask, Task.Delay(Timeout.Infinite, cancellationToken));
        }

        private async Task DeliverAsync(CancellationToken token)
        {
            logger.LogInformation("E-mail background delivery started");

            while (!token.IsCancellationRequested)
            {
                BaseEmailModel? message = null;
                try
                {if(_mailMessages.Count == 0) continue;
                    message = await _mailMessages.ReceiveAsync(token);
                    switch (message)
                    {
                        case ContactEmailModel contactEmailModel:
                            await emailService.SendContactEmail(contactEmailModel);
                            break;
                        case CommentEmailModel commentEmailModel:
                            await emailService.SendCommentEmail(commentEmailModel);
                            break;
                    }
                    logger.LogInformation("Email from {SenderEmail} sent", message.SenderEmail);
                }
                catch (OperationCanceledException)
                {
                    break;
                }
                catch (Exception exc)
                {
                    logger.LogError(exc, "Couldn't send an e-mail from {SenderEmail}", message?.SenderEmail);
                    await Task.Delay(1000, token); // Delay and respect the cancellation token
                    if (message != null)
                    {
                        await _mailMessages.SendAsync(message, token);
                    }
                }
            }

            logger.LogInformation("E-mail background delivery stopped");
        }

        public void Dispose()
        {
            cancellationTokenSource.Cancel();
            cancellationTokenSource.Dispose();
        }
    }
}
Aquí usted puede ver que tratamos el inicio del servicio y la configuración de un nuevo BufferBlock para mantener los correos.
public class EmailSenderHostedService(EmailService emailService, ILogger<EmailSenderHostedService> logger)
        : IHostedService, IDisposable
    {
        private readonly BufferBlock<BaseEmailModel> _mailMessages = new();
        private Task _sendTask = Task.CompletedTask;
        private CancellationTokenSource cancellationTokenSource = new();

También hemos establecido una nueva Task para entregar los correos en el fondo. y una cancelaciónTokenSource para cancelar la tarea graciosamente cuando queremos detener el servicio.

Luego iniciamos el HostedService con StartAsync y proporcionamos el punto de entrada para otros servicios para enviar un correo electrónico.

 public async Task SendEmailAsync(BaseEmailModel message)
        {
            await _mailMessages.SendAsync(message);
        }

        public Task StartAsync(CancellationToken cancellationToken)
        {
            logger.LogInformation("Starting background e-mail delivery");
            // Start the background task
            _sendTask = DeliverAsync(cancellationTokenSource.Token);
            return Task.CompletedTask;
        }

En nuestra clase de configuración ahora tenemos que registrar el servicio con el contenedor DI y iniciar el HostedService

       services.AddSingleton<EmailSenderHostedService>();
        services.AddHostedService(provider => provider.GetRequiredService<EmailSenderHostedService>());

Ahora podemos enviar correos en el fondo llamando al método SendEmailAsync en el EmailSenderHostedService. e.gM SK1 para el formulario de contacto que hacemos esto.

            var contactModel = new ContactEmailModel()
            {
                SenderEmail = user.email,
                SenderName =user.name,
                Comment = commentHtml,
            };
            await sender.SendEmailAsync(contactModel);

En el código de arriba esto agrega este mensaje a nuestra BufferBlock<BaseEmailModel> _mailMessages y la tarea de fondo lo capturará y enviará el correo electrónico.

   private async Task DeliverAsync(CancellationToken token)
        {
          ...

            while (!token.IsCancellationRequested)
            {
                BaseEmailModel? message = null;
                try
                {if(_mailMessages.Count == 0) continue;
                    message = await _mailMessages.ReceiveAsync(token);
                    switch (message)
                    {
                        case ContactEmailModel contactEmailModel:
                            await emailService.SendContactEmail(contactEmailModel);
                            break;
                        case CommentEmailModel commentEmailModel:
                            await emailService.SendCommentEmail(commentEmailModel);
                            break;
                    }
                    logger.LogInformation("Email from {SenderEmail} sent", message.SenderEmail);
           ...
            }

            logger.LogInformation("E-mail background delivery stopped");
        }

Esto entonces se repleje hasta que paramos el servicio y continuemos a monitorizar el BufferBlock para nuevos correos a enviar.

Finding related posts...
logo

© 2026 Scott Galloway — Unlicense — All content and source code on this site is free to use, copy, modify, and sell.