24282 2 лет назад
Родитель
Сommit
75ef395cae

+ 161 - 120
src/main/java/com/fjhx/service/impl/AccountServiceImpl.java

@@ -2,7 +2,6 @@ package com.fjhx.service.impl;
 
 
 import cn.hutool.core.bean.BeanUtil;
 import cn.hutool.core.bean.BeanUtil;
 import cn.hutool.core.io.FileUtil;
 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.IdWorker;
 import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
 import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
@@ -16,6 +15,7 @@ import com.fjhx.vo.BindingVo;
 import com.fjhx.vo.EmailMailboxVo;
 import com.fjhx.vo.EmailMailboxVo;
 import com.fjhx.vo.MessageDetailVo;
 import com.fjhx.vo.MessageDetailVo;
 import com.fjhx.vo.MessageVo;
 import com.fjhx.vo.MessageVo;
+import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Qualifier;
 import org.springframework.beans.factory.annotation.Qualifier;
 import org.springframework.stereotype.Service;
 import org.springframework.stereotype.Service;
@@ -26,6 +26,7 @@ import java.util.List;
 import java.util.concurrent.Executor;
 import java.util.concurrent.Executor;
 import java.util.stream.Collectors;
 import java.util.stream.Collectors;
 
 
+@Slf4j
 @Service
 @Service
 public class AccountServiceImpl implements IAccountService {
 public class AccountServiceImpl implements IAccountService {
 
 
@@ -106,136 +107,176 @@ public class AccountServiceImpl implements IAccountService {
      */
      */
     private void asyncReadEmail(String email, List<EmailMailbox> emailMailboxList) {
     private void asyncReadEmail(String email, List<EmailMailbox> emailMailboxList) {
         executor.execute(() -> {
         executor.execute(() -> {
-            ThreadUtil.sleep(5000);
+            // ThreadUtil.sleep(5000);
 
 
             // 记录上次消息id,防止循环查询分页过程中接收到了新邮件,出现邮件重复问题
             // 记录上次消息id,防止循环查询分页过程中接收到了新邮件,出现邮件重复问题
-            List<String> lastMessageId = new ArrayList<>();
+            List<String> lastMessageIdList = new ArrayList<>();
 
 
+            // 遍历每个邮箱
             for (EmailMailbox emailMailbox : emailMailboxList) {
             for (EmailMailbox emailMailbox : emailMailboxList) {
+                // 保存邮箱中的邮件
                 EmailEngineUtil.handleMessageList(
                 EmailEngineUtil.handleMessageList(
                         email,
                         email,
                         emailMailbox.getPath(),
                         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);
-                                emailMessage.setMessageId(messagesDTO.getId());
-                                emailMessage.setEmailMailboxId(emailMailbox.getId());
-                                emailMessage.setEmailMailboxPath(emailMailbox.getPath());
-                                emailMessage.setUnseen(messagesDTO.getUnseen());
-                                emailMessage.setFlagged(messagesDTO.getFlagged());
-                                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) {
-                                        EmailMessageSend emailMessageSend = new EmailMessageSend();
-                                        emailMessageSend.setEmailMessageId(id);
-                                        emailMessageSend.setMessageId(messagesDTO.getId());
-                                        emailMessageSend.setType(SendConstants.TO);
-                                        emailMessageSend.setName(toDTO.getName());
-                                        emailMessageSend.setAddress(toDTO.getAddress());
-                                        emailMessageSendList.add(emailMessageSend);
-                                    }
-                                }
-
-                                // 抄送人
-                                List<MessageVo.MessagesDTO.ToDTO> cc = messagesDTO.getCc();
-                                if (ObjectUtils.isNotEmpty(cc)) {
-                                    for (MessageVo.MessagesDTO.ToDTO toDTO : cc) {
-                                        EmailMessageSend emailMessageSend = new EmailMessageSend();
-                                        emailMessageSend.setEmailMessageId(id);
-                                        emailMessageSend.setMessageId(messagesDTO.getId());
-                                        emailMessageSend.setType(SendConstants.CC);
-                                        emailMessageSend.setName(toDTO.getName());
-                                        emailMessageSend.setAddress(toDTO.getAddress());
-                                        emailMessageSendList.add(emailMessageSend);
-                                    }
-                                }
-
-                                // 密送人
-                                List<MessageVo.MessagesDTO.ToDTO> bcc = messagesDTO.getBcc();
-                                if (ObjectUtils.isNotEmpty(bcc)) {
-                                    for (MessageVo.MessagesDTO.ToDTO toDTO : cc) {
-                                        EmailMessageSend emailMessageSend = new EmailMessageSend();
-                                        emailMessageSend.setEmailMessageId(id);
-                                        emailMessageSend.setMessageId(messagesDTO.getId());
-                                        emailMessageSend.setType(SendConstants.BCC);
-                                        emailMessageSend.setName(toDTO.getName());
-                                        emailMessageSend.setAddress(toDTO.getAddress());
-                                        emailMessageSendList.add(emailMessageSend);
-                                    }
-                                }
-
-                                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());
-                            }
-
-                        }
+                        messageList -> this.saveBatchMessage(email, lastMessageIdList, emailMailbox, messageList)
                 );
                 );
             }
             }
+
         });
         });
+    }
+
+
+    /**
+     * 批量保存邮件信息
+     */
+    private void saveBatchMessage(String email, List<String> lastMessageId, EmailMailbox emailMailbox, List<MessageVo.MessagesDTO> 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;
+            }
+
+            // 生成邮件实体
+            EmailMessage emailMessage = createMessage(email, emailMailbox, messagesDTO);
+
+            emailMessageList.add(emailMessage);
+
+            // 添加推送信息
+            addMessageSend(emailMessageSendList, messagesDTO, emailMessage.getId());
+
+            // 下载并添加附件信息
+            addMessageAttachment(email, emailMessageAttachmentList, messagesDTO, emailMessage.getId());
+
+        }
+
+        emailMessageService.saveBatch(emailMessageList);
+        emailMessageSendService.saveBatch(emailMessageSendList);
+        emailMessageAttachmentService.saveBatch(emailMessageAttachmentList);
+
+        lastMessageId.clear();
+        for (EmailMessage emailMessage : emailMessageList) {
+            lastMessageId.add(emailMessage.getMessageId());
+        }
+
+    }
+
+
+    /**
+     * 生成邮件实体
+     */
+    private EmailMessage createMessage(String email, EmailMailbox emailMailbox, MessageVo.MessagesDTO messagesDTO) {
+
+        EmailMessage emailMessage = new EmailMessage();
+        emailMessage.setId(IdWorker.getId());
+        emailMessage.setMessageId(messagesDTO.getId());
+        emailMessage.setEmailMailboxId(emailMailbox.getId());
+        emailMessage.setEmailMailboxPath(emailMailbox.getPath());
+        emailMessage.setUnseen(messagesDTO.getUnseen());
+        emailMessage.setFlagged(messagesDTO.getFlagged());
+        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 messageDetail = EmailEngineUtil.getMessageDetail(email, messagesDTO.getId());
+        MessageDetailVo.TextDTO text = messageDetail.getText();
+        if (ObjectUtils.isNotEmpty(text)) {
+            emailMessage.setHtmlContent(text.getHtml());
+        }
+
+        return emailMessage;
+    }
+
+    /**
+     * 添加推送信息
+     */
+    private void addMessageSend(List<EmailMessageSend> emailMessageSendList, MessageVo.MessagesDTO messagesDTO, Long emailMessageId) {
+        // 收件人
+        List<MessageVo.MessagesDTO.ToDTO> to = messagesDTO.getTo();
+        if (ObjectUtils.isNotEmpty(to)) {
+            for (MessageVo.MessagesDTO.ToDTO toDTO : to) {
+                EmailMessageSend emailMessageSend = new EmailMessageSend();
+                emailMessageSend.setEmailMessageId(emailMessageId);
+                emailMessageSend.setMessageId(messagesDTO.getId());
+                emailMessageSend.setType(SendConstants.TO);
+                emailMessageSend.setName(toDTO.getName());
+                emailMessageSend.setAddress(toDTO.getAddress());
+                emailMessageSendList.add(emailMessageSend);
+            }
+        }
+
+        // 抄送人
+        List<MessageVo.MessagesDTO.ToDTO> cc = messagesDTO.getCc();
+        if (ObjectUtils.isNotEmpty(cc)) {
+            for (MessageVo.MessagesDTO.ToDTO toDTO : cc) {
+                EmailMessageSend emailMessageSend = new EmailMessageSend();
+                emailMessageSend.setEmailMessageId(emailMessageId);
+                emailMessageSend.setMessageId(messagesDTO.getId());
+                emailMessageSend.setType(SendConstants.CC);
+                emailMessageSend.setName(toDTO.getName());
+                emailMessageSend.setAddress(toDTO.getAddress());
+                emailMessageSendList.add(emailMessageSend);
+            }
+        }
+
+        // 密送人
+        List<MessageVo.MessagesDTO.ToDTO> bcc = messagesDTO.getBcc();
+        if (ObjectUtils.isNotEmpty(bcc)) {
+            for (MessageVo.MessagesDTO.ToDTO toDTO : cc) {
+                EmailMessageSend emailMessageSend = new EmailMessageSend();
+                emailMessageSend.setEmailMessageId(emailMessageId);
+                emailMessageSend.setMessageId(messagesDTO.getId());
+                emailMessageSend.setType(SendConstants.BCC);
+                emailMessageSend.setName(toDTO.getName());
+                emailMessageSend.setAddress(toDTO.getAddress());
+                emailMessageSendList.add(emailMessageSend);
+            }
+        }
+    }
 
 
+    /**
+     * 下载并添加附件信息
+     */
+    private void addMessageAttachment(String email, List<EmailMessageAttachment> emailMessageAttachmentList,
+                                      MessageVo.MessagesDTO messagesDTO, Long emailMessageId) {
+
+        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());
+
+                // 下载附件
+                try {
+                    Boolean flag = RetryUtil.execute(() -> EmailEngineUtil.downloadAttachment(email, attachmentId, newFileName));
+
+                    if (flag) {
+                        EmailMessageAttachment emailMessageAttachment = new EmailMessageAttachment();
+                        emailMessageAttachment.setEmailMessageId(emailMessageId);
+                        emailMessageAttachment.setMessageId(messagesDTO.getId());
+                        emailMessageAttachment.setName(attachment.getFilename());
+                        emailMessageAttachment.setPath(email + "\\" + newFileName);
+                        emailMessageAttachment.setAttachmentId(attachmentId);
+                        emailMessageAttachment.setSize(attachment.getEncodedSize());
+                        emailMessageAttachmentList.add(emailMessageAttachment);
+                    }
+
+                } catch (Exception e) {
+                    log.error("下载附件失败:", e);
+                }
+
+            }
+        }
     }
     }
 
 
 }
 }

+ 37 - 7
src/main/java/com/fjhx/utils/EmailEngineUtil.java

@@ -5,14 +5,16 @@ import cn.hutool.core.lang.Assert;
 import cn.hutool.http.HttpUtil;
 import cn.hutool.http.HttpUtil;
 import com.fjhx.vo.*;
 import com.fjhx.vo.*;
 import lombok.extern.slf4j.Slf4j;
 import lombok.extern.slf4j.Slf4j;
+import org.jetbrains.annotations.NotNull;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.beans.factory.annotation.Value;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.client.ClientHttpResponse;
 import org.springframework.stereotype.Component;
 import org.springframework.stereotype.Component;
+import org.springframework.web.client.ResponseErrorHandler;
 import org.springframework.web.client.RestTemplate;
 import org.springframework.web.client.RestTemplate;
 
 
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.OutputStream;
+import java.io.*;
+import java.rmi.RemoteException;
 import java.util.List;
 import java.util.List;
 import java.util.function.Consumer;
 import java.util.function.Consumer;
 
 
@@ -26,6 +28,24 @@ public class EmailEngineUtil {
 
 
     private static final RestTemplate restTemplate = new RestTemplate();
     private static final RestTemplate restTemplate = new RestTemplate();
 
 
+    static {
+        restTemplate.setErrorHandler(new ResponseErrorHandler() {
+            @Override
+            public boolean hasError(@NotNull ClientHttpResponse response) throws IOException {
+                HttpStatus.Series series = response.getStatusCode().series();
+                return !HttpStatus.Series.SUCCESSFUL.equals(series);
+            }
+
+            @Override
+            public void handleError(@NotNull ClientHttpResponse response) throws IOException {
+                InputStream body = response.getBody();
+                byte[] bytes = new byte[body.available()];
+                String result = new String(bytes);
+                throw new RemoteException(result);
+            }
+        });
+    }
+
     @Value("${config.urlPrefix}")
     @Value("${config.urlPrefix}")
     public void setUrlPrefix(String urlPrefix) {
     public void setUrlPrefix(String urlPrefix) {
         EmailEngineUtil.urlPrefix = urlPrefix;
         EmailEngineUtil.urlPrefix = urlPrefix;
@@ -97,15 +117,17 @@ public class EmailEngineUtil {
     /**
     /**
      * 下载附件
      * 下载附件
      */
      */
-    public static void downloadAttachment(String email, String attachmentId, String fileName) throws FileNotFoundException {
+    public static boolean downloadAttachment(String email, String attachmentId, String fileName) throws FileNotFoundException {
         File file = new File(attachmentPath + email);
         File file = new File(attachmentPath + email);
         if (!file.exists()) {
         if (!file.exists()) {
             boolean mkdir = file.mkdir();
             boolean mkdir = file.mkdir();
             Assert.isTrue(mkdir, "创建文件夹失败");
             Assert.isTrue(mkdir, "创建文件夹失败");
+            return false;
         }
         }
 
 
         FileOutputStream fileOutputStream = new FileOutputStream(attachmentPath + email + "\\" + fileName);
         FileOutputStream fileOutputStream = new FileOutputStream(attachmentPath + email + "\\" + fileName);
         download("v1/account/" + email + "/attachment/" + attachmentId, fileOutputStream);
         download("v1/account/" + email + "/attachment/" + attachmentId, fileOutputStream);
+        return true;
     }
     }
 
 
     /**
     /**
@@ -183,11 +205,19 @@ public class EmailEngineUtil {
     }
     }
 
 
     public static <T> T get(String url, Class<T> cls) {
     public static <T> T get(String url, Class<T> cls) {
-        return restTemplate.getForObject(urlPrefix + url, cls);
+        try {
+            return RetryUtil.execute(() -> restTemplate.getForObject(urlPrefix + url, cls), 5, 3000L);
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
     }
     }
 
 
     public static <T> T post(String url, Object paramObj, Class<T> cls) {
     public static <T> T post(String url, Object paramObj, Class<T> cls) {
-        return restTemplate.postForObject(urlPrefix + url, paramObj, cls);
+        try {
+            return RetryUtil.execute(() -> restTemplate.postForObject(urlPrefix + url, paramObj, cls), 5, 3000L);
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
     }
     }
 
 
 }
 }

+ 14 - 12
src/main/java/com/fjhx/utils/RetryUtil.java

@@ -8,30 +8,32 @@ public class RetryUtil {
 
 
     /**
     /**
      * 重试机制
      * 重试机制
+     * 默认执行3次
+     * 每次失败等待1秒
      */
      */
-    public static boolean execute(RetryRunnable runnable) {
+    public static <T> T execute(RetryRunnable<T> runnable) throws Exception {
         return execute(runnable, 0, 3, 1000L);
         return execute(runnable, 0, 3, 1000L);
     }
     }
 
 
-    public static boolean execute(RetryRunnable runnable, int executeCount, int maxCount, Long sleep) {
-
-        if (executeCount >= maxCount) {
-            return false;
-        }
+    public static <T> T execute(RetryRunnable<T> runnable, int maxCount, Long sleep) throws Exception {
+        return execute(runnable, 0, maxCount, sleep);
+    }
 
 
+    public static <T> T execute(RetryRunnable<T> runnable, int executeCount, int maxCount, Long sleep) throws Exception {
         try {
         try {
-            runnable.run();
-            return true;
+            return runnable.run();
         } catch (Exception e) {
         } catch (Exception e) {
-            log.error("runnable.run()", e);
+            if (executeCount >= maxCount) {
+                throw e;
+            }
+            log.warn("任务执行失败,最多允许失败{}次,已失败{}次,{}秒后开始重试", maxCount, executeCount + 1, sleep / 1000, e);
             ThreadUtil.sleep(sleep);
             ThreadUtil.sleep(sleep);
             return execute(runnable, ++executeCount, maxCount, sleep);
             return execute(runnable, ++executeCount, maxCount, sleep);
         }
         }
     }
     }
 
 
-
-    public interface RetryRunnable {
-        void run() throws Exception;
+    public interface RetryRunnable<T> {
+        T run() throws Exception;
     }
     }
 
 
 }
 }