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); } }
问题根因
- 编译错误和MailKit附件逻辑无关:
SendEmail方法被修改为需要传入List<IFormFile>类型的必填参数,但Razor模板中绑定触发该方法的事件(按钮点击、表单提交等)时,没有传入对应参数,编译器找不到匹配的方法签名直接抛出CS7036错误。 - 现有附件处理逻辑存在隐患:使用同步方法
CopyTo读取文件流,在Blazor Server场景下容易阻塞UI线程;内存流未做显式释放,大文件场景下存在内存泄漏风险;SMTP操作全部使用同步方法,不符合异步编程规范。
修复步骤
- 移除
SendEmail方法的file入参,在组件内声明全局列表变量,直接绑定Radzen Upload组件的文件输出,不需要在事件触发时手动传参。 - 替换所有同步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
相关产品推荐
相关产品推荐

