This is a viewer only at the moment see the article on how this works.
To update the preview hit Ctrl-Alt-R (or ⌘-Alt-R on Mac) or Enter to refresh. The Save icon lets you save the markdown file to disk
This is a preview from the server running through my markdig pipeline
إضافة إرسال الخلفية للبريد الإلكتروني
Wednesday, 07 August 2024
##بداية
في پستي السابق شرحت كيف أرسل الرسائل الإلكترونية باستخدام 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");
}
ومن ثم سيدور هذا حتى نتوقف عن الخدمة ونستمر في مراقبة "بفر بلاك" لإرسال رسائل بريدية جديدة