java 對.EML格式郵件文件解析

使用 Apache James Mime4J

	<dependency>
	    <groupId>org.apache.james</groupId>
	    <artifactId>apache-mime4j-dom</artifactId>
	</dependency>
	<dependency>
	    <groupId>org.apache.james</groupId>
	    <artifactId>apache-mime4j-core</artifactId>
	</dependency>
    <dependency>
	    <groupId>org.apache.james</groupId>
	    <artifactId>apache-mime4j-storage</artifactId>
	</dependency>
	public class EmailPreviewVo {
	
	    private Long id;
	
	    private String from;
	
	    private String cc;
	
	    private String to;
	
	    private String subject;
	
	    private String sentDate;
	
	    private String content;
	
	    private List<FileVo> attachments;
	
	    private String partnerId = null;
	}
  /**
     * 解析EML郵件,可以將郵件以HTML展示。
     * @param file EML格式郵件的全路徑
     * @return Email
     * @throws MimeException 解析異常
     * @throws IOException IO異常
     */
    public static EmailPreviewVo parseToPreview(File file) throws MimeException, IOException {

        EmailPreviewVo vo = new EmailPreviewVo();

        String messageFileName = file.getAbsolutePath();
        CustomContentHandler contentHandler =  new CustomContentHandler();
        parseEmail(messageFileName, contentHandler);
        Email emailSrc = ((CustomContentHandler) contentHandler).getEmail();
        EmailFacade email = new EmailFacade(emailSrc);
        String html = email.getHtmlBody();
        Document doc = Jsoup.parse(html);

        List<FileVo> attachList = new ArrayList<>();
        for(int i=0; i < email.getAttacheNames().size(); i++) {
            Map<String, Object> map = new HashMap<String, Object>();
            InputStream ins = email.getAttachementList().get(i).getIs();
            String attachName = email.getAttacheNames().get(i);
            File attachementFile = null;
            if (Utils.existSuffix(attachName)) {
                String suffix = Utils.getSuffix(attachName);
                attachementFile = Utils.createTmpFile(suffix);// 以後綴創建文件
              /* public static String getSuffix(String fileName) {
                  if (fileName.contains(".")) {
                      String suffix = fileName.substring(fileName.lastIndexOf("."));
                      return trimilSpace(suffix.toLowerCase());
                    }
       			 throw new AppException("文件沒有後綴");
    			}*/
            } else {
                attachementFile = Utils.createTmpFileWithName(attachName);//以名稱創建文件,可根據自己實際情況改寫
            }
            org.apache.commons.io.FileUtils.copyInputStreamToFile(ins, attachementFile);
            if (attachementFile != null) {
               /*FileVo 對象屬性
                 private Long id = null;
			  	 private String fileName = null;
			     private int fileType = 2;
			     @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
			     @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
			       private Date fileDate = null;
			    private String fileSessionId = null;
			    private String userName = null;
			    private Long fileLength = null;
				private String filePath = null;
			    private String filePathName = null;
    			private String description = null;
    			*/
                FileVo fileVo = new FileVo();
                fileVo.setFileName(attachName);
                fileVo.setFileLength(attachementFile.length());
                fileVo.setFilePath(attachementFile.getAbsolutePath());
                attachList.add(fileVo);
            }
        }
        vo.setAttachments(attachList);

        // 對郵件中圖片進行處理
        Elements imgList = doc.select("img");
        if (imgList.size() > 0) {
            imgList.forEach(new Consumer<Element>() {
                @Override
                public void accept(Element element) {
                    String src = element.attr("src");
                    if (src.indexOf("cid:") < 0) {
                        return;
                    }
                    String imgAttach = src.substring(4);
                    FileVo fileVo = null;
                    for (FileVo tmp : attachList) {
                        if (tmp.getFileName().equals(imgAttach)) {
                            fileVo = tmp;
                            break;
                        }
                    }
                    if (fileVo == null) {
                        return;
                    }
                    File attach = new File(fileVo.getFilePath());
                    String base64 = null;
                    InputStream in = null;
                    try {
                        in = new FileInputStream(attach);
                        byte[] bytes=new byte[(int)attach.length()];
                        in.read(bytes);
                        base64 = Base64.getEncoder().encodeToString(bytes);
                    } catch (Exception e) {
                        e.printStackTrace();
                    } finally {
                        if (in != null) {
                            try {
                                in.close();
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                        }
                    }

                    if (StringUtils.isNotBlank(base64)) {
                        String srcBase64 = "data:image/png;base64," + base64;
                        element.attr("src", srcBase64);
                        attachList.remove(fileVo);
                    }
                }
            });
        }

        Elements bodyList = doc.select("body");
        if (bodyList.size() > 0) {
            Element bodyEle = bodyList.first();
            if (bodyEle.html().length() > 0) {
                vo.setContent(bodyEle.html());
            }
        }

        org.apache.james.mime4j.dom.Header header = emailSrc.getHeader();
        List<Field> fields = header.getFields();
        for (Field field : fields) {
            if ("Date".equals(field.getName())) {
                vo.setSentDate(decode(field.getBody()));
            } else if ("From".equals(field.getName())) {
                vo.setFrom(decode(field.getBody()));
            } else if ("To".equals(field.getName())) {
                vo.setTo(decode(field.getBody()));
            } else if ("Cc".equals(field.getName())) {
                vo.setCc(decode(field.getBody()));
            } else if ("Subject".equals(field.getName())) {
                vo.setSubject(decode(field.getBody()));
            }
        }

        return vo;
    }

   private static void parseEmail(String messageFileName,
			ContentHandler contentHandler) throws FileNotFoundException,
			MimeException, IOException {

		MimeConfig mime4jParserConfig = MimeConfig.DEFAULT;
		BodyDescriptorBuilder bodyDescriptorBuilder = new DefaultBodyDescriptorBuilder();
		MimeStreamParser mime4jParser = new MimeStreamParser(
				mime4jParserConfig, DecodeMonitor.SILENT, bodyDescriptorBuilder);
		mime4jParser.setContentDecoding(true);
		mime4jParser.setContentHandler(contentHandler);

		InputStream mailIn = new FileInputStream(new File(messageFileName));
		mime4jParser.parse(mailIn);

	}

/** 解碼例如標題等信息
     * @param rawvalue 郵件
     * @return 獲取郵件的標題頭
     */
    public static String decode(String rawvalue) {
    	if (rawvalue == null || "".equals(rawvalue.trim())) {
    		return "無標題";
    	}
        try {
            if (!rawvalue.contains("=?")) {
                return toChinese(rawvalue);
            }
            if (rawvalue.contains("gb2312")) {
            	rawvalue = rawvalue.replace("gb2312", "GBK");
            } else if (rawvalue.contains("GB2312")) {
            	rawvalue = rawvalue.replace("GB2312", "GBK");
            }
            StringBuilder sb = new StringBuilder();
            while (true) {
                int codingStartIdx = rawvalue.indexOf("=?");
                if (codingStartIdx == -1) {
                    sb.append(rawvalue);
                    break;
                }
                if (codingStartIdx != 0) {
                    sb.append(rawvalue.substring(0, codingStartIdx));
                }
                int codingEndIdx = rawvalue.indexOf("?", codingStartIdx + 2);
                String coding = rawvalue.substring(codingStartIdx + 2, codingEndIdx);
                String codingType = rawvalue.substring(codingEndIdx + 1, codingEndIdx + 2);
                String code = "=?" + coding + "?" + codingType + "?";
                int innerCodingIdx = rawvalue.indexOf(code, codingEndIdx + 2);
                while (innerCodingIdx != -1) {
                    int lastCodingEndInx = rawvalue.indexOf("?=");
                    if (lastCodingEndInx < innerCodingIdx) {
                        String connection = rawvalue.substring(lastCodingEndInx, innerCodingIdx);
                        Pattern p = Pattern.compile("\\s*|\t|\r|\n");
                        Matcher m = p.matcher(connection);
                        rawvalue = rawvalue.replace(connection, m.replaceAll(""));
                    }
                    if (!rawvalue.contains("=?=" + code)) {
                        rawvalue = rawvalue.replace("?=" + code, "");
                    }
                    innerCodingIdx = rawvalue.indexOf(code, innerCodingIdx + 2);
                }
                int segEnd = rawvalue.indexOf("?=", codingEndIdx + 3);
                if ("q".equals(codingType.toLowerCase())) {
                    String codeSeg = rawvalue.substring(codingEndIdx + 3, segEnd);
                    sb.append(parseQ(coding, codeSeg));
                } else {
                    sb.append(MimeUtility.decodeText(code + rawvalue.substring(
                        codingEndIdx + 3, segEnd) + "?="));
                }
                if (rawvalue.length() == segEnd + 2) {
                    break;
                }
                rawvalue = rawvalue.substring(segEnd + 2);
            }
            return Utils.trimilSpace(sb.toString());
        } catch (Exception e) {
            logger.warn("cannot decode subject." + rawvalue, e);
        }
        return rawvalue;
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章