cancel
Showing results for 
Search instead for 
Did you mean: 

sender mail adapter - attachment name

Former Member
0 Kudos

Hi there

We have configured a sender email adapter to receive text/csv attachments and save them to a file system. What we are having a problem with is reading the attachment name. So we are using Dynamis Configuration to create the file name using the subject line - Which is not ideal. Ideally we would like to use the same name as the origianl attachment but haven't found any way of doing that. We even tried using Content-type in the Variable Header (XHeaderName1) suing variable transport binding but it doesn't show up in the Dynamic Config part of the SOAP message.

Is there any way of reading the name of the file attachment? We are on PI release 7.0.

Any help would be appreciated.

Cheers

Salil

Accepted Solutions (1)

Accepted Solutions (1)

stefan_grube
Active Contributor
0 Kudos

Wait for SP12, then you can read the attachment name with a self-written adapter module with the method getContentType.

There is no standard way for this.

Regards

Stefan

Former Member
0 Kudos

Stefan,

can you plz elaborate on your idea?

I guess you are referring to PI 7.0 SP12. I'm on XI 3.0, what is the equivalent, SP20?

I appreciate your inputs/links.

Salil, were you able to get the attachement name using adapter module? Can you please share the solution with the community?

thx

praveen

Answers (4)

Answers (4)

Former Member
0 Kudos

Hi Salil,

I have a SOAP-PI-Proxy synchronous scenario.

I need to set the name of excel attachment getting created in PI .

Could you please guide?

https://scn.sap.com/thread/3955194

Thanks,

Indu Khurana.

Former Member
0 Kudos

Hi Salil.

I'm new in this forum. I'm a XI developer and I'm working for the first time whit a Mail Adapter.

I need to save the mail attachement in a file system. Can you tell me how do you reach this goal? Did you use an ejb or in other way?

Thank's in advance,

Daniela.

Former Member
0 Kudos

Hi Praveen

Yes, I was able to retrieve the attachment name from the email adapter by writing an adapter module. Obviously this only works when you are on SP20 for XI 3.0 or SP12 for XI 7.0.

Here is the code (very basic - since I have no experience in JAVA) from the adapter module . All this does is pass the filename to Dynamic Configuration to be picked up later.

Regards

Salil

/*

  • Created on Jul 19, 2007

*

  • To change the template for this generated file go to

  • Window>Preferences>Java>Code Generation>Code and Comments

*/

package emailPackage;

import javax.ejb.CreateException;

import javax.ejb.SessionBean;

import javax.ejb.SessionContext;

import com.sap.aii.af.mp.module.*;

import com.sap.aii.af.ra.ms.api.*;

/**

  • @author Salil.Mehta

  • To change the template for this generated type comment go to

  • Window>Preferences>Java>Code Generation>Code and Comments

  • @ejbHome<{com.sap.aii.af.mp.module.ModuleHome}>

  • @ejbLocal<{com.sap.aii.af.mp.module.ModuleLocal}>

  • @ejbLocalHome<{com.sap.aii.af.mp.module.ModuleLocalHome}>

  • @ejbRemote<{com.sap.aii.af.mp.module.ModuleRemote}>

  • @stateless

*/

public class emailClass implements SessionBean, Module{

private SessionContext myContext;

public void ejbRemove() {

}

public void ejbActivate() {

}

public void ejbPassivate() {

}

public void setSessionContext(SessionContext context) {

myContext = context;

}

public void ejbCreate() throws CreateException{

}

public ModuleData process(ModuleContext moduleContext,

ModuleData inputModuleData)

throws ModuleException{

// put your code here

try {

Message msg = (Message) inputModuleData.getPrincipalData();

TextPayload payload = msg.getDocument();

// This gets the content in the attachment

String attname = payload.getContentType();

// Unfotunately the ContentType looks like

// - application/octet-stream;name="filename.csv" -

// So we have to get the filename from there

// Step 1 - replace all quotes with spaces

String quoteMark = "\"";

String space = "";

String newAttachment = attname.replaceAll(quoteMark, space);

// Step 2 - Now that we have replaced the quotes let's pick up the file name

String splCharacter = "=";

int ind = newAttachment.lastIndexOf(splCharacter) + 1;

String fileName = newAttachment.substring(ind, newAttachment.length());

// Step 3 - Set this filename in the Dynamic configuration of the message

msg.setMessageProperty("http://xyz.com/email", "FileName", fileName);

inputModuleData.setPrincipalData(msg);

} catch (Exception e) {

ModuleException me = new ModuleException(e);

throw me;

}

return inputModuleData;

}

}

Former Member
0 Kudos

Thank you very much Salil.

I've question, why does this piece work only on P 7.0 SP12 or XI 3.0 SP20? Adapter modules can be written for earlier SPs as well, can they not be?

We are currently on XI 3.0 SP17, planning to upgrading to PI 7.0 SP12 soon.

Will your module not work XI 3.0 SP17?

thanks

praveen

stefan_grube
Active Contributor
0 Kudos

Due to a bug the filename will not be provided by the method payload.getContentType();

You get only (in the example) "application/octet-stream"

The bugfix comes with SP20/12.

Regards

Stefan

Former Member
0 Kudos

Salil, how can I use your code to keep the attach name on mail adaptar ?

Please provide me a step by step solution.

Thanks

Former Member
0 Kudos

Hi Vitor

Here is the solution -

1. Use the payloadSwap Bean as described in the blog below to ensure that the attachment of the email becomes the Message payload instead of the body ....

/people/michal.krawczyk2/blog/2005/12/18/xi-sender-mail-adapter--payloadswapbean--step-by-step

2. Use Netweaver Developer Studio to create an EJb Module with the code supplied by me. This code grabs the attachment name and adds it to the Dynamic Configuration section of the Message. Here is a link to Stefan Grube's webinar on custom adapter module development -

https://www.sdn.sap.com/irj/sdn/go/portal/prtroot/docs/library/uuid/64a6bdab-0c01-0010-079a-b3707717...

3. In our integration scenario we are saving the email attachment to a file. so on the receiver file adapter we used to Dynamic Configuration Bean to get the Attachment name from the Dynamic Config section of the Message and name the file the same as the attahcmnet name from the email.

/people/jin.shin/blog/2007/04/27/sap-netweaver-xi-variable-substitution-with-adapter-specific-message-attributes-via-dynamicconfigurationbean

4. If your attachment was an XML (actually any other format could be converted into XML by writing another Bean for the sender mail adapter or maybe the MessageTransform Bean would do the job) you could use the Dyanmic Config in your mapping itself in a user defined function. Here is the code for that UDF. We called it getAttachmentName .............

public String getAttachmentName(Container container){

DynamicConfiguration conf = (DynamicConfiguration) container.getTransformationParameters().get(StreamTransformationConstants.DYNAMIC_CONFIGURATION);

DynamicConfigurationKey key = DynamicConfigurationKey.create("http://xyz.com/email","FileName");

String value = conf.get(key);

return value;

}

Hope this helps

Salil

p.s) I've got to say SDN is a great place to get your questions answered as I have mostly got mine.

Former Member
0 Kudos

Salil, Thanks A LOT for your help

I'll try to do what you said.

Regards

Former Member
0 Kudos

Salil, I'm not using mapping on my scenario, because I'm receiving generic XML files.

(like the blog /people/william.li/blog/2006/09/08/how-to-send-any-data-even-binary-through-xi-without-using-the-integration-repository)

As I'm using only Integration Directory, I'm not able to use that UDF you provided. Is there any way to set it up directly on adapter ?

Thanks again

Former Member
0 Kudos

Hi Vitor

There are 2 scenarios that I can think of -

1. You are saving the email attachment as a file. In that case use step 3 in the earlier reply to get the attachment name and save the file witht that name.

2. You are sending the XML straight to a receiver using HTTP, IDOC, JDBC etc. in which case you would need the attachment name much earlier that step 3. For that I guess you would have to write another adapter module on the sender mail adapter(at Position 3 where position1 = payloadswap bean, 2 = custom module to get the attachment name) and add an xml tag to your incoming message. These adapter modules are really powerful and are like user exits in ABAP. In that case you would have to change the Data Type in the Integration repository to reflect that extra tag. Here is some code from a module we wrote to totally change the structure of the xml coming in. The key thing to remember is this module is that you can read the whole message byte by byte. There might be smarter ways of doing it (like using the SAP XML parser factory class) but since I'm not a Java programmer I stuck to the basics. Here's the code( you could also look at the example given in sap help where they remove (or add I'm not sure) CR(carriage return) from CRLF (CR Line feed).

**********************************************************************************************

/*

  • Created on Aug 8, 2007

*

  • To change the template for this generated file go to

  • Window&gt;Preferences&gt;Java&gt;Code Generation&gt;Code and Comments

*/

package jdbcPackage;

import javax.ejb.CreateException;

import javax.ejb.SessionBean;

import javax.ejb.SessionContext;

import com.sap.aii.af.mp.module.*;

import com.sap.aii.af.ra.ms.api.*;

/**

  • @author Salil.Mehta Soltius NZ Ltd

*

  • To change the template for this generated type comment go to

  • Window&gt;Preferences&gt;Java&gt;Code Generation&gt;Code and Comments

*/

public class jdbcClass implements SessionBean, Module {

private SessionContext myContext;

public void ejbRemove() {

}

public void ejbActivate() {

}

public void ejbPassivate() {

}

public void setSessionContext(SessionContext context) {

myContext = context;

}

public void ejbCreate() throws CreateException {

}

public ModuleData process(

ModuleContext moduleContext,

ModuleData inputModuleData)

throws ModuleException {

// put your code here

try {

Message msg = (Message) inputModuleData.getPrincipalData();

XMLPayload payload = msg.getDocument();

String payEnc = payload.getEncoding();

byte[] payByte = payload.getContent();

byte[] payByteOut = new byte[payByte.length];

byte[] payByteTemp = new byte[payByte.length];

int i;

int j;

int actualCount = 0;

char xmlTagFound = ' ';

char endXmlTagFound = ' ';

char tagFound = ' ';

System.arraycopy(payByte, 0, payByteTemp, 0, payByte.length);

// Step 1 - Conversions

// convert "&lt; to <" and "&gt; to >"

// convert &quot; to "

// This will remove any carriage returns and line feeds

// and the <XML* and </XML* tags plus the <row> and </row> tags

for (i = 0; i < payByte.length; i++) {

// convert &lt; to < and &gt; to >

if (payByteTemp<i> == '&') {

if (payByteTemp[i + 1] == 'l') {

if (payByteTemp[i + 2] == 't') {

if (payByteTemp[i + 3] == ';') {

payByteTemp<i> = '<';

payByteTemp[i + 1] = '\n';

payByteTemp[i + 2] = '\n';

payByteTemp[i + 3] = '\n';

}

}

}

}

if (payByteTemp<i> == '&') {

if (payByteTemp[i + 1] == 'g') {

if (payByteTemp[i + 2] == 't') {

if (payByteTemp[i + 3] == ';') {

payByteTemp<i> = '>';

payByteTemp[i + 1] = '\n';

payByteTemp[i + 2] = '\n';

payByteTemp[i + 3] = '\n';

}

}

}

}

if (payByteTemp<i> == '&') {

if (payByteTemp[i + 1] == 'q') {

if (payByteTemp[i + 2] == 'u') {

if (payByteTemp[i + 3] == 'o') {

if (payByteTemp[i + 4] == 't') {

if (payByteTemp[i + 5] == ';') {

payByteTemp<i> = '"';

payByteTemp[i + 1] = '\n';

payByteTemp[i + 2] = '\n';

payByteTemp[i + 3] = '\n';

payByteTemp[i + 4] = '\n';

payByteTemp[i + 5] = '\n';

}

}

}

}

}

}

// This will take in the initial xml declaration from the Byte array

// And we also don't want the stuff after the xml declaration till

// we reach the first <row> tag

if (xmlTagFound == ' ') {

if (payByteTemp<i> == '>') {

xmlTagFound = 'X';

}

payByteOut[actualCount++] = payByteTemp<i>;

if (xmlTagFound == 'X') {

payByteOut[actualCount++] = '\r';

}

continue;

}

if (xmlTagFound == 'X') {

if (payByteTemp<i> == '<') {

if (payByteTemp[i + 1] == 'r') {

if (payByteTemp[i + 2] == 'o') {

if (payByteTemp[i + 3] == 'w') {

if (payByteTemp[i + 4] == '>') {

xmlTagFound = 'Y';

} else {

continue;

}

} else {

continue;

}

} else {

continue;

}

} else {

continue;

}

} else {

continue;

}

}

// Carriage return and line feed

if ((payByteTemp<i> == '\r') || (payByteTemp<i> == '\n')) {

continue;

}

// <XML_*> tag

if (payByteTemp<i> == '<') {

if (payByteTemp[i + 1] == 'X') {

if (payByteTemp[i + 2] == 'M') {

if (payByteTemp[i + 3] == 'L') {

tagFound = 'X';

endXmlTagFound = ' ';

continue;

}

}

}

}

// </XML_*> tag

if (payByteTemp<i> == '<') {

if (payByteTemp[i + 1] == '/') {

if (payByteTemp[i + 2] == 'X') {

if (payByteTemp[i + 3] == 'M') {

if (payByteTemp[i + 4] == 'L') {

tagFound = 'X';

endXmlTagFound = 'X';

continue;

}

}

}

}

}

// <row> tag

if (payByteTemp<i> == '<') {

if (payByteTemp[i + 1] == 'r') {

if (payByteTemp[i + 2] == 'o') {

if (payByteTemp[i + 3] == 'w') {

if (payByteTemp[i + 4] == '>') {

tagFound = 'X';

continue;

}

}

}

}

}

// </row> tag

if (payByteTemp<i> == '<') {

if (payByteTemp[i + 1] == '/') {

if (payByteTemp[i + 2] == 'r') {

if (payByteTemp[i + 3] == 'o') {

if (payByteTemp[i + 4] == 'w') {

if (payByteTemp[i + 5] == '>') {

tagFound = 'X';

continue;

}

}

}

}

}

}

if ((payByteTemp<i> == '>') && (tagFound == 'X')) {

tagFound = ' ';

continue;

}

if (tagFound == ' ') {

if (endXmlTagFound == 'X') {

continue;

}

payByteOut[actualCount++] = payByteTemp<i>;

}

}

byte[] payByteExp = new byte[actualCount];

System.arraycopy(payByteOut, 0, payByteExp, 0, actualCount);

payload.setContent(payByteExp);

msg.setDocument(payload);

inputModuleData.setPrincipalData(msg);

} catch (Exception e) {

ModuleException me = new ModuleException(e);

throw me;

}

return inputModuleData;

}

}

VijayKonam
Active Contributor
0 Kudos

Salil,

This was very useful thread. How did you test your adapter module? Did you every time deployed it on to XI server and tested using a test mail?

Stefan Grube - Could you help or tell me how to test an adapter module? The only issue is, what would at runtime the statement - Message msg = (Message) inputModuleData.getPrincipalData(); would return?

Is there a way to test the modules before we actually deploy them on to the server?

VJ

stefan_grube
Active Contributor
0 Kudos

There is no way to test the adapter module outside the adapter framework.

But you will see: When the module is syntactical correct and there are no deployment issues, then it runs at once.

Regards

Stefan

Former Member
0 Kudos

Thanks for that Stefan.