使用C#中的MailKit发送批量电子邮件
本文关键字:电子邮件 中的 MailKit 使用 | 更新日期: 2023-09-27 18:01:00
我们使用MailKit
通过创建客户端、建立连接和发送邮件来成功发送电子邮件。非常标准的东西,当我们在应用程序中收到消息时,我们会做一些事情并通过电子邮件发送
但是,我们希望能够尽快处理成千上万封电子邮件中的10封
我们的目标电子邮件服务器可能不可用,因此我们可以快速备份邮件,从而产生积压。
使用MailKit
,处理邮件的最佳快捷方式是什么,以便尽快发送。例如,目前每封邮件都可能被一封接一封地处理,如果每封邮件需要一秒钟的处理时间,那么发送40000封邮件可能需要很长时间。
我们一直在使用parallel foreach
来启动许多线程,但这有局限性。如有任何建议或建议,我们将不胜感激。
添加代码示例:更正,添加新代码示例。这要快得多,但我无法让它每次都创建一个新的连接。Exchange引发错误"已指定发件人"。目前平均每秒发送约6封邮件
var rangePartitioner = Partitioner.Create(0, inpList.Count, 15);
var po = new ParallelOptions { MaxDegreeOfParallelism = 30 };
Parallel.ForEach(rangePartitioner, (range, loopState) =>
{
using (var client = new SmtpClient(new SlabProtocolLogger()))
{
client.Connect(_appSettings.RelayAddress, _appSettings.RelayPort);
client.AuthenticationMechanisms.Remove("XOAUTH2");
for (int i = range.Item1; i < range.Item2; i++)
{
var message = _outboundQueueRepository.Read(inpList[i]).Load();
client.Send(message.Body, message.Metadata.Sender, message.Metadata.Recipients.Select(r => (MailboxAddress)r));
_outboundQueueRepository.Remove(inpList[i]);
};
}
});
如果我错了,请纠正我,但在我看来,这是并行的。Foreach正在创建一些线程。然后,每个线程创建一个SMTP连接,然后循环发送一批消息。
这对我来说似乎很合理。
我能给你的唯一建议是,如果其中许多邮件的内容和发件人地址完全相同,唯一的区别是收件人是谁,你可以大大减少需要发送的邮件数量。
例如,如果你目前正在做一些事情,比如发送以下3条消息:
消息#1:
From: no-reply@company.com
To: Joe The Plumber <joe@plumbing-masters.com>
Subject: We've got a new sale! 50% off everything in stock!
some message text goes here.
消息#2
From: no-reply@company.com
To: Sara the Chef <sara@amazing-chefs.com>
Subject: We've got a new sale! 50% off everything in stock!
some message text goes here.
消息#3:
From: no-reply@company.com
To: Ben the Cobbler <ben@cobblers-r-us.com>
Subject: We've got a new sale! 50% off everything in stock!
some message text goes here.
您的代码可能会创建3个线程,在每个线程中发送1条消息。
但是,如果您创建了以下单个消息:
From: no-reply@company.com
To: undisclosed-recipients:;
Subject: We've got a new sale! 50% off everything in stock!
some message text goes here.
然后使用以下代码发送给同一MimeMessage
的所有3个客户?
var sender = new MailboxAddress (null, "no-reply@company.com");
var recipients = new List<MailboxAddress> ();
recipients.Add (new MailboxAddress ("Joe the Plumber", "joe@plumbing-masters.com"));
recipients.Add (new MailboxAddress ("Sara the Chef", "sara@amazing-chefs.com"));
recipients.Add (new MailboxAddress ("Ben the Cobbler", "ben@cobblers-r-us.com"));
client.Send (message, sender, recipients);
您的所有3个客户都将收到相同的电子邮件,您不必发送3条消息,只需发送1条消息。
你可能已经理解了这个概念,所以这可能对你没有任何帮助——我之所以提到它,只是因为我注意到这并不是每个人都能立即意识到的。有些人认为他们需要为每个收件人发送1条消息,因此最终会出现这样的情况:他们试图优化发送1000条消息,而实际上他们只需要发送1条。
因此,我们发现了一个范围更广的修复程序,除了Parralle-ForEach循环的改进外,它还大大提高了性能。与MailKit无关,但我想我无论如何都会分享。调用代码创建inputList的方式是使用DirectoryInfo。GetDirectories以枚举目录中的所有第一个。在某些情况下,我们的代码在包含40k个文件的目录上执行需要2秒钟。我们将其更改为EnumerateDirectories,它有效地释放了发送邮件的代码来发送许多电子邮件。
因此,要确认的是,并行循环运行得很好,其他地方的潜在性能问题才是真正的瓶颈。