Processing multiple email attachments with BizTalk Server 2009 using POP3 adapter and orchestration
This article will describe how to:
– Receive emails through the standard BizTalk POP3 adapter.
– Process multiple email attachments.
– How to keep track of the filename for the individual attachments.
How long time does it take me to implement this?
– Receiving emails through the standard BizTalk POP3 adapter is a very simple configuration, which can be done within 15 minutes. Everything is configured using only the BizTalk Administration Console. No coding skills needed.
– Processing any number of email attachments requires a bit more BizTalk development, but still no coding skills necessary. This article will show how to solve this using standard BizTalk functionality such as multi part messages in an orchestration. This task can be done within 1 hour.
– Accessing context of each email attachment requires a few lines of code. As an example we’ll read manipulate the filename of each attachment, which can be done within 1 hour.
The entire solution can be done within 3 hours.
– Configuring the POP3 adapter on the receive location:
In most BizTalk scenarios incoming messages only have one part, which is also the body part. Of course this is not always the case. When receiving an email with multiple file attachments using the standard BizTalk POP3 Adapter, BizTalk will create one BizTalk message with multiple parts.
By default the POP3 adapter will determine the body part based on a Body Part Selection Algorithm (MSDN Documentation). The reason for paying attention to which part of the message is the body part is because, unlike all other message parts, the body part is being disassembled, validated, mapped, etc.
For this article, let’s say I only want to process the email attachments as raw messages .Therefore I’m not doing any disassembling, validation, mapping, etc.
Still, I explicitly want the body part to be the first part of the message, so I’m setting Body Part Index to 1(See POP3 Transport Properties image). The reason for that has nothing to do with the actual receive process of the email message; Instead, this is done to please the orchestration which is going to subscribe to the one BizTalk message, in which I’ll need to know which part index is the body part. I’ll discuss why in the Multi-part messages section.
When receiving messages through this receive location now, I expect one message to be submitted to the BizTalk MessageBox with x-number of parts, and the first part of the message as the Body Part.
– Configuring the orchestration for processing my email attachments
o Multi-part messages:
To receive x-number of parts into my orchestration, I’ll need to declare one Multi-part Message Type with only one single Message Part. And I’ll set this Message Part as the body part.
Now when receiving the original message with multiple parts from the Reciever Process, the orchestration engine will automatically create the number of parts corresponding to the incoming message. Nice, huh?
A common pitfall is not considering that Message Parts in orchestrations are index based, meaning the index of a Message Part is a result of the Message Part creation order. The sequence of the Message Parts listed underneath the Multi-part Message Type corresponds to individual indexes.
To see/adjust the index order, you can open the orchestration in a text-editor and navigate to your Multi-part Message Type.
Now back to the email processing. I’m pretty happy right now, because I know that my incoming message will always have its first part set as the body part, which is exactly what I promised my orchestration.
If I had not set my body part to 1 in the adapter configuration on the receive location, I would have risked having the adapter choose e.g. part two as my body part, thus the orchestration would fail because of mismatching part indexes, not receiving the expected part as body part.
This is also why a lot of people working with this (including me) have met this error message:
Multi-part message ‘MultipartType_1’ has body part ‘MessagePart_2’, expected body part ‘MessagePart_1’.
o Sending all parts out as files:
Keeping in mind that the orchestration engine just created x-number of parts we want to loop through all these parts and send out every single one of them to our file destination.
Once we’ve accomplished this, our email process for receiving x-number of email attachments and sent them out as files, has been implemented.
So first step in the expression shape is to set a Microsoft.XLANGs.BaseTypes.XLANGMessage variable to the value of our input message.
xlangMsg = msgRaw;
msgRaw is just a regular orchestration message of the Multi-part Message Type.
Having the xlangMsg we can loop trough all the parts of this message. For each part we’ll assign the msgOut. msgOut is just a regular orchestration message of type System.Xml.XmlDocument.
msgOut = xlangMsg[count];
And that’s it. Now we can add a send shape sending out outMsg. And someone might argue that I did write one line of code there, but I’d say that using XLANGMessages is just cool so it doesn’t count.
o Accessing the parts:
So what if we wanted to do a little context fun on each individual part. An example could be to be able to set the output filename from the source filename.
This could be useful to determine if the current part is a file attachment. This could be accomplished by looping through all parts, processing only the actual attachments and not the email body text by simply asking if the property MIME.Filename exists for this part.
In the implementation we’ll need a utility function in an external assembly which will look something like this:
public static string GetXLANGPartProperty(XLANGPart part, Type t)
This method returns the given property type of this part.
Now this method should be called from inside an expression shape in our orchestration with an XLANGPart and a Type.
First, we’ll need to extract the XLANGPart from our XLANGMessage by simply creating a new orchestration variable of type Microsoft.XLANGs.BaseTypes.XLANGPart and then assign it inside the loop by doing:
xlangPart = xlangMsg[count];
Secondly, we’ll need to pass a Type to the method. In this case we want to retrieve the source filename, which is stored in context within the MIME.Filename property type. And this is what we’ll pass. Note that you’ll need a reference to Microsoft.BizTalk.GlobalPropertySchemas in order for the Orchestration to recognize this type.
So now that we’re able to extract the source filename we can set up a dynamic send port in our orchestration to send out every part with e.g. SourceFileName + “IWASCHANGED”.txt as the filename.