Manipulating messages in the MIME domain

A MIME message does not need to be received over a particular transport. For example, a message can be received over HTTP by using an HTTPInput node, or over WebSphere® MQ by using an MQInput node. The MIME parser is used to process a message if the message domain is set to MIME in the input node properties, or if you are using WebSphere MQ, and the MQRFH2 header has a message domain of MIME.

This topic explains how to deal with messages that belong to the MIME domain, and are parsed by the MIME parser. Use this information in conjunction with the information in Manipulating message body content.

You can manipulate the logical tree using ESQL before passing the message on to other nodes in the message flow. A message flow can also create a MIME domain tree using ESQL. When a MIME domain message reaches an output node, the MIME parser is called to rebuild the bit stream from the logical tree.

The following examples show how to manipulate MIME messages:

Creating a new MIME tree

A message flow often receives, modifies, and returns a MIME message. In this case, you can work with the valid MIME tree that is created when the input message is parsed. If a message flow receives input from another domain, such as XMLNS, and returns a MIME message, you must create a valid MIME tree. Use the following ESQL example in a Compute node to create the top-level structure for a single-part MIME tree:
CREATE FIELD OutputRoot.MIME TYPE Name;
DECLARE M REFERENCE TO OutputRoot.MIME;
CREATE LASTCHILD OF M TYPE Name NAME 'Data';
The message flow must also ensure that the MIME Content-Type is set correctly, as explained in Managing Content-Type. The flow must then add the message data into the MIME tree. The following ESQL examples show how you can do this. In each case, a Data element is created with the domain BLOB.
  • A bit stream from another part of the tree is used. This example shows how a bit stream could be created from an XML message that is received by the message flow. The flow then invokes the BLOB parser to store the data under the Data element.
     DECLARE partData BLOB ASBITSTREAM(InputRoot.XMLNS);
     CREATE LASTCHILD OF M.Data DOMAIN('BLOB') PARSE(partData);
    
  • Instead of parsing the bit stream, create the new structure, then attach the data to it, as shown in this ESQL example:
    DECLARE partData BLOB ASBITSTREAM(InputRoot.XMLNS);
    CREATE LASTCHILD OF M.Data DOMAIN('BLOB') NAME 'BLOB';
    CREATE LASTCHILD OF M.Data.BLOB NAME 'BLOB' VALUE partData;
    

Both of these approaches create the same tree structure. The first approach is better because explicit knowledge of the tree structure that the BLOB parser requires is not built into the flow.

More commonly, the Compute node must build a tree for a multipart MIME document. The following ESQL example shows how you can do this, including setting the top-level Content-Type property.
DECLARE part1Data BLOB ASBITSTREAM(InputRoot.XMLNS, InputProperties.Encoding, InputProperties.CodedCharSetId);

SET OutputRoot.Properties.ContentType = 'multipart/related; boundary=myBoundary';

CREATE FIELD OutputRoot.MIME TYPE Name;
DECLARE M REFERENCE TO OutputRoot.MIME;
CREATE LASTCHILD OF M TYPE Name NAME 'Parts';
CREATE LASTCHILD OF M.Parts TYPE Name NAME 'Part'; 
DECLARE P1 REFERENCE TO M.Parts.Part[1];  
CREATE FIELD P1."Content-Type" TYPE NameValue VALUE 'text/plain';
CREATE FIELD P1."Content-Id"   TYPE NameValue VALUE 'part one'; 
CREATE LASTCHILD OF P1 TYPE Name NAME 'Data'; 
CREATE LASTCHILD OF P1.Data DOMAIN('BLOB') PARSE(part1Data);

CREATE LASTCHILD OF M.Parts TYPE Name NAME 'Part'; 
DECLARE P2 REFERENCE TO M.Parts.Part[2];  
CREATE FIELD P2."Content-Type" TYPE NameValue VALUE 'text/plain';
CREATE FIELD P2."Content-Id"   TYPE NameValue VALUE 'part two'; 
CREATE LASTCHILD OF P2 TYPE Name NAME 'Data'; 
CREATE LASTCHILD OF P2.Data DOMAIN('BLOB') PARSE(part2Data);

Modifying an existing MIME tree

This ESQL example adds a new MIME part to an existing multipart MIME message. If the message is not multipart, it is not modified.
SET OutputRoot = InputRoot;

-- Check to see if the MIME message is multipart or not.
IF LOWER(InputProperties.ContentType) LIKE 'multipart/%'
THEN
  CREATE LASTCHILD OF OutputRoot.MIME.Parts NAME 'Part';

  DECLARE P REFERENCE TO OutputRoot.MIME.Parts.[<];
  CREATE FIELD P."Content-Type" TYPE NameValue VALUE 'text/xml';
  CREATE FIELD P."Content-ID"   TYPE NameValue VALUE 'new part';
  CREATE LASTCHILD OF P TYPE Name NAME 'Data';

  -- This is an artificial way of creating some BLOB data. 
  DECLARE newBlob BLOB '4f6e652074776f2074687265650d0a';
  CREATE LASTCHILD OF P.Data DOMAIN('BLOB') PARSE(newBlob);
END IF;
If you receive a MIME message, for example; through an EmailInput node, and you know the format of your message, you might want to reparse the message. For example:
CREATE LASTCHILD OF OutputRoot.XMLNSC.emailData  DOMAIN('XMLNSC') 
PARSE(InputRoot.MIME.Data.BLOB.BLOB,InputProperties.Encoding,
InputProperties.CodedCharSetId);

Managing Content-Type

When you create a new MIME message tree, or when you modify the value of the MIME boundary string, make sure that the MIME Content-Type header is set correctly by setting the ContentType value in the integration node Properties subtree. The following example shows how to set the ContentType value for a MIME part with simple content:
SET OutputRoot.Properties.ContentType = 'text/plain';
Do not set the Content-Type value directly in the MIME tree or HTTP trees because the value is ignored or used inconsistently.
When you receive a MIME message, you can filter or route the message content based on the content-Type. The following example shows an XPath query that can be used in a Route node to filter the content based on whether the message contains an attachment or not:
starts-with($Root/MIME/Content-Type,"multipart")