Tallan's Technology Blog

Tallan's Top Technologists Share Their Thoughts on Today's Technology Challenges

BizTalk- SMTP E-Mail: Compress Attachment in Memory

Karl Schwirz

When trying to send a message via the SMTP adapter in BizTalk we have the option of attaching messages as part of Multi-Part Messages.  If the message being attached is too large the message will fail to send.  In our application, we send email notifications of failed messages in BizTalk with the original message sent as an attachment.

An solution we devised was to compress the original message and attach it to the email.  This solution, however, presented its own considerations.

  • We didn’t want to create a temporary directory on a server to create the compressed file in.  We wanted to do all of the compression in memory.
  • Since we were compressing in memory we had to come up with a solution to attach the file to the email message.

The compression in memory is discussed in my posting on File Compression In Memory.  The post demonstrates how to name and create the archive, as well as compressing the data in memory and output a byte array which we will use.

The next step is attaching the compressed file byte array to the XLANG multi-part message we’re constructing.  We created a BinaryStreamFactory () class                                                  <REF:Tomas Restrepo Article> to hold an open stream created with the byte array.  This is necessary because  in order create and attach the XLANG Part to the message, as I’ll demonstrate below, we need to pass in a object of type IStreamFactory.

Note: You will have to import the BaseTypes and RuntimeTypes from the BizTalk Bin Folder.

using System.IO;
using Microsoft.XLANGs.BaseTypes;
using Microsoft.XLANGs.RuntimeTypes;

public class BinaryStreamFactory : RefCountedBase, IRefCountedStreamFactory
    {
        private Stream _stream;

public BinaryStreamFactory(Stream stream)
        {
            if (stream == null)
                throw new ArgumentNullException("Stream passed in is Null.");
            if (stream.Position != 0)
                stream.Position = 0;
            _stream = stream;
        }

        public Stream CreateStream()
        {
            return _stream;
        }

        public override void Dispose()
        {
            _stream.Dispose();
        }
        

    }

Now we can use these two methods to add the message to the XLANG Message.

using Microsoft.XLANGs.BaseTypes;

public static void AttachStreamToSmtpMessage(XLANGMessage xlangMsg, XLANGPart langAttach)
        {
            //Open stream reader to read the message and assign it to a string
            using (StreamReader str = new StreamReader((Stream)xlangAttach.RetrieveAs(typeof(Stream))))
            {
                string xLangPart = str.ReadToEnd();

                //Compress the file
                byte[] memBuffer = FileCompressionHelper.CompressFileAttachment(xLangPart);

                //Add the Message Part to the Multi-Part Message.
                IStreamFactory streamFactory = new BinaryStreamFactory(new MemoryStream(memBuffer));
                xlangMsg.AddPart(streamFactory, "AttachedMessage");
                xlangMsg["AttachedMessage"].SetPartProperty(typeof(ContentType), "application/zip"); 
                xlangMsg["AttachedMessage"].SetPartProperty(typeof(MIME.FileName), "AttachedMessage.zip");
            }
        }

We will take in the two parameters XLANGMessage and XLANGPart.  The XLANGMessage is the message we’re constructing and will be attaching the file to.  The XLANGPart is the message which is being originally passed through as a XMLDocument from another multi-part message.

We then convert the message into a  string, then a byte array, using the compression method referenced above, and use the byte array to input a memory stream into our BinaryStreamFactory.  Now, the message can be added to the XLANGMessage.

Note:  The part properties being set as well, the Content Type and File Name.  The File Name will be the name of the attachment as it shows up in the email, and the Content Type is what tells the email client how to open the file as a zip archive.

After you have implemented this you can now apply it to your emailing logic.  We chose to implement in an orchestration using the construct message shape.

image

We created a shape that sets the contents of the email body, takes that message and adds another message part as our attachment by passing the XLANGMessage, and the XLANG message part that is our original failed message.

Please feel free to post any questions and clarifications you may have.

Thanks to Reddy Kadasani and Thomas Babiec for their contributions to this solution.

-Karl

1 Comment. Leave new

[…] BizTalk- SMTP E-Mail: Compress Attachment in Memory […]

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

\\\