|
@@ -47,6 +47,7 @@ import org.springframework.util.StopWatch;
|
|
|
|
|
|
import java.io.File;
|
|
|
import java.io.IOException;
|
|
|
+import java.io.UnsupportedEncodingException;
|
|
|
import java.nio.file.Path;
|
|
|
import java.nio.file.Paths;
|
|
|
import java.util.*;
|
|
@@ -684,22 +685,23 @@ public class EmailParseService {
|
|
|
|
|
|
private void rePart(String account, String subject, Date sendDate, Part part,
|
|
|
List<EmailContentInfoDTO> emailContentInfoDTOList) throws Exception {
|
|
|
- String fileName = part.getFileName();
|
|
|
+ String fileName = decodeFileName(part);
|
|
|
if (StrUtil.isBlank(fileName)) {
|
|
|
log.warn("邮件{} 附件文件名是空的,不做下载!", subject);
|
|
|
return;
|
|
|
}
|
|
|
- fileName = MimeUtility.decodeText(fileName);
|
|
|
String disposition = part.getDisposition();
|
|
|
String contentType = part.getContentType();
|
|
|
+ if (log.isInfoEnabled()) {
|
|
|
+ log.info("邮件{} 附件(fileName={},disposition={},contentType={})",
|
|
|
+ subject, fileName, disposition, contentType);
|
|
|
+ }
|
|
|
boolean isAttachment =
|
|
|
(disposition != null && (disposition.equalsIgnoreCase(Part.ATTACHMENT))) ||
|
|
|
StrUtil.startWithIgnoreCase(contentType, MediaType.APPLICATION_PDF.toString());
|
|
|
if (!isAttachment) {
|
|
|
- if (log.isInfoEnabled()) {
|
|
|
- log.info("邮件{} 没有附件(fileName={},disposition={},contentType={}),下载不了附件内容!",
|
|
|
- subject, fileName, disposition, contentType);
|
|
|
- }
|
|
|
+ log.warn("邮件{} 没有附件(fileName={},disposition={},contentType={}),下载不了附件内容!",
|
|
|
+ subject, fileName, disposition, contentType);
|
|
|
return;
|
|
|
}
|
|
|
|
|
@@ -730,6 +732,30 @@ public class EmailParseService {
|
|
|
emailContentInfoDTOList.add(emailContentInfoDTO);
|
|
|
}
|
|
|
|
|
|
+ // 解码文件名(处理 RFC 2231 和 RFC 2047)
|
|
|
+ private static String decodeFileName(Part part) throws UnsupportedEncodingException, MessagingException {
|
|
|
+ String filename = part.getFileName();
|
|
|
+
|
|
|
+ // 优先尝试 RFC 2231 的 filename*(如 "filename*=utf-8''%E4%B8%AD%E6%96%87.txt")
|
|
|
+ String[] values = part.getHeader("Content-Disposition");
|
|
|
+ if (values != null) {
|
|
|
+ for (String value : values) {
|
|
|
+ if (value.startsWith("filename*")) {
|
|
|
+ filename = value.split("'")[2]; // 提取编码后的字符串
|
|
|
+ filename = MimeUtility.decodeText(filename);
|
|
|
+ return filename;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 处理 RFC 2047 的多段编码(如 "=?utf-8?B?5Lit?= =?utf-8?B?5paH?=.txt")
|
|
|
+ if (filename != null && filename.contains("=?")) {
|
|
|
+ return MimeUtility.decodeText(filename);
|
|
|
+ }
|
|
|
+
|
|
|
+ return filename;
|
|
|
+ }
|
|
|
+
|
|
|
private void reMultipart(String account, String subject, Date emailDate, Multipart multipart,
|
|
|
List<EmailContentInfoDTO> emailContentInfoDTOList) throws Exception {
|
|
|
for (int i = 0; i < multipart.getCount(); i++) {
|