1

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

使用MailKit,什么是处理邮件的最佳和最快捷的方式,以便尽快发送。例如,此时每封邮件可能会一个接一个地处理,如果每个邮件需要一秒钟来处理,则发送 40000 封邮件可能需要很长时间。

我们一直在使用 aparallel 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]);
                    };
                }

            });
4

2 回答 2

3

如果我错了,请纠正我,但在我看来,它的工作方式是 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 个线程,在每个线程中发送 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.

然后使用以下代码同时发送给所有 3 个客户MimeMessage

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 条消息。

于 2015-07-16T16:06:29.710 回答
1

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

因此,为了确认,并行循环运行良好,其他地方的潜在性能问题是真正的瓶颈。

于 2015-07-22T07:19:14.353 回答