【问题标题】:SmtpClient.SendMailAsync method is hanging when sending a big amount of mails发送大量邮件时 SmtpClient.SendMailAsync 方法挂起
【发布时间】:2019-07-02 01:56:07
【问题描述】:

我正在尝试使用 SmtpClient.SendMailAsync 方法发送大量电子邮件。 这是我从简单控制台应用程序调用的测试方法。

    static void Main(string[] args)
    {

        SendMailsOnebyOneAsync().GetAwaiter().GetResult();

    }


    public static async Task SendMailsOnebyOneAsync()
    {
        for (int i = 0; i < 1000; i++)
        {
            try
            {
                using (SmtpClient sMail = new SmtpClient("XXX"))
                {
                    sMail.DeliveryMethod = SmtpDeliveryMethod.Network;
                    sMail.UseDefaultCredentials = false;
                    sMail.Credentials = null;

                    var fromMailAddress = new MailAddress("XXX");
                    var toMailAddress = new MailAddress("XXX");

                    MailMessage message = new MailMessage(fromMailAddress, toMailAddress)
                    {
                        Subject = "test"
                    };

                    await sMail.SendMailAsync(message);

                    Console.WriteLine("Sent {0}", i);
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }
        }
    }

有时该方法挂起 - 它等待 SendMailAsync 似乎卡住并且不会返回。

我看到一个相关问题 SmtpClient SendMailAsync sometimes never returns 。 但是没有建议对我有用的修复方法。

当我尝试使用同步方法 SmtpClient.Send 时,一切正常,应用程序永远不会挂起。

有人知道什么是错的吗?

【问题讨论】:

  • 您可以访问 SMTP 服务器吗?查看日志可能会发现问题。
  • 知道您不能发送异步 20 亿封电子邮件。我夸大了,但你的身体受到一定程度的限制。在你的情况下,电子邮件非常小,但如果它只是一个示例代码,而你有附件的真实电子邮件是 1-2mb,这完全会杀死你的网卡在同一秒内发送 1000 封电子邮件,尤其是在充其量你在千兆网络上每秒可以发送 60-70 个。
  • id 检查您正在使用的任何 smtp 服务,它们有任何速率限制 - 大多数流行的服务都会有它们。为了克服它,您可以在这种情况下使用队列(很多不同的队列实现 - 数据库、rabbitMQ、EASendMail、MSMQ 等),在这种情况下,您有大量的电子邮件要发送出去。如果它是您自己的 smtp 服务器,那么正如@virusstorm 所说,查看日志
  • 如果能获得访问权限,我会尝试查看日志。
  • 问题 - 如果弗兰克提到的“杀死网络卡”我应该得到任何异常还是只是挂起?

标签: c# async-await smtpclient


【解决方案1】:

一位同事指出,SmtpClient 实际上已过时,Microsoft 建议不要使用它。

请参阅以下link

     ************ Update ***********

我已尝试按照链接中的建议使用 MailKit。 对于 non asyncasync 发送,相同的场景与 MailKit 完美配合。

   **********************************

【讨论】:

  • 你是个节省者
【解决方案2】:
  • 为了使用 SmtpClient 发送大量电子邮件,我记得建议重用相同的连接。
  • 我会改变你处理异步的方式。试试ThreadPool

附带说明,SmtpClient 不支持现代协议。 偶尔用于内部使用和测试的电子邮件仍然可以。
你可以试试MailKit

【讨论】:

    【解决方案3】:

    使用一个客户端发送重复的邮件。不断创建和处理许多客户端可能存在端口问题。

    public static async Task SendMailsOnebyOneAsync() {
        using (var sMail = new SmtpClient("XXX")) {
            sMail.DeliveryMethod = SmtpDeliveryMethod.Network;
            sMail.UseDefaultCredentials = false;
            sMail.Credentials = null;
    
            for (int i = 0; i < 1000; i++) {
                try {
                    var fromMailAddress = new MailAddress("XXX");
                    var toMailAddress = new MailAddress("XXX");
    
                    var message = new MailMessage(fromMailAddress, toMailAddress) {
                        Subject = "test"
                    };
    
                    await sMail.SendMailAsync(message);
    
                    Console.WriteLine("Sent {0}", i);
                } catch (Exception e) {
                    Console.WriteLine(e.Message);
                }
            }
        }
    }
    

    其次,虽然这可能只是一个例子,但尝试一次发送这么多电子邮件是不合理的。

    【讨论】:

    • 我试过这个并没有解决问题。谢谢。
    猜你喜欢
    • 2018-08-30
    • 1970-01-01
    • 2011-04-08
    • 1970-01-01
    • 1970-01-01
    • 2021-11-07
    • 2014-02-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多