如何从电子邮件中获取内嵌图像?

时间:2015-06-09 03:31:09

标签: java javamail email-attachments inline-images

我正在使用下一代码使用javamail API从我的邮箱帐户下载附件和正文文本,它运行正常。但是,当电子邮件上有内嵌或嵌入图像时,图像不会以文本或附件文件的形式下载。我是Java新手,已经在网上阅读,但没有找到易于理解的实施解决方案。任何workarround或代码来完成它?

这是我正在使用的代码:

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();
    }

}

我尝试添加下一个if语句来显示一条消息(如果它是内嵌图像),但没有幸运:

 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();
        }

    }

4 个答案:

答案 0 :(得分:1)

以下代码应该适合您....

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;
}

答案 1 :(得分:1)

嵌入式图片将成为多部分/相关内容的一部分,不会被标记为附件。有关此类消息的结构,请参阅RFC 2387

答案 2 :(得分:0)

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;
    }

答案 3 :(得分:0)

如果要将内联文件保存到附件中,可以尝试以下代码:

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());
    }

您还可以获取文件的mime类型。

 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);
}

还有FileData类:

@Data
@Accessors(chain = true)
public class FileData {
    byte[] data;
    String name;
    String type;
}