Monday, September 18, 2006

Limitations with the BizTalk SMTP Adapter

This post discusses a recent project I worked on where we used the BizTalk 2004 SMTP adapter to send emails from within our orchestration. Here is an outline of the orchestration:

1) Orchestration was triggered twice a day by use of the Scheduled Task Adapter
2) Sends a message to a custom Web service requesting a list of reports from the SharePoint repository. This Web service uses the SharePoint API to do the retrieval
3) Sends a message to a custom Web service requesting a list of email recipients from the SharePoint repository. Again, this Web service uses the SharePoint API to do the retrieval
4) Sends the list of reports embedded inside the email body as HTML to the email recipients.

We found the following exception in the Event Viewer when running this orchestration with an email recipient list with greater than 256 characters:

Event Type: Error
Event Source: XLANG/s
Description: Uncaught exception terminated service
Failed while attempting to send message 'SummaryEmail'.
Exception type: SendFailedException
Source: Microsoft.XLANGs.BizTalk.Engine
Target Site: Void WriteMessageState(Microsoft.BizTalk.Interop.IBTPEPInfoLookup, System.Guid, Microsoft.XLANGs.BaseTypes.XLANGMessage, Microsoft.XLANGs.Core.Segment, System.String, System.String, System.Collections.IList, Boolean, System.Collections.IList)

Additional error information: The property 'OutboundTransportLocation' has a value with length greater than 256 characters.

Exception type: COMException
Source: Target Site: Void PostToSendPort(System.Guid ByRef, Microsoft.BizTalk.Agent.Interop.IBTMessageBatch, Microsoft.BizTalk.Agent.Interop.IBTMessage, System.String, System.String, Microsoft.BizTalk.Interop.IBTMMessageList ByRef)

Here are the basic steps I took to resolve this issue:

1) The email distribution list returned from the Web service was a simple comma separated string. This string was converted to a collection of strings.
2) A Loop shape was used to loop over each string (email address) and send the email.

The relative section of the orchestration is shown here:

I borrowed ideas from Richard Seroter for the code inside the Assign Summary and Set Port Properties Expression shapes:

tempDoc = (System.Xml.XmlDocument)OutgoingEmailVesselReport;
HtmlSummaryReports = XmlToHtmlStringConverter.Convert(tempDoc, EmailStylesheetLocation);
SummaryEmail.EmailBody = new RawString(HtmlSummaryReports);
SummaryEmail(SMTP.Subject) = Part.SetContentType(SummaryEmail.EmailBody, "text/html");

EmailAddress = StringUtils.GetString(EmailDistributionCollection, LoopCounter);
AppendedEmailAddress = "mailto:" + EmailAddress;
ReportPort(Microsoft.XLANGs.BaseTypes.Address) = AppendedEmailAddress;
LoopCounter = LoopCounter + 1;

I didn't use the accessor operator to access the email strings inside the EmailDistributionCollection string collection object because this operator wasn't recognized by the BizTalk editor. I tried to use an enumerator, but the enumerator is not a serialized type, so I put a number of the shapes inside an atomic scope, but you cannot put a Send shape inside an atomic scope...

The Send Port's type uses a Send Pipeline that uses a MIME/SMIME encoder at the Encode stage. You need to reference this Send Pipeline in the "Send Pipeline" property of your Send Port.

Wednesday, September 13, 2006

I'll be posting my regular thoughts on the state of the software industry. I'm currently working with C#, .NET and BizTalk so expect a few posts on these subjects as well.