6

我在玩 MailKit/MimeKit,有些东西困扰着我。我想使用流发送带有附件的电子邮件。MimeKit 提供的BodyBuilder类使得创建正文消息和附加文件变得非常容易:

public void SendEmail(string body, Stream attachment, string fileName)
{
    var message = new MimeMessage();
    message.From.Add(new MailboxAddress("Carl", "carl@site.com"));
    message.To.Add(new MailboxAddress("Rick", "rick@site.com"));
    message.Subject = "Things got messy...?";

    var builder = new BodyBuilder();
    builder.TextBody = body;

    builder.Attachments.Add(fileName, attachment);

    message.Body = builder.ToMessageBody();

    using (var client = new SmtpClient())
    {
        // code to send e-mail here...
    }
}

我在代码的其他地方生成流并且我没有关闭它,所以我可以将它传递给 MimeKit。不清楚的是:MimeKit 是否处理流?基本上(据我所知)消费者通常负责处理 Streams。我也知道在 MemoryStream (我基本上正在使用)上调用 dispose 不会释放任何资源..但会阻止读取/写入它。但是,如果将来实现更改为另一种类型的 Stream,事情会变得更加复杂。

我还深入研究了 MikeKit 源代码,发现传入的 StreamAttachmentCollection.Add被“添加”到了MemoryBlockStream从 Stream 继承的 a 中(并实现了 Dispose),所以我假设它被释放了,但在这一点上,我只是猜测。

有任何想法吗?

4

2 回答 2

6

通过检查 MimeKit 上的代码。特别是两个重载:

1 -需要的重载byte[] data,您可以看到他们创建了一个流并保留了它的所有权。这是通过在using block. 可以假设下游代码 ( CreateAttachment()) 没有处理任何 Stream 处置。

2-您提到的重载,流只是传递给CreateAttachment().

我会说,在这种情况下,如果可以的话,你最好自己处理它。也就是说,如果它只能在流被消费后完成。

事实上,在调用之后Add,你的 Stream 已经被消费了。一旦方法返回,所有数据都将保存在内存中,您可以处理您的流。您可以在LoadContent()上看到这一点。

就像您不想避免调用 Dispose 一样,因为您有一个 MemoryStream ,知道以后可以使用另一个需要 Dispose 的流。在调用后处理您的 StreamAdd可能是个坏主意。如果库的行为在未来发生变化并且在调用Add您的流时尚未使用(我认为这将是预期的行为)。

只有在将数据写入 NetworkSocket 时,该流才会被读取。实际上是流式传输数据,无需将其全部加载到 RAM 中。

在这种情况下,您只能在Mailkit.Send调用后处理流。

于 2017-06-12T08:53:49.710 回答
3

您不需要处置这些流。如果你愿意,你可以,但这不是必需的。

于 2017-06-12T00:16:05.407 回答