Add attachment stream on SMTP not always working

Last week I was developing a framework which needs the SMTP Mail in NAV2013. I noticed a new function on the variable (which is now a DotNet assembly) which allows you to add an attachment from a stream. Which is useful when you are storing your attachments in blobs. I started programming, but soon noticed that my email contained empty attachments…

I started searching around for possible reasons but found none. This drove me to the point that I filed a support incident with Microsoft. While preparing the incident I created a sample for them to be able to test where I also discovered the exact conditions. Below, you will find my proof of concept codeunit. This contains 5 tests that are performed:
– Creating DotNet / Add Attachment / Send in separate functions: FAILS
– All calls in 1 function: SUCCEEDS
– Adding Attachment / Send in 1 function, Creating in a separate function – all local vars: SUCCEEDS
– Separate Functions – global vars: SUCCEEDS
– Same as test 4, multiple stream attachments: SUCCEEDS

My theory was that since DotNet variables are passed by reference, it could be that Garbage Collector was run to soon on those variables, making the streams of SMTP cleared.

Basically the description of the problem is as follows:

When SMTP is used to send notifications with attachments using a stream, if the stream is created from a record that is local and the send procedure is called from another function the attachment file arrives empty.

If the record is not local, or if the send function is called from the same function, or both together, the notification arrives with the attachment without problem.

Since I was able to provide a good test scenario, Microsoft was pretty quick at confirming the issue, so just this morning I received following answer:


I’ve been debugging the code you sent earlier and I do not think it’s in the SMTP assembly. I do however think you’re right in the cleanup theory.

From what I can see when debugging then the data being sent to the SMTP assembly is correct however when it comes to the time when you want to send the document the stream is somehow empty. It seems like the stream implementation in NAV allows for a silent failure here (stream length becomes 0).

We could do a hotfix where we cache the streams in the SMTP assembly (tested that and it works) but that would mean all streams would be twice (and even more in your test case) in memory; once in AL and once in .NET. That doesn’t really seem like the right option.

I think the best option is to close it as “by design” and reshape the calling code to keep the streams alive until the sending is complete. Alternatively you can dump the data to temp files and add them as attachments. In the end it’s an interesting issue that can potentially be quite difficult to debug. Perhaps the best fix in this would be to get any query to the stream to fail after it’s gone out of scope but I don’t know if that’s even possible.


I did reply that closing this as “by design” might indeed be the best option, just not to waste any unnecessary memory and keeping streams double. I did suggest to make a knowledge base article about the workaround however.

In case someone is using Streams and SMTP Mail codeunit and gets empty attachments, remember this post and hopefully, you will not waste too much time debugging this 🙂

BTW, here is the link to the NAV Team Blog post:

2 thoughts on “Add attachment stream on SMTP not always working

  1. Pingback: Add attachment stream on SMTP not always working – 2/27, Dynamics NAV Team | Partner Compete

  2. Hello,

    Thanks for the hints.

    I have fixed the AddAttachmentStream by using System.IO.Stream .NET variable directly instead of using NAV InStream. I had to add new function to SMTP Mail accepting System.IO.Stream variable and pass to it e.g. System.IO.FileStream. By not using any conversion to NAV InStream I have succeeded to make the code that used to work in NAV 2013 to work in NAV 2013 R2 as well.

    BTW using AddAttachment from file is not always an option as I cannot force the file name in there and using temp files with strange names as an input is usually the best option.


Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.