إضافة إرسال الخلفية للبريد الإلكتروني (العربية (Arabic))

إضافة إرسال الخلفية للبريد الإلكتروني

Wednesday, 07 August 2024

//

4 minute read

##بداية

في پستي السابق شرحت كيف أرسل الرسائل الإلكترونية باستخدام FluentEmail و客户端 SMTP. لكن مشكلة واحدة مع هذا هو التأخر في إرسال الرسائل الإلكترونية. مراكز SMTP تميل إلى أن تكون بطيئة ويمكن أن تستغرق وقتاً لإرسال الرسائل الإلكترونية

أحد الطرق للتعامل مع هذا هو إرسال البريد الإلكتروني في الخلفية. بهذه الطريقة يمكن للمستخدم أن يستمر باستخدام التطبيق دون الحاجة إلى انتظار إرسال البريد الالكتروني. هذا نمط شائع في تطبيقات الويب ويمكن تحقيقه باستخدام الوظيفة الخلفية

خيارات خلفية في ASP.NET Core

في ASP.NET Core لديكم خيارين رئيسيين ( بالإضافة إلى خيارات متقدمة مثل Hangfire

  • IHostedService - هذه الخيار تعطيك إدارة دورة حياة أساسية لمهام الخلفية الخاصة بك. يمكنك أن تبدأ وتتوقف عن الخدمة وسيجري في الخلفيةM SK2
  • IHostedLifetime - هذه الخيار تعطيك المزيد من التحكم في دورة حياة مهمتك الخلفية. يمكنك أيضاً أن تبدأ وتتوقف عن الخدمة وسيجري في الخلفية ولكن لديك المزيد من السيطرة startn , stoppingM SK3 started , stopped etcMSC5

في هذا المثال سوف أستخدم IHostedService بسيطاً لإرسال البريد الإلكتروني في الخلفية

الرمز المصدر

المصدر الكامل لهذا هو .

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();
        }
    }
}
هنا يمكنكم أن تروا أننا نتعامل مع بداية الخدمة وإعداد حفر بلاك جديد لحفظ الرسائل الإلكترونية.
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();

كما أننا وضعنا مهمة جديدة لإرسال البريد الإلكتروني في الخلفية. و cancellationTokenSource لإلغاء المهمة ببهجة عندما نريد إيقاف الخدمة.

ومن ثم نبدأ خدمة المضيفة مع StartAsync ونقوم بتوفير نقطة الدخول للخدمات الأخرى لإرسال بريد إلكتروني.

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

في دراستنا لإعداداتنا نحتاج الآن إلى تسجيل الخدمة مع حاسوبك DI ونبدأ خدمة المضيفة

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

الآن يمكننا إرسال البريد الإلكتروني في الخلفية عن طريق الاتصال بأسلوب SendEmailAsync على EmailSenderHostedService. e.g., للنموذج الإتصالي نحن نفعل هذا

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

في البرمجة فوق هذا يضيف هذه الرسالة إلى BufferBlock<BaseEmailModel> _رسائل بريدية و المهمة الخلفية ستلتقطها وترسل البريد

   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");
        }

ومن ثم سيدور هذا حتى نتوقف عن الخدمة ونستمر في مراقبة "بفر بلاك" لإرسال رسائل بريدية جديدة

Finding related posts...
logo

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