繁体   English   中英

使用C#中的MailKit发送批量电子邮件

[英]Send bulk email with MailKit in C#

我们正在使用MailKit通过创建客户端,建立连接和发送邮件来成功发送电子邮件。 非常标准的东西非常有用,因为我们在应用程序中收到一条消息,然后做一些事情并通过电子邮件发送。
但是,我们希望能够尽快处理成千上万的电子邮件
我们的目标电子邮件服务器可能不可用,因此我们可以快速备份邮件,从而产生积压。

使用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]);
                    };
                }

            });

如果我错了,请纠正我,但是在我看来,这种工作方式是Parallel.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个线程,并在每个线程中发送一条消息。

但是,相反,如果您创建了以下一条消息,该怎么办:

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条消息,因此最终导致他们实际上只需要发送1条消息时就尝试优化发送1000条消息。

因此,我们发现了范围更广的修复程序,除了通过Parrallel ForEach循环发现的改进之外,还大大提高了性能。 与MailKit无关,但我想还是应该分享。 调用代码创建inputList的方式是使用DirectoryInfo.GetDirectories枚举目录中的所有第一个。 在某些情况下,我们的代码需要2秒钟才能在其中包含40k文件的目录上执行。 我们将其更改为EnumerateDirectories,它有效地释放了邮件发送代码以发送许多电子邮件。

因此可以确认,并行循环非常有效,其他地方的根本性能问题是真正的瓶颈。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM