Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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 BodyBuilderclass 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", "[email protected]"));
    message.To.Add(new MailboxAddress("Rick", "[email protected]"));
    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?

like image 960
jpgrassi Avatar asked Jun 11 '17 16:06

jpgrassi


2 Answers

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.

like image 129
Bruno Garcia Avatar answered Sep 21 '22 18:09

Bruno Garcia


You don't need to dispose those streams. You can if you want, but it's not necessary.

like image 40
jstedfast Avatar answered Sep 25 '22 18:09

jstedfast