Sunday, May 25, 2014

Sending email with attachments in Oracle SOA 11g

Here I show one generic BPLE service which will send the email with attachment.  


Generic Email Service Interface


The service interface is defined by the below xsd file.  In the request message apart from email to, from, subject and body elements there is one array of attachment elements which are sent with the email.

<element name="NotificationRequest">
 <complexType>
  <sequence>
   <element name="From" type="string" minOccurs="0"/>
   <element name="To" type="string"/>
   <element name="CC" type="string" minOccurs="0"/>
   <element name="Subject" type="string"/>
   <element name="Body" type="string" minOccurs="0"/>
   <element name="Attachment" type="tns:AttachmentType" minOccurs="0" maxOccurs="unbounded"/>
  </sequence>
 </complexType>
</element>
<complexType name="AttachmentType">
 <sequence>
  <element name="MimeType" type="string"/>
  <element name="AttachmentContent" type="anyType"/>
  <element name="AttachmentName" type="string"/>
  <element name="ContentEncoding" type="string"/>
 </sequence>
</complexType> 



Oracle Notification Service


This service will use Notification service provided by Oracle SOA 11g. Notification service uses Oracle User Messaging Service to send email, SMS, IM and etc. notification to the recipients.   Notification service can be invoked from BPEL process.   From JDeveloper you can choose the different notification channels.  For sending email you need to choose Email as below.


After dragging and dropping Email into BPEL process, NotificationService.wsdl and NotificationService.xsd are added to the project.  These wsdl and xsd files define the interface to Oracle User Messaging Service.  For request message which sends email is defined as EmailPayloadType.  The key to send the email with attachments is to populate the appropriate values in EmailPayload.

EmailPayloadType defines the request message for invoking Oracle Notification service to send the email.  
<xsd:complexType name="ContentType">
 <xsd:sequence>
  <xsd:element name="MimeType" type="xsd:string" default="text/plain" minOccurs="0"/>
  <xsd:element name="ContentBody" type="xsd:anyType" nillable="true"/>
  <xsd:element name="ContentEncoding" type="xsd:string" nillable="true"/>
 </xsd:sequence>
</xsd:complexType>

ContentType defines the email content.  Note here that ContentBody is defined as anyType.  In order to include the attachments in email there are two things needed to be done:

  • MimeType should be set as: multipart/mixed.   
  • ContentBody will use MultiPartType.


<xsd:complexType name="MultiPartType">
 <xsd:sequence>
  <xsd:element name="BodyPart" type="BodyPartType" maxOccurs="unbounded"/>
 </xsd:sequence>
</xsd:complexType>

The MultiPartType is an array of BodyPartType.  First element in thus array is the email body itself and the subsequent elements are the attachments for the email.
<xsd:complexType name="BodyPartType">
 <xsd:sequence>
  <xsd:element name="MimeType" type="xsd:string" default="text/plain" minOccurs="0"/>
  <xsd:element name="ContentBody" type="xsd:anyType" nillable="true"/>
  <xsd:element name="BodyPartName" type="xsd:string"/>
  <xsd:element name="Disposition" type="dispositionEnum" default="inline" minOccurs="0"/>
  <xsd:element name="ContentId" type="xsd:string" minOccurs="0"/>
  <xsd:element name="ContentEncoding" type="contentEncodingEnum" nillable="true"/>
  <xsd:element name="AttachmentContentEnclosed" type="xsd:boolean" default="true" minOccurs="0"/>
 </xsd:sequence>
</xsd:complexType>

BodyPartType defines the email body and attachment for the email.   MimeType specifies the type of data in email.   If the email body is HTML email the MimeType of email body(first Body Part) would be: "text/html; charset=UTF-8".   Depending on the attachments with the email the MimeType in BodyParts for attachments can be set the values of proper Mime type.   
Some of such values are shown below:
image/tiff;            - tiff image file
image/jpeg;            - jpeg image file   
application/pdf;       - PDF file
application/xml;       - XML file  
application/msword;    - MS Word file

ContentBody in BodyPartType will be the actual data for email body and attachment.  For the attachment the ContentEncoding will be set as base64. BodyPartName will be set as the file name for the attachment.

The below is one example of EmailPayload message which are populated with the data.  The email will have one attachment of .tiff image file whose name is Testing.tif.
<EmailPayload xsi:type="def:EmailPayloadType">
 <FromAccountName>Default</FromAccountName>
 <To>Mark_ke_chen@yahoo.com</To>
 <ReplyToAddress/>
 <Subject>Tesyimg email with one attachement</Subject>
 <Content>
  <ns:MimeType>multipart/mixed</ns:MimeType>
  <ns:ContentBody>
   <ns:MultiPart>
    <ns:BodyPart>
     <ns:MimeType>text/html; charset=UTF-8</ns:MimeType>
     <ns:ContentBody>
      ......  Email body here
     </ns:ContentBody>
     <ns:BodyPartName/>
     <Disposition>inline</Disposition>
    </ns:BodyPart>
    <ns:BodyPart>
     <ns:MimeType>image/tiff;</ns:MimeType>
     <ns:ContentBody>
      .... Tiff image data
     </ns:ContentBody>
     <ns:BodyPartName>Testing.tif</ns:BodyPartName>
     <ns:ContentEncoding>base64</ns:ContentEncoding>
     <Disposition>attachment</Disposition>
    </ns:BodyPart>
   </ns:MultiPart>
  </ns:ContentBody>
 </Content>
 <Cc/>
 <Bcc/>
 <NotificationContext/>
</EmailPayload>

Here use xlst transformation to populate the Content element.
<copy>
 <from expression="ora:processXSLT('xsl/EmailContentBodyTransform.xsl', $NotificationRequest.payload)"/>

 <to variable="varNotificationReq"
  part="EmailPayload"
  query="/EmailPayload/ns1:Content"/>
</copy>

The below is the snippet of XSLT transformation.
<ns:Content>
 <ns:MimeType>multipart/mixed</ns:MimeType>
 <ns:ContentBody>
  <ns:MultiPart>
   <ns:BodyPart>
    <ns:MimeType >text/html; charset=UTF-8</ns:MimeType>
    <ns:ContentBody>
     <xsl:value-of select="/*[local-name()='NotificationRequest']/*[local-name()='Body']"/>
    </ns:ContentBody>
    <ns:BodyPartName/>
   </ns:BodyPart>
   <xsl:for-each select="/*[local-name()='NotificationRequest']/*[local-name()='Attachment']">
    <ns:BodyPart >
     <ns:MimeType>
      <xsl:value-of select="./*[local-name()='MimeType']"/>
     </ns:MimeType>
     <ns:ContentBody >
      <xsl:value-of select="./*[local-name()='AttachmentContent']"/>
     </ns:ContentBody>
     <ns:BodyPartName>
      <xsl:value-of select="./*[local-name()='AttachmentName']"/>
     </ns:BodyPartName>
     <ns:ContentEncoding>
      <xsl:value-of select="./*[local-name()='ContentEncoding']"/>
     </ns:ContentEncoding>
    </ns:BodyPart>
   </xsl:for-each>
  </ns:MultiPart>
 </ns:ContentBody>
</ns:Content>


Testing Email service with attachments


In order to test this generic email service I have another BPEL service which will populate email body and attachment and then invoke the generic email service.  The below shows the two assign activities used in the BPEL to set the email body and email attachment.

<assign name="AssignEmailBody">
  <copy>
 <from expression="ora:toCDATA(  ora:processXSLT('xsl/TransformHTMLEmailBody.xsl', $Request.request, bpws:getVariableData('Parameters')) )"/>
 <to variable="EmailNotificationRequest" part="payload"
  query="/ns4:NotificationRequest/ns4:Body"/>
  </copy>
</assign>

<assign name="AssignEmailAttachment">
  <copy>
 <from expression="ora:readFile( $ImageFileName) )"/>
 <to variable="EmailNotificationRequest" part="payload"
  query="/ns4:NotificationRequest/ns4:Attachment/ns4:AttachmentContent"/>
  </copy>
</assign>

One assign is used to set the email body. Since the email is HTML format the assign activity uses ora:toCDATA to wrap the html content.   
Another assign activity uses orad:readFile function to read the physical file which is going to attach in the email.

No comments:

Post a Comment