向MailMessage添加附件时流关闭错误

时间:2011-03-09 21:17:07

标签: c# .net email

我使用以下代码将文件附加到电子邮件中。

msg = new MailMessage();

    using (strMem = new MemoryStream((byte[])attDr["filedata"]))
    {
        using (strWriter = new StreamWriter(strMem))
        {
            strWriter.Flush(); strMem.Position = 0;
            using (attachment = new Attachment(strMem, attDr["filename"].ToString()))
            {
                msg.Attachments.Add(attachment);
            }
        }
    }

...
...
msg.Send();  //Error: System.ObjectDisposedException: Cannot access a closed Stream.

错误消息是://错误:System.ObjectDisposedException:无法访问已关闭的流

我猜测“USING”语句在退出块时关闭流。但是为什么“Attacments.Add()”没有制作自己的流副本?

5 个答案:

答案 0 :(得分:39)

Send()方法将访问附件以将它们嵌入到邮件消息中。这就是kaboom,内存流被处理掉了。您需要使用语句移动内部的Send()调用,以便在发送消息之后 之前不会释放流。

这里没有必要提到使用,因为内存流没有任何需要处理的非托管资源,总是让我遇到麻烦。所以我不会提起这件事。

答案 1 :(得分:12)

当我处理创建MailMessage的场景与发送分开并且可能具有多个附件时,我发现了一个解决方案是使用List of MemoryStream对象

// Tuple contains displayName and byte[] content for attachment in this case
List<Tuple<string,byte[]>> attachmentContent;
MailMessage email = BuildNativeEmail(requestObject, out attachmentContent);
List<MemoryStream> streams = new List<MemoryStream>();
foreach(Tuple<string,byte[]> attachment in attachmentContent)
{
    MemoryStream m = new MemoryStream(attachment.Item2);
    email.Attachments.Add(new System.Net.Mail.Attachment(m, attachment.Item1));
    streams.add(m);
}

// client represents a System.Net.Mail.SmtpClient object
client.Send(email);

foreach(MemoryStream stream in streams)
{
    stream.Dispose();
}

答案 2 :(得分:2)

是的,它是真的。退出块时使用语句关闭流。

请勿使用“ 使用”语句。发送电子邮件呼叫 dispose()方法以获取附件后。

...
...
msg.Send();

msg.Attachments.ToList().ForEach(x => x.ContentStream.Dispose());

对于 AlternateView ,您也可以使用相同的方式。

...
...
msg.AlternateViews.Add(alternateView);

...
msg.Send();
...
if (alternateView != null) {
    mail.AlternateViews.Dispose();
}

答案 3 :(得分:0)

使用:

using (strMem = new MemoryStream((byte[])attDr["filedata"]))
{
    using (strWriter = new StreamWriter(strMem))
    {
        strWriter.Flush(); strMem.Position = 0;
        using (attachment = new Attachment(attDr["filename"].ToString()))
        {
            strMem.CopyTo(attachment.ContentStream);
            msg.Attachments.Add(attachment);
        }
    }
}

答案 4 :(得分:-1)

将使用放在 MailMessage 上,它会在内部处理构成附件的流

using(var msg = new MailMessage())
{
    ...
    ...
    var attachment = new Attachment(strMem, filename,contentType);
    msg.Attachments.Add(attachment);
    ...
    ...             
    msg.Send();
}