You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

发送批量邮件时遇错误:异步调用已在进行中需完成或取消

解决SmtpClient异步调用冲突的问题

嘿,这个问题我之前做批量邮件发送的时候也踩过一模一样的坑!咱们来一步步拆解原因和解决方案:

问题根源

你遇到的错误“异步调用已在进行中,必须完成或取消后才能调用此方法”,本质是因为**System.Net.Mail.SmtpClient的实例不是线程安全的**。当你用同一个smtp实例同时发起多个SendMailAsync调用时,客户端会尝试复用同一个网络连接,导致并发调用之间互相干扰,触发这个错误。

解决方案1:为每封邮件创建独立的SmtpClient实例

最简单的修复方式,就是让每个异步任务都使用自己的SmtpClient实例,这样就不会有连接冲突的问题。同时用using语句确保资源被正确释放:

public static async Task<bool> SendRegisterEmail(List<MailMessage> mailMessage) {
    bool flag = true;
    try {
        // 给每封邮件分配独立的SmtpClient实例
        var emailTasks = mailMessage.Select(async message => {
            using var smtp = new SmtpClient();
            // 这里可以根据你的配置设置SMTP服务器、端口、凭据等
            // smtp.Host = "your-smtp-server.com";
            // smtp.Port = 587;
            // smtp.Credentials = new NetworkCredential("username", "password");
            // smtp.EnableSsl = true;
            
            await smtp.SendMailAsync(message);
        });
        
        await Task.WhenAll(emailTasks);
    } catch (Exception ex) {
        flag = false;
        // 记得这里添加日志记录或者异常处理逻辑
        Console.WriteLine($"邮件发送失败: {ex.Message}");
    }
    return flag;
}

解决方案2:改用更现代的MailKit库

官方其实已经标记System.Net.Mail.SmtpClient为过时(Obsolete),推荐使用更可靠、线程安全的第三方库MailKit。它不仅支持并发发送,还提供了更丰富的邮件处理功能:

  1. 首先通过NuGet安装MailKit:Install-Package MailKit
  2. 修改你的代码为以下形式:
using MailKit.Net.Smtp;
using MimeKit;

public static async Task<bool> SendRegisterEmail(List<MimeMessage> mimeMessages) {
    bool flag = true;
    try {
        using var smtp = new SmtpClient();
        // 连接到SMTP服务器
        await smtp.ConnectAsync("your-smtp-server.com", 587, MailKit.Security.SecureSocketOptions.StartTls);
        // 验证身份
        await smtp.AuthenticateAsync("your-email@example.com", "your-password");

        // MailKit的SmtpClient支持并发调用SendAsync
        var emailTasks = mimeMessages.Select(message => smtp.SendAsync(message));
        await Task.WhenAll(emailTasks);

        // 断开连接
        await smtp.DisconnectAsync(true);
    } catch (Exception ex) {
        flag = false;
        Console.WriteLine($"邮件发送失败: {ex.Message}");
    }
    return flag;
}

注意:这里需要把原来的MailMessage转换成MimeMessage,MailKit提供了便捷的转换方式,或者你可以直接用MimeMessage构建邮件内容。

总结

  • 如果只是临时修复现有代码,方案1足够简单直接;
  • 如果是长期维护的项目,强烈推荐方案2,MailKit是目前.NET生态中处理邮件的首选库,稳定性和功能都远超原生的SmtpClient。

内容的提问来源于stack exchange,提问作者Vatsal Patel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 08:37:48