24282 2 years ago
parent
commit
c0d2b8c658

+ 1 - 1
src/main/java/com/fjhx/config/CodeGeneration.java

@@ -25,7 +25,7 @@ public class CodeGeneration {
                 })
                 .strategyConfig(builder -> builder
                         // 设置需要生成的表名
-                        .addInclude("email_message_send")
+                        .addInclude("email_message_attachment")
                         .entityBuilder()
                         .disableSerialVersionUID()
                         .superClass(BaseEntity.class)

+ 18 - 0
src/main/java/com/fjhx/controller/EmailMessageAttachmentController.java

@@ -0,0 +1,18 @@
+package com.fjhx.controller;
+
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.stereotype.Controller;
+
+/**
+ * <p>
+ * 文件附件 前端控制器
+ * </p>
+ *
+ * @author zlj
+ * @since 2022-12-21
+ */
+@Controller
+@RequestMapping("/emailMessageAttachment")
+public class EmailMessageAttachmentController {
+
+}

+ 52 - 0
src/main/java/com/fjhx/entity/EmailMessageAttachment.java

@@ -0,0 +1,52 @@
+package com.fjhx.entity;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.fjhx.base.BaseEntity;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * <p>
+ * 文件附件
+ * </p>
+ *
+ * @author zlj
+ * @since 2022-12-21
+ */
+@Getter
+@Setter
+@TableName("email_message_attachment")
+public class EmailMessageAttachment extends BaseEntity {
+
+    /**
+     * 附件id
+     */
+    private String attachmentId;
+
+    /**
+     * 文件id
+     */
+    private Long emailMessageId;
+
+    /**
+     * 文件id
+     */
+    private String messageId;
+
+    /**
+     * 附件名称
+     */
+    private String name;
+
+    /**
+     * 附件地址
+     */
+    private String path;
+
+    /**
+     * 附件大小
+     */
+    private Integer size;
+
+
+}

+ 16 - 0
src/main/java/com/fjhx/mapper/EmailMessageAttachmentMapper.java

@@ -0,0 +1,16 @@
+package com.fjhx.mapper;
+
+import com.fjhx.entity.EmailMessageAttachment;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+/**
+ * <p>
+ * 文件附件 Mapper 接口
+ * </p>
+ *
+ * @author zlj
+ * @since 2022-12-21
+ */
+public interface EmailMessageAttachmentMapper extends BaseMapper<EmailMessageAttachment> {
+
+}

+ 5 - 0
src/main/java/com/fjhx/mapper/xml/EmailMessageAttachmentMapper.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.fjhx.mapper.EmailMessageAttachmentMapper">
+
+</mapper>

+ 16 - 0
src/main/java/com/fjhx/service/IEmailMessageAttachmentService.java

@@ -0,0 +1,16 @@
+package com.fjhx.service;
+
+import com.fjhx.entity.EmailMessageAttachment;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ * <p>
+ * 文件附件 服务类
+ * </p>
+ *
+ * @author zlj
+ * @since 2022-12-21
+ */
+public interface IEmailMessageAttachmentService extends IService<EmailMessageAttachment> {
+
+}

+ 54 - 5
src/main/java/com/fjhx/service/impl/AccountServiceImpl.java

@@ -1,18 +1,17 @@
 package com.fjhx.service.impl;
 
 import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.io.FileUtil;
 import cn.hutool.core.thread.ThreadUtil;
 import com.baomidou.mybatisplus.core.toolkit.IdWorker;
 import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.fjhx.config.TaskPoolConfig;
 import com.fjhx.constants.SendConstants;
-import com.fjhx.entity.EmailInfo;
-import com.fjhx.entity.EmailMailbox;
-import com.fjhx.entity.EmailMessage;
-import com.fjhx.entity.EmailMessageSend;
+import com.fjhx.entity.*;
 import com.fjhx.service.*;
 import com.fjhx.utils.EmailEngineUtil;
+import com.fjhx.utils.RetryUtil;
 import com.fjhx.vo.BindingVo;
 import com.fjhx.vo.EmailMailboxVo;
 import com.fjhx.vo.MessageDetailVo;
@@ -42,6 +41,9 @@ public class AccountServiceImpl implements IAccountService {
     @Autowired
     private IEmailMessageSendService emailMessageSendService;
 
+    @Autowired
+    private IEmailMessageAttachmentService emailMessageAttachmentService;
+
     @Qualifier(TaskPoolConfig.taskExecutor)
     @Autowired
     private Executor executor;
@@ -106,16 +108,26 @@ public class AccountServiceImpl implements IAccountService {
         executor.execute(() -> {
             ThreadUtil.sleep(5000);
 
+            // 记录上次消息id,防止循环查询分页过程中接收到了新邮件,出现邮件重复问题
+            List<String> lastMessageId = new ArrayList<>();
+
             for (EmailMailbox emailMailbox : emailMailboxList) {
-                EmailEngineUtil.getMessageList(
+                EmailEngineUtil.handleMessageList(
                         email,
                         emailMailbox.getPath(),
                         messageList -> {
                             List<EmailMessage> emailMessageList = new ArrayList<>();
                             List<EmailMessageSend> emailMessageSendList = new ArrayList<>();
+                            List<EmailMessageAttachment> emailMessageAttachmentList = new ArrayList<>();
+
                             for (MessageVo.MessagesDTO messagesDTO : messageList) {
+                                if (lastMessageId.contains(messagesDTO.getId())) {
+                                    continue;
+                                }
+
                                 MessageDetailVo messageDetail = EmailEngineUtil.getMessageDetail(email, messagesDTO.getId());
 
+                                // 基本信息
                                 EmailMessage emailMessage = new EmailMessage();
                                 long id = IdWorker.getId();
                                 emailMessage.setId(id);
@@ -127,17 +139,20 @@ public class AccountServiceImpl implements IAccountService {
                                 emailMessage.setSubject(messagesDTO.getSubject());
                                 emailMessage.setFromDate(messagesDTO.getDate());
 
+                                // 发件人
                                 MessageVo.MessagesDTO.ToDTO from = messagesDTO.getFrom();
                                 if (ObjectUtils.isNotEmpty(from)) {
                                     emailMessage.setFromName(from.getName());
                                     emailMessage.setFromAddress(from.getAddress());
                                 }
 
+                                // 正文内容
                                 MessageDetailVo.TextDTO text = messageDetail.getText();
                                 if (ObjectUtils.isNotEmpty(text)) {
                                     emailMessage.setHtmlContent(text.getHtml());
                                 }
 
+                                // 收件人
                                 List<MessageVo.MessagesDTO.ToDTO> to = messagesDTO.getTo();
                                 if (ObjectUtils.isNotEmpty(to)) {
                                     for (MessageVo.MessagesDTO.ToDTO toDTO : to) {
@@ -151,6 +166,7 @@ public class AccountServiceImpl implements IAccountService {
                                     }
                                 }
 
+                                // 抄送人
                                 List<MessageVo.MessagesDTO.ToDTO> cc = messagesDTO.getCc();
                                 if (ObjectUtils.isNotEmpty(cc)) {
                                     for (MessageVo.MessagesDTO.ToDTO toDTO : cc) {
@@ -164,6 +180,7 @@ public class AccountServiceImpl implements IAccountService {
                                     }
                                 }
 
+                                // 密送人
                                 List<MessageVo.MessagesDTO.ToDTO> bcc = messagesDTO.getBcc();
                                 if (ObjectUtils.isNotEmpty(bcc)) {
                                     for (MessageVo.MessagesDTO.ToDTO toDTO : cc) {
@@ -177,11 +194,43 @@ public class AccountServiceImpl implements IAccountService {
                                     }
                                 }
 
+                                List<MessageVo.MessagesDTO.AttachmentsDTO> attachments = messagesDTO.getAttachments();
+                                if (ObjectUtils.isNotEmpty(attachments)) {
+                                    for (MessageVo.MessagesDTO.AttachmentsDTO attachment : attachments) {
+                                        String attachmentId = attachment.getId();
+
+                                        String newFileName = attachmentId + "." + FileUtil.getSuffix(attachment.getFilename());
+
+                                        // 异常重试
+                                        boolean execute = RetryUtil.execute(() -> EmailEngineUtil.downloadAttachment(email, attachmentId, newFileName));
+
+                                        // TODO 下载失败加入日志
+                                        if (execute) {
+                                            EmailMessageAttachment emailMessageAttachment = new EmailMessageAttachment();
+                                            emailMessageAttachment.setEmailMessageId(id);
+                                            emailMessageAttachment.setMessageId(messagesDTO.getId());
+                                            emailMessageAttachment.setName(attachment.getFilename());
+                                            emailMessageAttachment.setPath(email + "\\" + newFileName);
+                                            emailMessageAttachment.setAttachmentId(attachmentId);
+                                            emailMessageAttachment.setSize(attachment.getEncodedSize());
+                                            emailMessageAttachmentList.add(emailMessageAttachment);
+                                        }
+
+                                    }
+                                }
+
                                 emailMessageList.add(emailMessage);
                             }
 
                             emailMessageService.saveBatch(emailMessageList);
                             emailMessageSendService.saveBatch(emailMessageSendList);
+                            emailMessageAttachmentService.saveBatch(emailMessageAttachmentList);
+
+                            lastMessageId.clear();
+                            for (EmailMessage emailMessage : emailMessageList) {
+                                lastMessageId.add(emailMessage.getMessageId());
+                            }
+
                         }
                 );
             }

+ 20 - 0
src/main/java/com/fjhx/service/impl/EmailMessageAttachmentServiceImpl.java

@@ -0,0 +1,20 @@
+package com.fjhx.service.impl;
+
+import com.fjhx.entity.EmailMessageAttachment;
+import com.fjhx.mapper.EmailMessageAttachmentMapper;
+import com.fjhx.service.IEmailMessageAttachmentService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.stereotype.Service;
+
+/**
+ * <p>
+ * 文件附件 服务实现类
+ * </p>
+ *
+ * @author zlj
+ * @since 2022-12-21
+ */
+@Service
+public class EmailMessageAttachmentServiceImpl extends ServiceImpl<EmailMessageAttachmentMapper, EmailMessageAttachment> implements IEmailMessageAttachmentService {
+
+}

+ 34 - 6
src/main/java/com/fjhx/utils/EmailEngineUtil.java

@@ -2,22 +2,27 @@ package com.fjhx.utils;
 
 import cn.hutool.core.bean.BeanUtil;
 import cn.hutool.core.lang.Assert;
+import cn.hutool.http.HttpUtil;
 import com.fjhx.vo.*;
-import lombok.Data;
-import lombok.NoArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Component;
 import org.springframework.web.client.RestTemplate;
 
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.OutputStream;
 import java.util.List;
 import java.util.function.Consumer;
 
-@NoArgsConstructor
-@Data
+@Slf4j
 @Component
 public class EmailEngineUtil {
 
-    private static String urlPrefix;
+    public static String urlPrefix;
+
+    public static String attachmentPath;
 
     private static final RestTemplate restTemplate = new RestTemplate();
 
@@ -26,6 +31,11 @@ public class EmailEngineUtil {
         EmailEngineUtil.urlPrefix = urlPrefix;
     }
 
+    @Value("${config.attachmentPath}")
+    public void setAttachmentPath(String attachmentPath) {
+        EmailEngineUtil.attachmentPath = attachmentPath;
+    }
+
     /**
      * 生成邮箱
      */
@@ -56,7 +66,7 @@ public class EmailEngineUtil {
     /**
      * 查看文件夹的所有邮件
      */
-    public static void getMessageList(String email, String mailboxName, Consumer<List<MessageVo.MessagesDTO>> consumer) {
+    public static void handleMessageList(String email, String mailboxName, Consumer<List<MessageVo.MessagesDTO>> consumer) {
         int page = 0;
         int pages;
 
@@ -73,6 +83,7 @@ public class EmailEngineUtil {
             pages = result.getPages();
             page++;
         } while (page < pages);
+
     }
 
     /**
@@ -83,6 +94,19 @@ public class EmailEngineUtil {
         return get(url, MessageDetailVo.class);
     }
 
+    /**
+     * 下载附件
+     */
+    public static void downloadAttachment(String email, String attachmentId, String fileName) throws FileNotFoundException {
+        File file = new File(attachmentPath + email);
+        if (!file.exists()) {
+            boolean mkdir = file.mkdir();
+            Assert.isTrue(mkdir, "创建文件夹失败");
+        }
+
+        FileOutputStream fileOutputStream = new FileOutputStream(attachmentPath + email + "\\" + fileName);
+        download("v1/account/" + email + "/attachment/" + attachmentId, fileOutputStream);
+    }
 
     /**
      * 生成验证邮箱配置实体
@@ -154,6 +178,10 @@ public class EmailEngineUtil {
                 addAccountResult.getAccount(), addAccountResult.getState());
     }
 
+    private static void download(String url, OutputStream outputStream) {
+        HttpUtil.download(urlPrefix + url, outputStream, true);
+    }
+
     public static <T> T get(String url, Class<T> cls) {
         return restTemplate.getForObject(urlPrefix + url, cls);
     }

+ 37 - 0
src/main/java/com/fjhx/utils/RetryUtil.java

@@ -0,0 +1,37 @@
+package com.fjhx.utils;
+
+import cn.hutool.core.thread.ThreadUtil;
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+public class RetryUtil {
+
+    /**
+     * 重试机制
+     */
+    public static boolean execute(RetryRunnable runnable) {
+        return execute(runnable, 0, 3, 1000L);
+    }
+
+    public static boolean execute(RetryRunnable runnable, int executeCount, int maxCount, Long sleep) {
+
+        if (executeCount >= maxCount) {
+            return false;
+        }
+
+        try {
+            runnable.run();
+            return true;
+        } catch (Exception e) {
+            log.error("runnable.run()", e);
+            ThreadUtil.sleep(sleep);
+            return execute(runnable, ++executeCount, maxCount, sleep);
+        }
+    }
+
+
+    public interface RetryRunnable {
+        void run() throws Exception;
+    }
+
+}

+ 2 - 1
src/main/resources/application-dev.yml

@@ -26,4 +26,5 @@ mybatis-plus:
 
 
 config:
-  urlPrefix: "http://localhost:3000/"
+  urlPrefix: http://localhost:3000/
+  attachmentPath: D:\24282\Downloads\

+ 2 - 1
src/main/resources/application-pro.yml

@@ -21,4 +21,5 @@ spring:
     database: 0
 
 config:
-  urlPrefix: "http://localhost:3000/"
+  urlPrefix: http://localhost:3000/
+  attachmentPath: D:\24282\Downloads\