Skip to Main Content

Java EE (Java Enterprise Edition) General Discussion

Announcement

For appeals, questions and feedback about Oracle Forums, please email oracle-forums-moderators_us@oracle.com. Technical questions should be asked in the appropriate category. Thank you!

Javamail IMAP: Base64 Encoded bodyparts from gmail truncated

843834Mar 5 2009 — edited Mar 6 2009
I'm attempting to access Gmail using IMAP. The problem is that when I read a Base64 encoded bodypart, the content stream is truncated.

The problem is the same whether I call getInputStream() on the content (the resulting binary is too short and the Base64DecodingStream complains about bad input) or call getRawInputStream() and examine the encoded bytes - it's short and I get an EOF before the end of the real attachment. It occurs about 2k before the end of the actual attachment for the attachments I've tested, which include 16k, 150k, and 400k attachments. It occurs for all gmail accounts that I've tested (3), and across a number of mime types (msword, pdf, and .zip).

When I save the attachments directly from Gmail, the resulting binaries are fine.

I set mail.imap.partialfetch to false, but that didn't help.

Any pointers would be greatly appreciated. I've pasted a bit of code below.

    
    protected InputStream getAttachmentStream(MimeMultipart parent, MessageAttachment localAttachment) 
            throws MessagingException, IOException {
// localAttachment is an (currently) unpopulated model of the attachment that I want to populate with data.
        InputStream is = null;
        for(int i = 0; i < parent.getCount(); i++) {
            MimeBodyPart part = (MimeBodyPart) parent.getBodyPart(i);
            String partType = part.getContentType();
            
            if(partType.toLowerCase().startsWith("multipart")) {
                is = getAttachmentStream((MimeMultipart)part.getContent(), localAttachment);
                if(is != null) break;
            }
            else {
                String filename = part.getFileName();
                int size = part.getSize();
                if(     filename != null &&
                        size == localAttachment.getAttachmentSize() && 
                        filename.equals(localAttachment.getAttachmentName())) {
                    part.saveFile("/Users/Rod/test.doc");  // this results in a truncated  file
                    is = part.getRawInputStream(); 


                   //  test code: read the input stream fully and examine the bytes
                   ByteArrayOutputStream bytestream = new ByteArrayOutputStream();
                   byte [] buffer = new byte[1024];
                   int bytesRead = 0;
                   do {
                        try {
                            bytesRead = is.read(buffer);
                            totalbytes += bytesRead;
                            if (bytesRead < 0) {
                                break; // while
                            }

                            bytestream.write(buffer, 0, bytesRead);
                        }
                        catch(Exception ex) {
                            ex.printStackTrace();
                            bytesRead = 0;
                        }
                    } while(bytesRead > 0);

                    logger.log(Level.INFO, "Loaded attachment with " + totalbytes + " bytes");  // is about 2k shorter than it should be
                    byte[] rawdata = bytestream.toByteArray();
                    logger.log(Level.INFO, "Raw data is " + rawdata.length + " bytes");  // matches totalbytes - just a sanity check

                    /*
                    Output the encoded data.  I generally get something like ends like this:
                    /zcBAAA4AQAAOQEAADoBAAA7AQAAPAEAAD0BAAD+////PwEAAEABAABBAQAAQgEAAEMBAABEAQAA
                    RQEAAP7////9/////f////3///9KAQAA/v////7////+////////////////////////////////
                    ////////////////////////////////////////////////////////                 
       
                   in this case, were it valid base64 there would be two '=' characters at the end to pad out to  a multiple of 3.
                   */
                    logger.log(Level.INFO, new String(rawdata)); 

                    // Amazon's decoder doesn't choke as soon as the Base64DecoderStream, but I only get a few more
                    // '/' characters decoded
                    byte[] data = com.amazon.thirdparty.Base64.decode(rawdata, 0, rawdata.length);
                    // length of data is about 1.5k less than the binary saved directly from Gmail
                    logger.log(Level.INFO, "Decoded attachment size: " + data.length + " bytes");
                    
                    localAttachment.setMimeType(partType);
                    break;
                }
            }
        }
        
        
        return is;
    }
Comments
Locked Post
New comments cannot be posted to this locked post.
Post Details
Locked on Apr 3 2009
Added on Mar 5 2009
4 comments
1,007 views