Search code examples
javajakarta-maileml

javax.mail: Get nested attachments in EML attachment


I have an existing code that downloads and processes some emails correctly.

The email to process must have one or more xml as attachment, now I'm migrating this process from the current standard mail account to a certified system that wrap that mail into a new email.

So, instead of a flat email with one xml attachment, I have to parse an email with an XML (the certified) and an EML (the message that I should process).

In short, my code is like the following:

private void processMessage(final Message message) {
    try {
        final String contentType = message.getContentType();
        if (contentType.contains("multipart")) {
            final Multipart multiPart = (Multipart) message.getContent();

            for (int i = 0; i < multiPart.getCount(); i++) {
                final MimeBodyPart part = (MimeBodyPart) multiPart.getBodyPart(i);

                /**************************************************************
                 * HERE I CAN'T GET THE EML (and its attachments) FROM 'part' *
                 **************************************************************/

                if (Part.ATTACHMENT.equalsIgnoreCase(part.getDisposition())) {
                    processAttachment(part);
                }
            }
        }
    } [...cutted...]
}

private void processAttachment(final MimeBodyPart part) throws IOException, MessagingException {
    final InputStream input = getReusableInputStream(part);

    if (part.getFileName() != null && isXmlType(part.getContentType())) {
        processXml(input);
    }
}

I should modify it, in order to parse the EML and get the attachments recursively, but I'm missing the big picture.

UPDATE: I've modified the processAttachment method (but it still doesn't work):

private void processAttachment(final Multipart multipart) {

    try {
        for (int i = 0; i < multipart.getCount(); i++) {
            final BodyPart bodyPart = multipart.getBodyPart(i);

            if (bodyPart.getContent() instanceof Multipart) {
                // part-within-a-part, do some recursion...
                extractAttachment((Multipart) bodyPart.getContent());
            }

            System.out.println("Filename: " + bodyPart.getFileName());
            System.out.println("ct: " + bodyPart.getContentType());

            final boolean isXml = bodyPart.getFileName() != null && isXmlType(bodyPart.getContentType());
            if (isXml) {
                final InputStream inputStream = getReusableInputStream(bodyPart);
                processXMLAttachment(inputStream);
            }

        }
    } [cutted]

}

The output is:

Filename: null
ct: TEXT/PLAIN; charset=iso-8859-1
Filename: null
ct: TEXT/HTML; charset=iso-8859-1
Filename: daticert.xml
ct: APPLICATION/XML; name=daticert.xml
Filename: postacert.eml
ct: MESSAGE/RFC822; name=postacert.eml
Filename: smime.p7s
ct: APPLICATION/X-PKCS7-SIGNATURE; name=smime.p7s

From the output, I can see that the system only scaned the first level attachments daticert.xml and postacert.eml but it didn't find the nested attachments.

More specifically, I have to read the content of:

Filename: postacert.eml
ct: MESSAGE/RFC822; name=postacert.eml

Any help, please?

Thanks


Solution

  • Well, I solved by checking the class of any MimePart, and I found that nested messages are type of IMAPNestedMessage, so on this kind of object I recursively call the main method processMessage:

    private void processAttachment(final Multipart multipart) {
    
        try {
            for (int i = 0; i < multipart.getCount(); i++) {
                final BodyPart bodyPart = multipart.getBodyPart(i);
    
    // BEGIN - Added this part
                System.out.println("CLASS bodyPart: " + bodyPart.getContent().getClass());
    
                if (bodyPart.getContent() instanceof IMAPNestedMessage) {
                    processMessage((IMAPNestedMessage) bodyPart.getContent());
                } else {
    // END - Added this part
                    if (bodyPart.getContent() instanceof Multipart) {
                        processAttachment((Multipart) bodyPart.getContent());
                    } else {
                        final boolean isXml = bodyPart.getFileName() != null && isXmlType(bodyPart.getContentType());
                        if (isXml) {
                            final InputStream inputStream = getReusableInputStream(bodyPart);
                            processXMLAttachment(inputStream);
                        }
                    }
                }
    
            }
        } catch (final Exception e) {
            sendMailService.sendMailForImportINPSFailed("metodo processAttachment()", e);
            e.printStackTrace();
        }
    
    }
    

    And now it works fine.