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

Blazor中使用MailKit发送多附件邮件报CS7036错误求助

问题背景
  • 基于MailKit为Blazor应用开发邮件发送模块,已实现纯文本、HTML邮件发送能力,无法实现多附件发送
  • 前端使用Radzen Blazor Upload组件完成文件上传,上传文件为IFormFile类型,需要提取为邮件附件
  • 调整代码新增List<IFormFile>类型的file参数替换原单附件变量后,原有报错消失,但出现编译错误:

CS7036 未提供与“AddEmailsComponent.SendEmail(List)”的必需形参“file”对应的实参

原问题代码如下:

private async Task SendEmail(List<IFormFile> file)
{
    try
    {
        // create email message
        var email = new MimeMessage();
        email.From.Add(MailboxAddress.Parse(sender));
        email.To.Add(MailboxAddress.Parse(receiver));
        email.Subject = emailsubject;
        var multipart = new Multipart("mixed");
        multipart.Add(new TextPart(TextFormat.Html) { Text = emailMessage });
        foreach (var attachment in file)
        {
            var content = new MemoryStream();
            attachment.CopyTo(content);
            content.Position = 0;

            var contentType = ContentType.Parse(attachment.ContentType);
            var part = new MimePart(contentType.MimeType)
            {
                FileName = Path.GetFileName(attachment.FileName),
                ContentTransferEncoding = ContentEncoding.Base64,
                Content = new MimeContent(content),
            };

            multipart.Add(part);
        }

        email.Body = multipart;
        // send email
        using var smtp = new SmtpClient();
        smtp.Connect(outgoingServer, outgoingPort, SecureSocketOptions.Auto);
        smtp.Authenticate(userName, userPassword);
        smtp.Send(email);
        smtp.Disconnect(true);
    }
    catch (Exception ex)
    {
        NotificationService.Notify(NotificationSeverity.Error, "Send Email Error!", ex.Message, 7000);
    }
}
问题根因
  1. 编译错误和MailKit附件逻辑无关:SendEmail方法被修改为需要传入List<IFormFile>类型的必填参数,但Razor模板中绑定触发该方法的事件(按钮点击、表单提交等)时,没有传入对应参数,编译器找不到匹配的方法签名直接抛出CS7036错误。
  2. 现有附件处理逻辑存在隐患:使用同步方法CopyTo读取文件流,在Blazor Server场景下容易阻塞UI线程;内存流未做显式释放,大文件场景下存在内存泄漏风险;SMTP操作全部使用同步方法,不符合异步编程规范。
修复步骤
  1. 移除SendEmail方法的file入参,在组件内声明全局列表变量,直接绑定Radzen Upload组件的文件输出,不需要在事件触发时手动传参。
  2. 替换所有同步IO操作为异步方法,用using声明自动释放流资源,避免双重释放问题。

修正后代码

首先是Razor组件中Upload组件和触发按钮的绑定:

<!-- 开启多文件上传,直接绑定到组件全局变量 -->
<RadzenUpload Multiple="true" @bind-Files="@UploadedFiles" />
<RadzenButton Text="发送邮件" Click="@SendEmail" />

然后是后端逻辑:

// 全局变量接收所有上传的文件,根据Radzen组件实际返回类型调整,如果你存的是IFormFile就把泛型换成IFormFile
private List<IFormFile> UploadedFiles { get; set; } = new List<IFormFile>();

private async Task SendEmail()
{
    try
    {
        var email = new MimeMessage();
        email.From.Add(MailboxAddress.Parse(sender));
        email.To.Add(MailboxAddress.Parse(receiver));
        email.Subject = emailsubject;
        
        var multipart = new Multipart("mixed");
        // 添加HTML正文
        multipart.Add(new TextPart(TextFormat.Html) { Text = emailMessage });

        // 遍历所有上传文件生成附件
        foreach (var attachment in UploadedFiles)
        {
            // using声明自动释放内存流
            using var content = new MemoryStream();
            // 异步读取文件流,避免阻塞
            await attachment.CopyToAsync(content);
            content.Position = 0;

            var contentType = ContentType.Parse(attachment.ContentType);
            var part = new MimePart(contentType.MimeType)
            {
                FileName = Path.GetFileName(attachment.FileName),
                ContentTransferEncoding = ContentEncoding.Base64,
                Content = new MimeContent(content),
                // 标记流由业务代码释放,避免MimePart和using重复释放流抛异常
                ContentOwnsStream = false
            };
            multipart.Add(part);
        }

        email.Body = multipart;

        // SMTP操作全部替换为异步方法
        using var smtp = new SmtpClient();
        await smtp.ConnectAsync(outgoingServer, outgoingPort, SecureSocketOptions.Auto);
        await smtp.AuthenticateAsync(userName, userPassword);
        await smtp.SendAsync(email);
        await smtp.DisconnectAsync(true);

        NotificationService.Notify(NotificationSeverity.Success, "邮件发送成功", duration: 3000);
    }
    catch (Exception ex)
    {
        NotificationService.Notify(NotificationSeverity.Error, "邮件发送失败", ex.Message, 7000);
    }
}

注意事项

  • 如果你用的Radzen Upload组件默认绑定的文件类型不是IFormFile,直接把UploadedFiles的泛型类型改成组件实际返回的类型即可,核心是不要把文件列表作为SendEmail的参数从事件传入,直接读取组件内绑定的全局变量就能解决编译错误。
  • 多附件添加逻辑本身没有问题,只要能正确拿到所有上传文件的流,遍历添加到Multipart容器中就能正常发送。

内容的提问来源于stack exchange,提问作者David Gammon

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 21:54:33