EDUCAÇÃO E TECNOLOGIA

Mail Package deprecated – ASMA and parameterized Java map to the rescue


Motivation and introduction

I had a requirement to send messages to different mail receivers. Depending on a value
in the XML payload being sent, two different email receivers should receive the messages.

I was used to set different email receivers in the message mapping (XSLT mapping).
Depending on flags/different values in payloads, I would set different receiver addresses.
Now I had a look at Eng Swee Yeoh blog about the deprecated mail package
https://blogs.sap.com/2016/03/10/stop-using-mail-package-simplify-your-mail-receiver-adapter-scenarios/
explaining that mail package is not an option anymore.

Also in Eng Swee’s blog he hard codes the receiver email addresses in the java mapping. That is a valid option but knowing in our environment these could possibly change over time and every time I would have to touch the java mapping which I do not want to do.

In my scenario there is a mapping involved that creates an HTML table in the body of the email. I did not test this with a “pass through” scenario but it should work very similarly.

(Possible) Solution

So I came up with a combination of a parameterized java map and ASMA (Adapter Specific Message Attributes) making use of the operation mapping parameters in the iFlow/Integrated configuration to hold the actual email addresses. Any time there is a change to the receiving email addresses I can modify these easily without having to change the java map.

  • Operation mapping

In my operation mapping I set parameters for the 2 different mail receivers and the XML element name I use from the payload to set the receivers:

  • iFlow – mapping parameters

In my iFlow I am setting “SalesOrg” as the XML element I will read from the payload and I fill the different email receiver addresses:

In the Java map I use DOM to parse the payload, I write into the message log (https://blogs.sap.com/2013/09/30/writing-log-entries-to-audit-log-of-the-message-from-custom-java-mapping-program/) and read parameters from the operation mapping:

import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.Map; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import org.w3c.dom.Document; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; import com.sap.aii.mapping.api.AbstractTransformation; import com.sap.aii.mapping.api.DynamicConfiguration; import com.sap.aii.mapping.api.DynamicConfigurationKey; import com.sap.aii.mapping.api.StreamTransformationConstants; import com.sap.aii.mapping.api.StreamTransformationException; import com.sap.aii.mapping.api.TransformationInput; import com.sap.aii.mapping.api.TransformationOutput; public class SetMailReceivers extends AbstractTransformation { String tagValue; //let's create the dynamic configuration key for the recipients //we only want to set the email receivers: private static final DynamicConfigurationKey KEY_RECIPIENTS = DynamicConfigurationKey .create("http://sap.com/xi/XI/System/Mail", "THeaderTO"); @Override public void transform(TransformationInput transformationInput, TransformationOutput transformationOutput) throws StreamTransformationException { Map mapParameters = (Map) transformationInput.getInputHeader().getAll(); //get the dynamic configuration DynamicConfiguration conf = (DynamicConfiguration) mapParameters .get(StreamTransformationConstants.DYNAMIC_CONFIGURATION); try { InputStream inputstream = transformationInput.getInputPayload().getInputStream(); OutputStream outputstream = transformationOutput.getOutputPayload().getOutputStream(); //get the message ID, we need it to add a message to the monitoring message String messageID = transformationInput.getInputHeader().getMessageId(); //create an input stream to read the payload using DOM InputStream inputstreamDOM = transformationInput.getInputPayload().getInputStream(); //start reading XML with DOM Document document = createDocument(inputstreamDOM); //in the operation mapping we set the tag name that we want to read from //the payload to determine our email receivers: String elementToReadFromPayload = transformationInput.getInputParameters().getString("elementToReadFromPayload"); AddAuditLogs.execute("elementToReadFromPayload contains: " + elementToReadFromPayload, messageID, "success"); //get specific nodes with tag name contained in "elementToReadFromPayload" NodeList nl = document.getElementsByTagName(elementToReadFromPayload); //instead of "i < nl.getLength()" we just do "i < 1" - we only look at the first occurrence //of our element with tag name "elementToReadFromPayload" for(int i=0;i<1;i++){ Node messageNode = nl.item(i); String nodename = messageNode.getNodeName(); if(nodename.equals(elementToReadFromPayload)){ tagValue = messageNode.getFirstChild().getNodeValue(); //add to message monitoring log what tag we read and what it contains AddAuditLogs.execute("found Element " + nodename + " contains: " + tagValue, messageID, "success"); } } //now get the other parameters we set in the Operation mapping which will contain the //two sets of email receivers: String receivers1 = transformationInput.getInputParameters().getString("mail1"); String receivers2 = transformationInput.getInputParameters().getString("mail2"); //add to monitoring log what parameters we read and what they contain: AddAuditLogs.execute("mail1 contains: " + receivers1, messageID, "success"); AddAuditLogs.execute("mail2 contains: " + receivers2, messageID, "success"); //now put the recipients into the dynamic configuration and we are done :-) //depending on the value in the XML element we read (elementToReadFromPayload) //we now set the receivers: if (tagValue.contains("1710")) { conf.put(KEY_RECIPIENTS, receivers2); }else { conf.put(KEY_RECIPIENTS, receivers1); } // b) Just copy Input file content to Output file content byte[] b = new byte[inputstream.available()]; inputstream.read(b); outputstream.write(b); } catch(Exception exception) { getTrace().addDebugMessage(exception.getMessage()); throw new StreamTransformationException(exception.toString()); } } //create the DOM Document public static Document createDocument(InputStream inputstreamDOM) throws ParserConfigurationException, IOException, SAXException { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder db = factory.newDocumentBuilder(); Document document = db.parse(inputstreamDOM); document.getDocumentElement().normalize(); return document; } }
  • Mail receiver channel

I set ASMA in the Mail receiver channel. All possible ASMA attributes for mail receiver adapters can be found here: https://help.sap.com/viewer/5cf7d2de571a45cc81f91261668b7361/7.3.20/en-US/6b4493404f673028e10000000a1550b0.html

Under tab “General” I just set an underscore in the “To” field and hardcoded the CC: values:

Testing the scenario

Once starting the scenario and triggering a message to the mail receiver channel, we are able to see audit entries in the message log:

Checking the Dynamic Configuration we can see the respective mail receiver addresses were set

and an email was received successfully:

I hope this blog helps one or the other colleague “out there” implementing mail-to scenarios.

Best regards,
Peter

References:

https://blogs.sap.com/2016/03/10/stop-using-mail-package-simplify-your-mail-receiver-adapter-scenarios/

https://help.sap.com/viewer/5cf7d2de571a45cc81f91261668b7361/7.3.20/en-US/6b4493404f673028e10000000a1550b0.html