I use javax.mail.internet.MimeBody* version 1.4.1
My program wants to send some binary data with multiple level of nesting from a server to client using MimeMultiPart. I observed that if on a level if we use GetContent it corrupts the data. I was able to reproduce this problem with this snippet
public static void CreateResponse() throws Exception {
//Simulate the Server side
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
MimeMultipart multiPartValues = new MimeMultipart();
MimeBodyPart valueBody = new MimeBodyPart();
byte[] firstKeyValue = new byte[] { (byte)0x8c};
valueBody.setContent(firstKeyValue,"application/octet-stream");
valueBody.addHeader(RestMessageHeaders.CONTENT_LENGTH,
Integer.toString(firstKeyValue.length));
multiPartValues.addBodyPart(valueBody);
Object input = valueBody.getContent();
System.out.println(String.format("input %02X", ((byte[])input)[0]));
multiPartValues.writeTo(outputStream);
//Simulate the client side
byte[] mimeOutput = outputStream.toByteArray();
ByteArrayDataSource ds = new ByteArrayDataSource(mimeOutput,
"multipart/mixed");
MimeMultipart mp = new MimeMultipart(ds);
MimeBodyPart part = (MimeBodyPart) mp.getBodyPart(0);
byte[] myOutput = new byte[1];
//Verified that getContent returns a String, why ??
Object output = part.getContent();
System.out.println("getContent type " + output.getClass());
String result = (String)output;
ByteArrayDataSource partDS = new ByteArrayDataSource(result, "multipart/mixed");
partDS.getInputStream().read(myOutput);
System.out.println(String.format("getContent %02X %02X", result.getBytes()[0],result.getBytes()[1]));
System.out.println(String.format("getContent %02X", myOutput[0]));
part.getInputStream().read(myOutput);
System.out.println(String.format("getInputStream %02X", myOutput[0]));
part.getRawInputStream().read(myOutput);
System.out.println(String.format("getRawInputStream %02X", myOutput[0]));
}
Here is the output
input 8C
getContent type class java.lang.String
getContent C2 8C
getContent C2
getInputStream 8C
getRawInputStream 8C
I have completely simplified the code here and it looks obvious to use get(Raw)InputStream, but we have nestedMultiPart and the top level was doing getContent which caused it to fail for some cases.
What does the complete stream contain that the server is creating and the client is reading?
Note that by using MimeMultipart without MimeMessage, you're missing some of the things that are done automatically for you by MimeMessage, in particular you're missing the call to MimeMultipart.updateHeaders(). Since the method is protected, you'll need to subclass MimeMultipart and call that method before calling writeTo. If that doesn't fix your problem, show us the exact data that's being written and read on the stream.
As mentioned above, if you're expecting binary data, you almost certainly want to use getInputStream. The getRawInputStream gives you the data before it has been decoded, e.g., the base64 input instead of binary output.