jpgrassi jpgrassi -4 years ago 97
C# Question

Should I dispose the stream used by MimeKit when sending e-mails with attachments?

I was playing around with MailKit/MimeKit and something is bugging me. I wanted to send e-mails with attachments using streams. MimeKit offers the

BodyBuilder
class which makes it very easy to create the body message and attach files:

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...
}
}


I generate the stream elsewhere in my code and I don't close it, so I can pass it on to MimeKit. The thing that is not clear is: Do MimeKit disposes the stream? Basically (as far as I'm aware) the consumer usually is the responsible for disposing Streams. I'm also aware that calling dispose on a MemoryStream (which I'm using basically) won't free up any resources.. but will prevent from reading/writing to it. But if, in the future, the implementations change to another type of Stream, things can get more complex.

I also dig into MikeKit source code, and found that the Stream passed in to the
AttachmentCollection.Add
gets 'added' into a
MemoryBlockStream
which inherits from Stream (and implements Dispose) so I'm supposing it get's disposed but, at this point, I'm just guessing.

Any ideas?

Answer Source

By inspecting the code on MimeKit. Specifically the two overloads:

1 - Overload that takes byte[] data, you can see that they create a stream and keep the ownership of it. That's done by creating the stream on a using block. One can assume already that the code downstream (CreateAttachment()) is not handling any Stream dispose.

2 - The overload that you mention, the stream is just passed through to CreateAttachment().

I'd say that in this case you're better off disposing it yourself if you can. That is, if it can be done only once the stream has been consumed.

In fact, after calling Add, your Stream was already consumed. All data will sit in memory once the method returns and you could dispose your stream. You can see this on LoadContent().

Just as you don't want to avoid calling Dispose because you have a MemoryStream knowingly that another stream that requires Dispose could be used later. Disposing your Stream after calling Add could be a bad idea. In case the behavior of the library changes in the future and at the time of the call to Add your stream is not consumed yet (which would be the expected behavior in my opinion).

The stream would only be Read at the time of writing the data to the NetworkSocket. In fact Streaming data, without loading it all in RAM.

In such case you'd only be able to Dispose the Stream after the Mailkit.Send was called.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download