As I understand, you need a mechanism to sequentially run some tasks. So I created a Background service which creates a SMTP client once and a ConcurrentQueue to hold the mail requests and run them one by one.
This service is going to be active through the whole process of your application so it has while(TRUE) in it. and after each email it sends it waits for 500 ms.
If you want to send a mail from other services you just need to call RegisterMailRequest to enqueue a mail request.
you should define this service as a HostedService like this:
services.AddHostedService<SequentialJobHandler>();
using System.Collections.Concurrent;
using System.Threading;
using System.Threading.Tasks;
using MailKit.Net.Smtp;
using Microsoft.Extensions.Hosting;
using MimeKit;
namespace Sample
{
public class SequentialJobHandler : BackgroundService
{
private readonly string MailServerAddress;
private readonly int MailServerPort;
private readonly string AdminEmailAccount;
private readonly string AdminEmailAccountPass;
private readonly string MailUser;
private readonly string MailTitle;
private ConcurrentQueue<MailRequest> queue = new ConcurrentQueue<MailRequest>();
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
using (var client = new SmtpClient())
{
// For demo-purposes, accept all SSL certificates (in case the server supports STARTTLS)
client.ServerCertificateValidationCallback = (s, c, h, e) => true;
await client.ConnectAsync(MailServerAddress, MailServerPort, MailKit.Security.SecureSocketOptions.Auto);
// Note: only needed if the SMTP server requires authentication
await client.AuthenticateAsync(MailUser, AdminEmailAccountPass);
while (true)
{
MailRequest localValue = null;
if (queue.TryDequeue(out localValue))
{
if (localValue != null)
{
SendMail(localValue, client);
}
}
Thread.Sleep(500);
}
//await client.DisconnectAsync(true);
}
}
private async Task SendMail(MailRequest request, SmtpClient client)
{
var message = new MimeMessage();
message.From.Add(new MailboxAddress(MailTitle, AdminEmailAccount));
message.To.Add(new MailboxAddress(request.toUsername, request.toEmail));
message.Subject = request.subject;
message.Body = new TextPart("html")
{
Text = request.body
};
await client.SendAsync(message);
}
public void RegisterMailRequest(MailRequest request)
{
queue.Enqueue(request);
}
public class MailRequest
{
public string toUsername, toEmail, subject, body;
}
}
}
hope this helps.
constructorof the class in your question? I don't see where the method creates a new instance ofSMTPSmtp.SendMailAsyncmethod. Doesn't it get instantiated every time this is called?smtpclass. something like this:SmtpClient Smtp = new SmtpClient("XXX")