BizTalk 2010 POP3 Attachement Pipeline filename issue

For BizTalk 2010, I am using the sample POP3 Pipeline to debatch the attachments from an email that was posted on the wiki.

http://social.technet.microsoft.com/wiki/contents/articles/21001.biztalk-server-how-to-extract-email-attachments-by-pipeline.aspx

In this example everything is working fine and I can set the values for the filename perfectly, BUT when the send port picks this up we are getting duplicate names for all the attachments.

So as example the send port file name format is the following "POP3Msg_%MessageID%.%SourceFileName%"; so for each message it should be the messagid prefix with the original source file name from the message. I attach CSV, JPG and other files together in the same email message. It always outputs each file but with the same SourceFileName portion. In the code I write to the event log and I can see that the values for the filename are being set and I can write them to the event log but it is not being used when outputting to the file system on BizTalk. Does anyone else see a problem here or why it would take the "first" name and not change per message?

The result looks like this. The highlighted one is a PNG and the other is a CSV. Notice that the CSV name is the one used for both.

In the event log here is what I see for each file:

Custom POP3 Attachment Processing

=======================================

Initial discovered File Name: image001.png

Resulting File Name: image001.png

Current MIME Content Type: image/png

Current Charset:

Outbound Message

=======================================

outMsg Filename: image001.png

outMsg Body Part Filename: image001.png

outMsg Content Type: image/png

outMsg Charset:

----------------------------------------------------------------------------------

Second File:

Custom POP3 Attachment Processing

=======================================

Initial discovered File Name: Duplicate Order Test 7-1.csv

Resulting File Name: Duplicate Order Test 7-1.csv

Current MIME Content Type: application/octet-stream

Current Charset:

Outbound Message

=======================================

outMsg Filename: Duplicate Order Test 7-1.csv

outMsg Body Part Filename: Duplicate Order Test 7-1.csv

outMsg Content Type: application/octet-stream

outMsg Charset:




  • Edited by Jazzy Wednesday, July 01, 2015 9:17 PM Attaching the image
July 1st, 2015 9:09pm

If the POP3 message has multiple parts, then there is a bug maybe in the Pipeline processing that is setting the FILE.ReceivedFileName property to probably the first file name.

FILE.ReceivedFileName, as ready by %SourceFileName% is a MessageContext Property so there can be only one.

You would need to look at each Part Context which is where the MIME disassembler should be writing the MIME part file name to.

So, what you are seeing is correct for BizTalk, but not for your process.
Free Windows Admin Tool Kit Click here and download it now
July 6th, 2015 11:08pm

Hi Jazzy,

Did you check comments of that article?

I think you need to change code to use 

outMsg.Context.Write("ReceivedFileName", "http://schemas.microsoft.com/BizTalk/2003/file-properties", currentPart.PartProperties.Read("FileName", "http://schemas.microsoft.com/BizTalk/2003/mime-properties" ));

instead of 

outMsg.Context.Write("ReceivedFileName", "http://schemas.microsoft.com/BizTalk/2003/file-properties", partName);


July 7th, 2015 5:24am

Ok, after some debugging with another project I discovered the bug in the original code. EVERYONE is making the same mistake. It is related to the following lines when creating the outbound message.

IBaseMessage outMsg;
 
outMsg = pc.GetMessageFactory().CreateMessage();
outMsg.AddPart("Body", pc.GetMessageFactory().CreateMessagePart(), true);
 
outMsg.Context = inmsg.Context;

That last line is what is causing the problem. What is happening is that you are copying a reference to the inbound context and not making a true duplicate of the context. So any changes you make apply to any message that uses that reference (and in the case of multiple attachments, they all get the last filename and not their own individual names). I figured this out when I would write event log messages after assigning all the messages to the queue and checking again. I would see several messages all with the last file name. To correct this, you want to use code similar to the following to truly duplicate the context.

IBaseMessage outMsg;
outMsg = pc.GetMessageFactory().CreateMessage();
// Usually below is not necessary, but just in case
if (outMsg.Context == null)
{
   outMsg.Context = pc.GetMessageFactory().CreateMessageContext();
}

outMsg.AddPart("Body", pc.GetMessageFactory().CreateMessagePart(), true);
// Usually below is not necessary, but just in case
if (outMsg.GetPart("Body").PartProperties == null)
{
   outMsg.GetPart("Body").PartProperties = pc.GetMessageFactory().CreatePropertyBag();
}

Then later you can duplicate all the existing properties to the new message. This code is code I found on the internet somewhere.

System.Text.StringBuilder logMsg = new StringBuilder(4000);
logMsg.AppendLine(Environment.NewLine + "Context Variables: ");
logMsg.AppendLine("=======================================");

for (int j = 0; j < inmsg.Context.CountProperties; j++)
{

    string currentName;

    string currentNamespace;

    object objin = inmsg.Context.ReadAt(j, out currentName, out currentNamespace);

    logMsg.AppendLine("Name: " + currentName);
    logMsg.AppendLine("Namespace: " + currentNamespace);
    logMsg.AppendLine("Value: " + objin.ToString());
    logMsg.AppendLine("--------------------------------------");

    outMsg.Context.Write(currentName, currentNamespace, objin);
    
	if (inmsg.Context.IsPromoted(currentName, currentNamespace))
    {

        outMsg.Context.Promote(currentName, currentNamespace, objin);

    }
    
}

logMsg.AppendLine(Environment.NewLine + "Message Part Variables: ");
logMsg.AppendLine("=======================================");
for (int j = 0; j < currentPart.PartProperties.CountProperties; j++)
{

    string currentName;

    string currentNamespace;

    object objin = currentPart.PartProperties.ReadAt(j, out currentName, out currentNamespace);
    
    logMsg.AppendLine("Name: " + currentName);
    logMsg.AppendLine("Namespace: " + currentNamespace);
    logMsg.AppendLine("Value: " + objin.ToString());
    logMsg.AppendLine("--------------------------------------");

    outMsg.GetPart("Body").PartProperties.Write(currentName, currentNamespace, objin);
    
}

So in the end values you set on this message say and you don't get that renaming problem like I mentioned in the original question. There is a class to truly copy the context, however the documentation says it is not for us to use in code (though there is probably no harm in doing so). The community note on this method mentions this issue as well.
https://msdn.microsoft.com/en-us/library/microsoft.biztalk.component.interop.pipelineutil.clonemessagecontext(v=bts.70).aspx


  • Marked as answer by Jazzy Monday, July 13, 2015 11:22 PM
Free Windows Admin Tool Kit Click here and download it now
July 13th, 2015 11:22pm

This topic is archived. No further replies will be accepted.

Other recent topics Other recent topics