Technical Articles
Replacing the message body with an attachment
A few days ago I answered this interesting question by Florian Kube in the Questions & Answers area. It struck me that the solution might be of more general interest, so in this blog post I’m going to expand a bit on my answer.
Florian’s scenario is this: He picks up an email with a sender Mail channel. The email has an XML attachment, and it is the contents of this attachment, he wants to process. He therefore needs to replace the message body with the attached XML document, and then proceed with mapping and so forth.
I’m going to show you how to solve this problem using scripting. The code is written in Groovy, but if your prefer JavaScript, translating it is straightforward.
Methods of the Message class
Access to the body and attachments of a message is provided by the com.sap.gateway.ip.core.customdev.util.Message
object, which the runtime passes to your Groovy function. The API documentation available for this interface is available here.
The two methods, we are going to use, are getAttachments
and setBody
. The former returns a java.util.Map
object containing the message’s attachments, and the latter sets a new message body.
Extracting the attachment contents
Let us deal with the attachment first, since that is the more complicated part. The keys of the Map
returned by getAttachments
are attachment names, and the values are javax.activation.DataHandler
objects. The DataHandler
objects contain the actual attachment data. Given the scenario, we assume that the Map
contains exactly one attachment, but we do not know its key ahead of time.
In order to get the Map
’s only value without knowing its associated key, I retrieve the Collection
of all the Map
’s values and iterate it once. The code looks like this (required import
statements not shown):
Map<String, DataHandler> attachments = message.getAttachments()
Iterator<DataHandler> it = attachments.values().iterator()
DataHandler attachment = it.next()
(You could combine the three lines into a single line, if you are so inclined, but that would make the intention of the code less clear, IMHO.)
Setting the message body
The DataHandler
class offers a couple of different ways to get at the wrapped data. We are going to use the getContent
method, which returns a java.lang.Object
object. Why? Because an Object
instance is what the setBody
method of the Message
class expects. Here is the code that replaces the message body:
message.setBody(attachment.getContent())
Putting the pieces together
We are now ready to put it all together. Here is the complete script:
import com.sap.gateway.ip.core.customdev.util.Message
import java.util.Map
import java.util.Iterator
import javax.activation.DataHandler
def Message processData(Message message) {
Map<String, DataHandler> attachments = message.getAttachments()
Iterator<DataHandler> it = attachments.values().iterator()
DataHandler attachment = it.next()
message.setBody(attachment.getContent())
return message
}
In order to use it, put the code in a Script step at the very beginning of your integration flow. After this step, proceed with whatever processing your scenario requires.
How to handle messages with no attachments
Keep in mind that the script assumes that the message has exactly one attachment. If it does not have any attachments, the code will fail. Determining why it fails, is left as an exercise for the reader 🙂
If this assumption is not always met in your particular scenario, you can test for the presence of attachments, by checking whether the Map
returned by getAttachments
is empty. You do this by calling its isEmpty
method as follows:
import com.sap.gateway.ip.core.customdev.util.Message
import java.util.Map
import java.util.Iterator
import javax.activation.DataHandler
def Message processData(Message message) {
Map<String, DataHandler> attachments = message.getAttachments()
if (attachments.isEmpty()) {
// Handling of missing attachment goes here
} else {
Iterator<DataHandler> it = attachments.values().iterator()
DataHandler attachment = it.next()
message.setBody(attachment.getContent())
}
return message
}
Nice blog. Tells power of Groovy scripting .
Nice blog.
Best Regards,
Harsh B.
Hi Morten,
I am looking for a way to add an attachment generated in a groovy script (a pdf file) to the header of the message so I can use it in the receiver mailadapter.
So at the start of the script there is no attachment, just a message body with text, which is written to a pdf file using itext.
What I cannot figure out is how to pass this on to the headers. Most of the examples I see work with strings and I guess the pdf file is an object of some sort.
Thanks & Regards
Tom
Hi Tom
I'm sorry that I didn't get back to you sooner. Just in case you haven't already found a solution: You can add the PDF in Groovy with a few lines of code. I wrote a short blog post about how you do that. You can find it here.
Regards,
Morten
Hi Morten,
Is this possible to update attachment content using script ? or remove attachment?
Thanks and Regards
Eric
Hi Morten,
Thanks for the excellent blogs, I am having a strange issue. As in your previous blogs, in the first step in my Iflow I am using the script to try to create an attachment, to save the payload in that attachment, and then later in my Iflow I want to read that attachment value again to use it as the resulting message body.
But for some reason it does not seem like the attachment is being created successfully. As when I try to read it later down the line, nothing is found.
Any help would be greatly appreciated.
Hi Jacques
I suggest that your post your question in the Q&A section, using the tag "SAP Cloud Platform Integration for process services". Provide as much detail as is needed. Include, for instance, your script code. Then myself and others will have a closer look.
Regards,
Morten
Thanks Morten.
I played around with it a bit more and I got it working using the details you shared in your Blogs.
Thank you so much. Thanks for the great blogs. Keep up the good work.
Kind Regards
Jacques Otto
Hi Jacques
I'm very happy to hear that 🙂
Have a nice weekend,
Morten
Hello Morten,
How to handle more than one attachments in the script.
Thanks,
Mohan
Hi Mohan
If you have multiple attachments, and you want to replace the payload with one of them, you need some way of identifying that particular attachment. You would need to take a look at the keys in the attachments map, and determine which one to select based on those keys.
Regards,
Morten
Hello Morten,
Thanks for the reply.
I am able to send one attachment from SOAP UI to the Iflow and i am able to receive to my email with attachment. Now i am trying to test with multiple attachments...but i am able to receive the only one. can you please tell me how to receive all the attachments?
Thanks,
Mohan
Hello again
Please post this as a question in the Q&A section, and provide all the details of your situation.
Regards,
Morten
Hi Experts,
Can any one give me the script to read the attachment id 72488 from below response. I need to use this in another call. Thank you.
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices">
<entry>
<content type="application/xml">
<m:properties>
<d:key>Attachment/attachmentId=72488</d:key>
<d:status>OK</d:status>
<d:editStatus>UPSERTED</d:editStatus>
<d:message>Upserted successfully</d:message>
<d:index m:type="Edm.Int32">0</d:index>
<d:httpCode m:type="Edm.Int32">200</d:httpCode>
<d:inlineResults m:type="Bag(SFOData.UpsertResult)"/>
</m:properties>
</content>
</entry>
</feed>
Thanks.
Hi,
did you manage to solve this?
Hi Morten Wittrock
one step forward. could you help me with this question ?
Mail to SFTP - how to read the attachment name | SAP Community
Hi Morten Wittrock
We are having issue in reading attachment from mail sender as groovy provided is reading inline embedded images such as signature in the mail also as attachment along with original attachments. Can you please guide us in restricting reading attachment only to original attachment of mail.
Regards,
Sindhuja.