使用MemoryStream作为邮件附件发送时报Stream does not support reading异常如何解决
异常原因分析
核心根因:流被提前释放
你的代码存在两个关联问题导致MemoryStream在SmtpClient读取前就被销毁:
- 首先
MailWithAttachment方法签名是void,但内部使用了await调用异步方法,说明你实际代码中这个方法是async void类型。async void方法仅适合用作事件处理器,外部调用方无法等待它的执行完成,会导致using代码块在SendMailAsync还没完成流读取操作时就提前结束,MemoryStream被Dispose后就不再支持读取操作,直接抛出对应异常。 - 就算你把方法改成
async Task,如果上层调用这个方法时没有加await,也会出现同样的提前释放问题。
其他可能诱因
- 你传入
Attachment构造函数的流被其他业务代码提前修改了Position到末尾,读取的时候直接读到结尾误以为流不可读,不过你现有代码中已经显式设置了Position=0,这个概率较低。 - 你简化的
GetMemoryStream方法中如果存在其他操作,比如返回的是已经被Dispose的MemoryStream,也会触发这个异常。
修复方案
- 修正
MailWithAttachment方法的签名,改为返回Task,不要用async void:
// 修改前 public void MailWithAttachment() // 修改后 public async Task MailWithAttachment()
- 所有调用
MailWithAttachment的地方都加上await,确保using块会等待整个邮件发送流程完成后再释放流:
// 调用示例 await MailWithAttachment();
- 可选兜底方案:如果确实无法避免流提前释放,可以在创建
Attachment的时候直接把流内容读出来传入,避免依赖外部流的生命周期:
// 创建Attachment时将流内容复制到新的MemoryStream,不依赖外部传入流的生命周期 using var streamCopy = new MemoryStream(); await stream.CopyToAsync(streamCopy); streamCopy.Position = 0; var attachment = new Attachment(streamCopy, ct);
内容的提问来源于stack exchange,提问作者Gerard
相关产品推荐
相关产品推荐

