How can i get inline images from an email?

8.1k views Asked by At

I am using next code to download attachments and body text from my mailbox account using javamail API, and it works just fine. But when an email has inline or embedded images on it, the images is not downloaded neither as text or attachment file. I am new at Java and have been reading on the web but did not find a implemented solution easy to understand. Any workarround or code to get it done ?

this is the code i am using :

public void processMessageBody(Message message) {
    try {
        Object content = message.getContent();
        // check for string
        // then check for multipart
        if (content instanceof String) {
            System.out.println(content);
        } else if (content instanceof Multipart) {
            Multipart multiPart = (Multipart) content;
            procesMultiPart(multiPart);
        } else if (content instanceof InputStream) {
            InputStream inStream = (InputStream) content;
            int ch;
            while ((ch = inStream.read()) != -1) {
                System.out.write(ch);
            }

        }

    } catch (IOException e) {
        e.printStackTrace();
    } catch (MessagingException e) {
        e.printStackTrace();
    }
}

public void procesMultiPart(Multipart content) {

    try {

        for (int i = 0; i < content.getCount(); i++) {
            BodyPart bodyPart = content.getBodyPart(i);
            Object o;

            o = bodyPart.getContent();
            if (o instanceof String) {
                System.out.println("Text = " + o);
            } else if (null != bodyPart.getDisposition()
                    && bodyPart.getDisposition().equalsIgnoreCase(
                            Part.ATTACHMENT)) {
                String fileName = bodyPart.getFileName();
                System.out.println("fileName = " + fileName);
                InputStream inStream = bodyPart.getInputStream();
                FileOutputStream outStream = new FileOutputStream(new File(
                        downloadDirectory + fileName));
                byte[] tempBuffer = new byte[4096];// 4 KB
                int numRead;
                while ((numRead = inStream.read(tempBuffer)) != -1) {
                    outStream.write(tempBuffer);
                }
                inStream.close();
                outStream.close();
            }
            // else?

        }
    } catch (IOException e) {
        e.printStackTrace();
    } catch (MessagingException e) {
        e.printStackTrace();
    }

}

I have tried adding the next if statment to display a message if it is an inline image, but no lucky:

 public void procesMultiPart(Multipart content) {

        try {

            for (int i = 0; i < content.getCount(); i++) {
                BodyPart bodyPart = content.getBodyPart(i);
                Object o;

                o = bodyPart.getContent();
// NOT WORKING
                if (o instanceof Image) {
                   System.out.println("procesMultiPart has Inline Images");
                } 
// 
else if (o instanceof String) {
                    System.out.println("Text = " + o);
                } else if (null != bodyPart.getDisposition()
                        && bodyPart.getDisposition().equalsIgnoreCase(
                                Part.ATTACHMENT)) {
                    String fileName = bodyPart.getFileName();
                    System.out.println("fileName = " + fileName);
                    InputStream inStream = bodyPart.getInputStream();
                    FileOutputStream outStream = new FileOutputStream(new File(
                            downloadDirectory + fileName));
                    byte[] tempBuffer = new byte[4096];// 4 KB
                    int numRead;
                    while ((numRead = inStream.read(tempBuffer)) != -1) {
                        outStream.write(tempBuffer);
                    }
                    inStream.close();
                    outStream.close();
                }
                // else?

            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (MessagingException e) {
            e.printStackTrace();
        }

    }
5

There are 5 answers

2
Pavan Kumar K On

The following code should work for you ....

private String getAttachments(Message message, HttpServletRequest request) throws MessagingException, IOException {
String contentType = message.getContentType();
String attachFiles="";
if (contentType.contains("multipart")) {
    // content may contain attachments
    Multipart multiPart = (Multipart) message.getContent();
    int numberOfParts = multiPart.getCount();
    for (int partCount = 0; partCount < numberOfParts; partCount++) {
        MimeBodyPart part = (MimeBodyPart) multiPart.getBodyPart(partCount);
        String disposition =part.getDisposition();
        String file=part.getFileName();
        //External attachments
        if (disposition != null && Part.ATTACHMENT.equalsIgnoreCase(disposition)) {
            // this part is attachment
            String fileName = new Date().getTime()+ "_"+ part.getFileName().replaceAll("[^a-zA-Z0-9\\._]+", "_"); //To make attachment name uniq we are adding current datatime before name.
            attachFiles += fileName + ","; //concrete all attachment's name with comma separated.                  
            part.saveFile(new File(request
                    .getSession()
                    .getServletContext()
                    .getRealPath(
                            "/WEB-INF/attechments/"
                                    + fileName)));   //To save the attachment file at specific location.
    //                    LOG.info("\n\t Path :- " +request.getSession().getServletContext().getRealPath("/WEB-INF/attechments/" + fileName));
        }
        //Inline Attachments
        else if (disposition != null && Part.INLINE.equalsIgnoreCase(disposition)) {
            // this part is attachment
            String fileName = new Date().getTime()+ "_"+ part.getFileName().replaceAll("[^a-zA-Z0-9\\._]+", "_"); //To make attachment name uniq we are adding current datatime before name.
          //  attachFiles += fileName + ","; //concrete all attachment's name with comma separated.                  
            part.saveFile(new File(request
                    .getSession()
                    .getServletContext()
                    .getRealPath(
                            "/WEB-INF/attechments/"
                                    + fileName)));   //To save the attachment file at specific location.
//                    LOG.info("\n\t Path :- " +request.getSession().getServletContext().getRealPath("/WEB-INF/attechments/" + fileName));
        }
        //Inline icons and smileys
        else if(file != null && disposition==null)
        {
            String fileName = new Date().getTime()+ "_"+ part.getFileName().replaceAll("[^a-zA-Z0-9\\._]+", "_");
        //  attachFiles += fileName + ","; //concrete all attachment's name with comma separated.
             part.saveFile(new File(request
                    .getSession()
                    .getServletContext()
                    .getRealPath(
                            "/WEB-INF/attechments/"
                                    + fileName))); 

        }
    }
 }
 if (attachFiles.length() > 1) {
     attachFiles = attachFiles.substring(0, attachFiles.length() - 1);
 }
return attachFiles;
}
2
Bill Shannon On

Embedded images will be part of a multipart/related content, they won't be marked as attachments. See RFC 2387 for the structure of such a message.

0
Faiz Akram On
@Value("classpath:/mail-logo.png")
private Resource resourceFile;

private void sendHtmlMessage(String to, String subject, String htmlBody, MultipartFile multipartFile)
        throws MessagingException, IOException {
    MimeMessage message = emailSender.createMimeMessage();
    MimeMessageHelper helper = new MimeMessageHelper(message, true, "UTF-8");
    helper.setFrom(NOREPLY_ADDRESS);
    helper.setTo(to);
    helper.setSubject(subject);
    helper.setText(htmlBody, true);
    //if you're uploading file
    helper.addInline("identifier1", multipartFile, multipartFile.getContentType());
    //if you're loading from any location
    helper.addInline("identifier2", resourceFile);
    emailSender.send(message);[![enter image description here][1]][1]
}

<!DOCTYPE html>
<html>
  <body>
  Hi Hello
 World

 Regards,

 World
    <img src='cid:identifier1'>
    <img src='cid:identifier2'>
  </body>
</html>

0
Skill For Kill On

If you want to save inline files into attachments, you can try the following code:

private static void fillBodyAndAttachments(Message message) throws Exception {
        String body = "";
        List<FileData> attachments = new LinkedList<>();
        String contentType = message.getContentType();

        if (contentType.contains("text/plain") || contentType.contains("text/html")) {
            Object content = message.getContent();
            if (content != null) {
                body = content.toString();
            }
            System.out.println(body);
            return;
        }

        if (contentType.contains("multipart")) {
        Multipart multiPart = (Multipart) message.getContent();
        int numberOfParts = multiPart.getCount();
        for (int partCount = 0; partCount < numberOfParts; partCount++) {
            MimeBodyPart part = (MimeBodyPart) multiPart.getBodyPart(partCount);
            String disposition = part.getDisposition();

            if (Part.ATTACHMENT.equalsIgnoreCase(disposition)) {
                addAttachment(attachments, part);
            } else if (Part.INLINE.equalsIgnoreCase(disposition)) {
                Object content = part.getContent();
                if (content instanceof InputStream) {
                    var inputStream = (InputStream) content;
                    byte[] byteArray = IOUtils.toByteArray(inputStream);
                    addInlineAttachment(attachments, byteArray, part.getFileName());
                }
            } else {
                Object content = part.getContent();
                if (content instanceof String) {
                    body = (String) content;
                } else if (content instanceof InputStream) {
                    body = new String(IOUtils.toByteArray((InputStream) content));
                } else if (content instanceof IMAPNestedMessage) {
                    IMAPNestedMessage imapNestedMessage = (IMAPNestedMessage) content;
                    body = new String(IOUtils.toByteArray(imapNestedMessage.getInputStream()));
                } else {
                    MimeMultipart mimeMultipart = (MimeMultipart) part.getContent();
                    body = new String(IOUtils.toByteArray(mimeMultipart.getBodyPart(0).getInputStream()));
                }
            }
        }
    }
        System.out.println(body);
        System.out.println(attacments.size());
    }

You can also get mime type of your files.

 private static void addAttachment(List<FileData> attachments, MimeBodyPart part) throws Exception {
    String fileName = part.getFileName();
    FileData fileData = new FileData()
            .setName(fileName)
            .setData(part.getInputStream().readAllBytes())
            .setType(getMimeType(fileName));
    attachments.add(fileData);
}

private static void addInlineAttachment(List<FileData> attachments, byte[] data, String fileName) throws Exception {
    FileData fileData = new FileData()
            .setName(fileName)
            .setData(data)
            .setType(getMimeType(fileName));
    attachments.add(fileData);
}

private static String getMimeType(String fileName) throws Exception {
    Path path = new File(fileName).toPath();
    return Files.probeContentType(path);
}

And the FileData class:

@Data
@Accessors(chain = true)
public class FileData {
    byte[] data;
    String name;
    String type;
}
2
Satish Bonde On
public static List<String> getAttachmentFileName(MimeMultipart mimeMultipart) throws Exception{
        List<String> attachFileNameList = new ArrayList<String>();
        int count = mimeMultipart.getCount();
        for (int i = 0; i < count; i++) {
            BodyPart bodyPart = mimeMultipart.getBodyPart(i);
            if("ATTACHMENT".equalsIgnoreCase(bodyPart.getDisposition())){
                attachFileNameList.add(bodyPart.getFileName());
            }
        }
        return attachFileNameList;
    }