|
|
@@ -0,0 +1,1959 @@
|
|
|
+package com.storlead.mail.service.impl;
|
|
|
+
|
|
|
+import cn.hutool.core.util.StrUtil;
|
|
|
+import com.alibaba.fastjson.JSON;
|
|
|
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
|
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
|
|
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
|
|
+import com.baomidou.mybatisplus.core.metadata.IPage;
|
|
|
+import com.storlead.framework.common.constant.CommonConstant;
|
|
|
+import com.storlead.framework.common.util.*;
|
|
|
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
|
|
+import com.storlead.framework.common.util.encryptor.AccessKeyEncryptor;
|
|
|
+import com.storlead.framework.redis.RedisService;
|
|
|
+import com.storlead.mail.connection.MailConnection;
|
|
|
+import com.storlead.mail.connection.client.MailConnectionUtil;
|
|
|
+import com.storlead.mail.connection.config.MailProperties;
|
|
|
+import com.storlead.mail.pojo.entity.*;
|
|
|
+import com.storlead.mail.pojo.vo.CustomerEmailVo;
|
|
|
+import com.storlead.mail.pojo.vo.CustomerMailVO;
|
|
|
+import com.storlead.mail.pojo.vo.NewMailCountTipVO;
|
|
|
+import com.storlead.mail.pojo.vo.UserClickTitleVO;
|
|
|
+import com.storlead.mail.properties.MailFileProperties;
|
|
|
+import com.storlead.mail.enums.EmailBoxEnum;
|
|
|
+import com.storlead.mail.enums.SendStatus;
|
|
|
+import com.storlead.mail.mapper.EmailsMapper;
|
|
|
+import com.storlead.mail.pojo.MailDTO;
|
|
|
+import com.storlead.mail.pojo.MailListDTO;
|
|
|
+import com.storlead.mail.pojo.SendMailDTO;
|
|
|
+import com.storlead.mail.service.*;
|
|
|
+import com.storlead.framework.mybatis.service.impl.MyBaseServiceImpl;
|
|
|
+import com.storlead.mail.util.EmailHelper;
|
|
|
+import com.storlead.mail.util.EmailSenderWithThreadLocal;
|
|
|
+import com.storlead.mail.util.ReceiveMailQueueThreadPool;
|
|
|
+import com.sun.mail.imap.IMAPFolder;
|
|
|
+import com.sun.mail.pop3.POP3Folder;
|
|
|
+import lombok.extern.log4j.Log4j2;
|
|
|
+import org.apache.commons.compress.utils.FileNameUtils;
|
|
|
+import org.springframework.core.env.Environment;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+import org.springframework.util.CollectionUtils;
|
|
|
+import javax.activation.DataHandler;
|
|
|
+import javax.activation.DataSource;
|
|
|
+import javax.activation.FileDataSource;
|
|
|
+import javax.annotation.Resource;
|
|
|
+import javax.mail.*;
|
|
|
+import javax.mail.internet.*;
|
|
|
+import javax.mail.search.*;
|
|
|
+import java.io.*;
|
|
|
+import java.lang.reflect.Method;
|
|
|
+import java.nio.charset.StandardCharsets;
|
|
|
+import java.nio.file.Path;
|
|
|
+import java.nio.file.Paths;
|
|
|
+import java.time.LocalDate;
|
|
|
+import java.time.LocalDateTime;
|
|
|
+import java.time.ZoneId;
|
|
|
+import java.time.temporal.ChronoUnit;
|
|
|
+import java.util.*;
|
|
|
+import java.util.concurrent.CompletableFuture;
|
|
|
+import java.util.concurrent.ConcurrentHashMap;
|
|
|
+import java.util.concurrent.ConcurrentMap;
|
|
|
+import java.util.concurrent.TimeUnit;
|
|
|
+import java.util.concurrent.locks.Lock;
|
|
|
+import java.util.stream.Collectors;
|
|
|
+
|
|
|
+/**
|
|
|
+ * <p>
|
|
|
+ * 邮件表 服务实现类
|
|
|
+ * </p>
|
|
|
+ *
|
|
|
+ * @author chenkq
|
|
|
+ * @since 2024-05-28
|
|
|
+ */
|
|
|
+@Log4j2
|
|
|
+@Service
|
|
|
+public class EmailsServiceImpl extends MyBaseServiceImpl<EmailsMapper, EmailsEntity> implements EmailsService {
|
|
|
+
|
|
|
+
|
|
|
+ private final ConcurrentMap<String, Boolean> processedMessages = new ConcurrentHashMap<>();
|
|
|
+
|
|
|
+ private static final ConcurrentHashMap<Long, Lock> userLockMap = new ConcurrentHashMap<>();
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 附件下载控制
|
|
|
+ */
|
|
|
+ private final ConcurrentMap<Long, Boolean> processedDownloadMailIds = new ConcurrentHashMap<>();
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ private SmtpPopSettingsService popSettingsService;
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ private MailFileProperties mailFileProperties;
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ private MailAttachmentService mailAttachmentService;
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ private MailTempAttachmentService tempAttachmentService;
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ private MailDelayPullRecordService delayPullRecordService;
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ private EmailSenderWithThreadLocal senderWithThreadLocal;
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ private RedisService redisService;
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ private EmailBlacklistRecordService blackListService;
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ private EmailFolderRuleService folderRuleService;
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ private Environment environment;
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void updateSelectBindCustomerMail() {
|
|
|
+ // this.baseMapper.updateCleanBindCustomerMail();
|
|
|
+ // this.baseMapper.updateBindLiaisonMail();
|
|
|
+ // this.baseMapper.updateBindCustomerMail();
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public SendStatus sendEmail(SendMailDTO dto, SmtpPopSettingsEntity smtpPop) {
|
|
|
+// String active = environment.getProperty("spring.profiles.active");
|
|
|
+// if("dev".equals(active)) {
|
|
|
+// return SendStatus.SUCCESS;
|
|
|
+// }
|
|
|
+ try {
|
|
|
+ if(Objects.isNull(dto.getRecipientCcls())) {
|
|
|
+ dto.setRecipientCcls(new ArrayList<>());
|
|
|
+ }
|
|
|
+ if(Objects.isNull(dto.getRecipientBccls())) {
|
|
|
+ dto.setRecipientBccls(new ArrayList<>());
|
|
|
+ }
|
|
|
+ if(Objects.isNull(dto.getRecipientls())) {
|
|
|
+ dto.setRecipientls(new ArrayList<>());
|
|
|
+ }
|
|
|
+ String fromAddress = smtpPop.getEmailAddress();
|
|
|
+ String fromNickName = smtpPop.getSenderNickName();
|
|
|
+
|
|
|
+ Session session = getSendEmailsSession(smtpPop);
|
|
|
+ InternetAddress [] froms = new InternetAddress[dto.getRecipientls().size()];
|
|
|
+ for (int i = 0; i < dto.getRecipientls().size(); i++) {
|
|
|
+ froms[i] = new InternetAddress(dto.getRecipientls().get(i));
|
|
|
+ }
|
|
|
+ InternetAddress [] fromsCC = new InternetAddress[dto.getRecipientCcls().size()];
|
|
|
+ for (int i = 0; i < dto.getRecipientCcls().size(); i++) {
|
|
|
+ fromsCC[i] = new InternetAddress(dto.getRecipientCcls().get(i));
|
|
|
+ }
|
|
|
+
|
|
|
+ InternetAddress [] fromsBCC = new InternetAddress[dto.getRecipientBccls().size()];
|
|
|
+ for (int i = 0; i < dto.getRecipientBccls().size(); i++) {
|
|
|
+ fromsBCC[i] = new InternetAddress(dto.getRecipientBccls().get(i));
|
|
|
+ }
|
|
|
+ Transport transport = session.getTransport("smtp");
|
|
|
+ int sizeInBytes = 0;
|
|
|
+ try {
|
|
|
+ MimeMessage message = new MimeMessage(session);
|
|
|
+ if (Objects.nonNull(froms) && froms.length > 0) {
|
|
|
+ message.setRecipients(Message.RecipientType.TO,froms);
|
|
|
+ }
|
|
|
+ if (Objects.nonNull(fromsCC) && fromsCC.length > 0) {
|
|
|
+ message.setRecipients(Message.RecipientType.CC,fromsCC);
|
|
|
+ }
|
|
|
+ if (Objects.nonNull(fromsBCC) && fromsBCC.length > 0) {
|
|
|
+ message.setRecipients(Message.RecipientType.BCC,fromsBCC);
|
|
|
+ }
|
|
|
+ if (CollectionUtils.isEmpty(dto.getFileIds()) && CollectionUtils.isEmpty(dto.getOldfileIds())) {
|
|
|
+ message.setFrom(new InternetAddress(fromAddress));
|
|
|
+ message.setSubject(dto.getSubject());
|
|
|
+
|
|
|
+ Multipart multipart = new MimeMultipart();
|
|
|
+// // 消息正文
|
|
|
+ BodyPart messageBodyPart1 = new MimeBodyPart();
|
|
|
+ List<MimeBodyPart> imageParts = new ArrayList<>();
|
|
|
+ String updatedHtmlContent = EmailHelper.convertImageUrlsToCidBodyPart(dto.getContent(),imageParts,mailFileProperties.getPath().getJpeg(),multipart);
|
|
|
+ messageBodyPart1.setContent(updatedHtmlContent, "text/html; charset=UTF-8");
|
|
|
+ multipart.addBodyPart(messageBodyPart1);
|
|
|
+ // 发送完整的消息部分
|
|
|
+ message.setContent(multipart);
|
|
|
+ // 获取邮件大小
|
|
|
+ sizeInBytes = dto.getContent().length();
|
|
|
+
|
|
|
+ } else {
|
|
|
+
|
|
|
+ message.setFrom(new InternetAddress(fromAddress));
|
|
|
+
|
|
|
+ message.setDescription(dto.getRemark());
|
|
|
+ // 设置邮件主题
|
|
|
+ message.setSubject(dto.getSubject());
|
|
|
+ // 创建消息部分
|
|
|
+ Multipart multipart = new MimeMultipart();
|
|
|
+// // 消息正文
|
|
|
+ BodyPart messageBodyPart1 = new MimeBodyPart();
|
|
|
+
|
|
|
+ List<MimeBodyPart> imageParts = new ArrayList<>();
|
|
|
+ String updatedHtmlContent = EmailHelper.convertImageUrlsToCidBodyPart(dto.getContent(),imageParts,mailFileProperties.getPath().getJpeg(),multipart);
|
|
|
+ messageBodyPart1.setContent(updatedHtmlContent, "text/html; charset=UTF-8");
|
|
|
+ multipart.addBodyPart(messageBodyPart1);
|
|
|
+ // 设置文本消息部分
|
|
|
+ if (!CollectionUtils.isEmpty(dto.getFileIds())) {
|
|
|
+ LambdaQueryWrapper fileWrapper = new LambdaQueryWrapper<MailTempAttachmentEntity>().in(MailTempAttachmentEntity::getId,dto.getFileIds());
|
|
|
+ List<MailTempAttachmentEntity> tempAttachment = tempAttachmentService.list(fileWrapper);
|
|
|
+ for (MailTempAttachmentEntity attachment : tempAttachment) {
|
|
|
+ BodyPart messageBodyPart = new MimeBodyPart();
|
|
|
+ String filePath = mailFileProperties.getPath().getPath() + attachment.getFilePath();
|
|
|
+ String fileName = attachment.getFileName()+"."+attachment.getFileExt();
|
|
|
+ DataSource fileSource = new FileDataSource(filePath);
|
|
|
+ messageBodyPart.setDataHandler(new DataHandler(fileSource));
|
|
|
+ messageBodyPart.setFileName(fileName);
|
|
|
+ multipart.addBodyPart(messageBodyPart);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!CollectionUtils.isEmpty(dto.getOldfileIds())) {
|
|
|
+ LambdaQueryWrapper fileMailWrapper = new LambdaQueryWrapper<MailTempAttachmentEntity>().in(MailTempAttachmentEntity::getId,dto.getOldfileIds());
|
|
|
+ List<MailAttachmentEntity> mailAttachments = mailAttachmentService.list(fileMailWrapper);
|
|
|
+ for (MailAttachmentEntity attachment : mailAttachments) {
|
|
|
+ BodyPart messageBodyPart = new MimeBodyPart();
|
|
|
+ String filePath = mailFileProperties.getPath().getPath() + attachment.getFilePath();
|
|
|
+ String fileName = attachment.getFileName()+"."+attachment.getFileExt();
|
|
|
+ DataSource fileSource = new FileDataSource(filePath);
|
|
|
+ messageBodyPart.setDataHandler(new DataHandler(fileSource));
|
|
|
+ messageBodyPart.setFileName(fileName);
|
|
|
+ multipart.addBodyPart(messageBodyPart);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 发送完整的消息部分
|
|
|
+ message.setContent(multipart);
|
|
|
+ // 获取邮件大小
|
|
|
+ sizeInBytes = dto.getContent().length();
|
|
|
+ // 发送消息
|
|
|
+ }
|
|
|
+ /**
|
|
|
+ * 发送成功,存储邮箱 replyEmailId null
|
|
|
+ */
|
|
|
+ if (Integer.valueOf(1).equals(dto.getIsReceipt())) {
|
|
|
+ message.addHeader("Disposition-Notification-To", smtpPop.getEmailAddress());
|
|
|
+ }
|
|
|
+ Long replyMsgId = dto.getReplyMsgId();
|
|
|
+ EmailsEntity email = saveSendEmails(dto,fromAddress,fromNickName,replyMsgId,Long.valueOf(sizeInBytes));
|
|
|
+ email.setIsOnlyHead(0);
|
|
|
+ email.setSmtpPopId(smtpPop.getId());
|
|
|
+ log.error("senderWithThreadLocal - saveOrUpdate----邮件");
|
|
|
+ if(this.saveOrUpdate(email)) {
|
|
|
+ if (Objects.nonNull(email.getDelaySendTime())) {
|
|
|
+ if (!CollectionUtils.isEmpty(dto.getFileIds())) {
|
|
|
+ LambdaUpdateWrapper<MailTempAttachmentEntity> mt = new LambdaUpdateWrapper<>();
|
|
|
+ mt.set(MailTempAttachmentEntity::getEmailId, email.getId());
|
|
|
+ mt.in(MailTempAttachmentEntity::getId, dto.getFileIds());
|
|
|
+ tempAttachmentService.update(mt);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ try {
|
|
|
+ CompletableFuture<SendStatus> resultFuture = senderWithThreadLocal.sendMailMessage(transport, message, email);
|
|
|
+ SendStatus result = resultFuture.get();
|
|
|
+ return result;
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("email -address --"+smtpPop.getEmailAddress()+"--send - error -",e);
|
|
|
+ return SendStatus.SERVER_LOGIN_FAIL;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }catch (Exception e) {
|
|
|
+ log.error("getSendEmailsSession -error",e);
|
|
|
+ return SendStatus.FAILED;
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("send sendMail -error",e);
|
|
|
+ return SendStatus.FAILED;
|
|
|
+ }
|
|
|
+ return SendStatus.SUCCESS;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public List<UserClickTitleVO> selectUserClickTitle(Long ownerBy, String title) {
|
|
|
+ return this.baseMapper.selectUserClickTitle(ownerBy,title);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public Boolean sendEmail(EmailsEntity emails,SmtpPopSettingsEntity smtpPop) {
|
|
|
+// String active = environment.getProperty("spring.profiles.active");
|
|
|
+// if("dev".equals(active)) {
|
|
|
+// return true;
|
|
|
+// }
|
|
|
+ try {
|
|
|
+
|
|
|
+ List<String> recipientls = new ArrayList<>();
|
|
|
+ if(StrUtil.isNotBlank(emails.getRecipient())) {
|
|
|
+ recipientls = Arrays.asList(emails.getRecipient().split(","));
|
|
|
+ }
|
|
|
+
|
|
|
+ List<String> recipientCcls = new ArrayList<>();
|
|
|
+ if(StrUtil.isNotBlank(emails.getRecipientCc())) {
|
|
|
+ recipientCcls = Arrays.asList(emails.getRecipientCc().split(","));
|
|
|
+ }
|
|
|
+ List<String> recipientBccls = new ArrayList<>();
|
|
|
+ if(StrUtil.isNotBlank(emails.getRecipientBcc())) {
|
|
|
+ recipientBccls = Arrays.asList(emails.getRecipientBcc().split(","));
|
|
|
+ }
|
|
|
+
|
|
|
+ String fromAddress = smtpPop.getEmailAddress();
|
|
|
+
|
|
|
+ Session session = getSendEmailsSession(smtpPop);
|
|
|
+ InternetAddress [] froms = new InternetAddress[recipientls.size()];
|
|
|
+ for (int i = 0; i < recipientls.size(); i++) {
|
|
|
+ froms[i] = new InternetAddress(recipientls.get(i));
|
|
|
+ }
|
|
|
+ InternetAddress [] fromsCC = new InternetAddress[recipientCcls.size()];
|
|
|
+ for (int i = 0; i < recipientCcls.size(); i++) {
|
|
|
+ fromsCC[i] = new InternetAddress(recipientCcls.get(i));
|
|
|
+ }
|
|
|
+ InternetAddress [] fromsBCC = new InternetAddress[recipientBccls.size()];
|
|
|
+ for (int i = 0; i < recipientBccls.size(); i++) {
|
|
|
+ fromsBCC[i] = new InternetAddress(recipientBccls.get(i));
|
|
|
+ }
|
|
|
+ Transport transport = session.getTransport("smtp");
|
|
|
+ int sizeInBytes = 0;
|
|
|
+ try {
|
|
|
+ Message message = new MimeMessage(session);
|
|
|
+ if (Objects.nonNull(froms) && froms.length > 0) {
|
|
|
+ message.setRecipients(Message.RecipientType.TO,froms);
|
|
|
+ }
|
|
|
+ if (Objects.nonNull(fromsCC) && fromsCC.length > 0) {
|
|
|
+ message.setRecipients(Message.RecipientType.CC,fromsCC);
|
|
|
+ }
|
|
|
+ if (Objects.nonNull(fromsBCC) && fromsBCC.length > 0) {
|
|
|
+ message.setRecipients(Message.RecipientType.BCC,fromsBCC);
|
|
|
+ }
|
|
|
+
|
|
|
+ LambdaQueryWrapper fileWrapper = new LambdaQueryWrapper<MailTempAttachmentEntity>().in(MailTempAttachmentEntity::getEmailId,emails.getId());
|
|
|
+ List<MailTempAttachmentEntity> tempAttachment = tempAttachmentService.list(fileWrapper);
|
|
|
+ if (CollectionUtils.isEmpty(tempAttachment)) {
|
|
|
+ message.setFrom(new InternetAddress(fromAddress));
|
|
|
+ message.setSubject(emails.getSubject());
|
|
|
+
|
|
|
+ Multipart multipart = new MimeMultipart();
|
|
|
+// // 消息正文
|
|
|
+ BodyPart messageBodyPart1 = new MimeBodyPart();
|
|
|
+ List<MimeBodyPart> imageParts = new ArrayList<>();
|
|
|
+ String updatedHtmlContent = EmailHelper.convertImageUrlsToCidBodyPart(emails.getContent(),imageParts,mailFileProperties.getPath().getJpeg(),multipart);
|
|
|
+ messageBodyPart1.setContent(updatedHtmlContent, "text/html; charset=UTF-8");
|
|
|
+ multipart.addBodyPart(messageBodyPart1);
|
|
|
+ // 发送完整的消息部分
|
|
|
+ message.setContent(multipart);
|
|
|
+ } else {
|
|
|
+ message.setFrom(new InternetAddress(fromAddress));
|
|
|
+ message.setDescription(emails.getRemark());
|
|
|
+ // 设置邮件主题
|
|
|
+ message.setSubject(emails.getSubject());
|
|
|
+ Multipart multipart = new MimeMultipart();
|
|
|
+// // 消息正文
|
|
|
+ BodyPart messageBodyPart1 = new MimeBodyPart();
|
|
|
+ List<MimeBodyPart> imageParts = new ArrayList<>();
|
|
|
+ String updatedHtmlContent = EmailHelper.convertImageUrlsToCidBodyPart(emails.getContent(),imageParts,mailFileProperties.getPath().getJpeg(),multipart);
|
|
|
+ messageBodyPart1.setContent(updatedHtmlContent, "text/html; charset=UTF-8");
|
|
|
+ multipart.addBodyPart(messageBodyPart1);
|
|
|
+ // 设置文本消息部分
|
|
|
+ for (MailTempAttachmentEntity attachment : tempAttachment) {
|
|
|
+ BodyPart messageBodyPart = new MimeBodyPart();
|
|
|
+ String filePath = mailFileProperties.getPath().getPath() + attachment.getFilePath();
|
|
|
+ String fileName = attachment.getFileName()+"."+attachment.getFileExt();
|
|
|
+ DataSource fileSource = new FileDataSource(filePath);
|
|
|
+ messageBodyPart.setDataHandler(new DataHandler(fileSource));
|
|
|
+ messageBodyPart.setFileName(fileName);
|
|
|
+ multipart.addBodyPart(messageBodyPart);
|
|
|
+ }
|
|
|
+ // 发送完整的消息部分
|
|
|
+ message.setContent(multipart);
|
|
|
+ }
|
|
|
+ /**
|
|
|
+ * 发送成功,存储邮箱 replyEmailId null
|
|
|
+ */
|
|
|
+ if (Integer.valueOf(1).equals(emails .getIsReceipt())) {
|
|
|
+ message.addHeader("Disposition-Notification-To", smtpPop.getEmailAddress());
|
|
|
+ }
|
|
|
+ if(this.saveOrUpdate(emails)) {
|
|
|
+ senderWithThreadLocal.sendMailMessage(transport,message,emails);
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+ }catch (Exception e) {
|
|
|
+ log.error("getSendEmailsSession -error",e);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ log.error("send sendMail -error",e);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ @Override
|
|
|
+ public void receiveEmails(SmtpPopSettingsEntity smtpPop,Boolean isBackTask) {
|
|
|
+ String active = environment.getProperty("spring.profiles.active");
|
|
|
+// if("dev".equals(active)) {
|
|
|
+// return;
|
|
|
+// }
|
|
|
+ String taskId = smtpPop.getEmailAddress()+"_"+smtpPop.getOwnerBy().toString();
|
|
|
+ ReceiveMailQueueThreadPool instance = ReceiveMailQueueThreadPool.getInstance();
|
|
|
+ if (instance.getTaskInProgressByMail(taskId)) {
|
|
|
+ log.error("有任务正在进行--:>>>>>>>>>>>>>"+smtpPop.getEmailAddress());
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ instance.addTask(taskId,new Runnable() {
|
|
|
+ @Override
|
|
|
+ public void run() {
|
|
|
+ receiveHeadEmails(smtpPop,isBackTask);
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ addLoadMailContentTask(smtpPop);
|
|
|
+
|
|
|
+ addLoadMailFilesTask(smtpPop);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void receiveHeadEmails(SmtpPopSettingsEntity smtpPop) {
|
|
|
+ receiveHeadEmails(smtpPop,false);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void receiveEmails(SmtpPopSettingsEntity smtpPop) {
|
|
|
+ receiveEmails(smtpPop,false);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void receiveHeadEmails(SmtpPopSettingsEntity smtpPop,Boolean isBackTask) {
|
|
|
+
|
|
|
+ try {
|
|
|
+ List<Message> inboxLs = getMessagels(smtpPop,"INBOX",EmailBoxEnum.INBOX,isBackTask);
|
|
|
+ if (!CollectionUtils.isEmpty(inboxLs)) {
|
|
|
+ List<EmailFolderRuleEntity> folderRules = folderRuleService.getUserFolderRules(smtpPop.getOwnerBy());
|
|
|
+ Set<String> blackList = blackListService.getBlackEmaillist(smtpPop.getOwnerBy());
|
|
|
+ pullHeadMail(inboxLs,smtpPop,EmailBoxEnum.INBOX,blackList,folderRules,isBackTask);
|
|
|
+ }
|
|
|
+// if (!smtpPop.getEnabled()) {
|
|
|
+// return;
|
|
|
+// }
|
|
|
+ List<Message> sentLs = getMessagels(smtpPop,"Sent Items", EmailBoxEnum.SENT,isBackTask);
|
|
|
+ if (!CollectionUtils.isEmpty(sentLs)) {
|
|
|
+ pullHeadMail(sentLs,smtpPop,EmailBoxEnum.SENT,null,null,isBackTask);
|
|
|
+ }
|
|
|
+ }catch (Exception e) {
|
|
|
+ log.error("receiveHeadEmails - error ---"+smtpPop.getEmailAddress(),e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public List<Message> getMessagels(SmtpPopSettingsEntity smtpPop,String folderName, EmailBoxEnum boxEnum) {
|
|
|
+ return getMessagels(smtpPop,folderName,boxEnum,false);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public List<Message> getMessagels(SmtpPopSettingsEntity smtpPop,String folderName, EmailBoxEnum boxEnum,Boolean isBackTask) {
|
|
|
+ try {
|
|
|
+ QueryWrapper queryWrapper = new QueryWrapper<>();
|
|
|
+ queryWrapper.eq("smtp_pop_id", smtpPop.getId());
|
|
|
+ queryWrapper.eq("folder", boxEnum.code);
|
|
|
+ queryWrapper.select("max(recipient_date) as recipient_date");
|
|
|
+ EmailsEntity email = this.getOne(queryWrapper);
|
|
|
+
|
|
|
+ Date beginDate = null;
|
|
|
+ MailProperties properties = new MailProperties(smtpPop);
|
|
|
+ MailConnection mailConnection = MailConnectionUtil.receiveEmailsConnection(properties);
|
|
|
+ if (Objects.isNull(mailConnection)) {
|
|
|
+// if(isBackTask) {
|
|
|
+// // 处理异常,并发送通知
|
|
|
+// if (Objects.nonNull(smtpPop.getId())) {
|
|
|
+// LambdaUpdateWrapper<SmtpPopSettingsEntity> updateWrapper = new LambdaUpdateWrapper<>();
|
|
|
+// updateWrapper.set(SmtpPopSettingsEntity::getEnabled,0);
|
|
|
+// updateWrapper.eq(SmtpPopSettingsEntity::getId, smtpPop.getId())
|
|
|
+// .setSql("connect_error_count = connect_error_count + 1"); // 原值 + 1
|
|
|
+// popSettingsService.update(updateWrapper);
|
|
|
+// // 禁止后续流程
|
|
|
+//// smtpPop.setEnabled(false);
|
|
|
+// }
|
|
|
+//// // 发送消息通知提醒邮箱连接异常
|
|
|
+//// String[] argsArr = {"wecom"};
|
|
|
+//// Set<Long> userIds = new HashSet<>();
|
|
|
+//// userIds.add(smtpPop.getOwnerBy());
|
|
|
+////
|
|
|
+//// Map<String,Object> messageMap = new HashMap<>();
|
|
|
+//// messageMap.put("messageContent","");
|
|
|
+//// messageMap.put("titleRemark","["+smtpPop.getEmailAddress()+"]");
|
|
|
+//// invokeSendMessage(messageMap,userIds,argsArr);
|
|
|
+// }
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ Folder inbox = mailConnection.getFolder(folderName);
|
|
|
+ if (Objects.isNull(inbox)) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ inbox.open(Folder.READ_ONLY);
|
|
|
+ if (Objects.nonNull(email)) {
|
|
|
+ beginDate = email.getRecipientDate();
|
|
|
+ }
|
|
|
+ if (beginDate == null) {
|
|
|
+ if (Integer.valueOf(0).equals(smtpPop.getPullDay()) || Objects.isNull(smtpPop.getPullDay())) {
|
|
|
+ LocalDate currentDate = LocalDate.now();
|
|
|
+ LocalDate datePullDayAgo = currentDate.minusYears(5);
|
|
|
+ beginDate = DateUtil.getDateByFormat(datePullDayAgo.toString(), "yyyy-MM-dd");
|
|
|
+ } else {
|
|
|
+ LocalDate currentDate = LocalDate.now();
|
|
|
+ LocalDate datePullDayAgo = currentDate.minusDays(smtpPop.getPullDay());
|
|
|
+ beginDate = DateUtil.getDateByFormat(datePullDayAgo.toString(), "yyyy-MM-dd");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ SearchTerm searchTerm = new ReceivedDateTerm(ComparisonTerm.GT, beginDate);
|
|
|
+ Message[] messages = inbox.search(searchTerm);
|
|
|
+
|
|
|
+ List<Message> messagesList = Arrays.asList(messages);
|
|
|
+ if (CollectionUtils.isEmpty(messagesList)) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+// Date finalBeginDate = beginDate;
|
|
|
+// List<Message> messagels = messagesList.stream().filter(e -> {
|
|
|
+// try {
|
|
|
+// return e.getReceivedDate().compareTo(finalBeginDate) > 0;
|
|
|
+// } catch (MessagingException ex) {
|
|
|
+// return false;
|
|
|
+// }
|
|
|
+// }).collect(Collectors.toList());
|
|
|
+//
|
|
|
+// if (Objects.isNull(messagels)) {
|
|
|
+// return messagels;
|
|
|
+// } else if (messagels.size() <= 100) {
|
|
|
+// return messagels;
|
|
|
+// } else if(messagels.size() > 100 && messagels.size() <= 1000) {
|
|
|
+// return messagels.stream().limit(500).collect(Collectors.toList());
|
|
|
+// } else {
|
|
|
+// return messagels.stream().limit(1000).collect(Collectors.toList());
|
|
|
+// }
|
|
|
+ return messagesList;
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("error", e);
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public void invokeSendMessage(Map messageMap,Set<Long> toUserIds,String[] argsArr ) {
|
|
|
+ try {
|
|
|
+ Object myClassInstance = SpringContextUtils.getBean("messageService");
|
|
|
+ Class<?> clazz = myClassInstance.getClass();
|
|
|
+
|
|
|
+// Class<?> clazz = Class.forName("com.storlead.message.service.impl.MessageService");
|
|
|
+
|
|
|
+ Method method = clazz.getMethod("autoMatchEventSendMessage",Map.class,String.class,String.class,Set.class, String[].class);
|
|
|
+ method.invoke(myClassInstance, messageMap,"999","EMAIL_SMTP_WARN",toUserIds,argsArr);
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("invokeSendMessage - error",e);
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ @Override
|
|
|
+ public void pullHeadMail(List<Message> messages,SmtpPopSettingsEntity smtpPop, EmailBoxEnum boxEnum,Set<String> blackls,List<EmailFolderRuleEntity> folderRules,Boolean isBackTask) {
|
|
|
+// Lock lock = userLockMap.computeIfAbsent(smtpPop.getOwnerBy(), id -> new ReentrantLock());
|
|
|
+ log.info("==========邮件入库开始=========="+boxEnum.code);
|
|
|
+
|
|
|
+// if (lock.tryLock()) {
|
|
|
+ try {
|
|
|
+ List<Message> messagels = messages;
|
|
|
+ if (CollectionUtils.isEmpty(messagels)) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ QueryWrapper queryMsgIdWp = new QueryWrapper<>();
|
|
|
+ queryMsgIdWp.select("message_id");
|
|
|
+ queryMsgIdWp.eq("folder", boxEnum.code);
|
|
|
+ queryMsgIdWp.eq("smtp_pop_id", smtpPop.getId());
|
|
|
+ queryMsgIdWp.last("order by recipient_date desc limit 100");
|
|
|
+ List<String> ids = this.listObjs(queryMsgIdWp);
|
|
|
+ List<String> mesageIds = new ArrayList<>();
|
|
|
+ if (!CollectionUtils.isEmpty(ids)) {
|
|
|
+ mesageIds.addAll(ids);
|
|
|
+ }
|
|
|
+ List<String> messageIds = new ArrayList<>();
|
|
|
+// if (!CollectionUtils.isEmpty(messagels)) {
|
|
|
+// List<String> varIdls = new ArrayList<>();
|
|
|
+// for (Message message : messagels) {
|
|
|
+// String [] varIds = message.getHeader("Message-ID");
|
|
|
+// if (Objects.isNull(varIds)) {
|
|
|
+// continue;
|
|
|
+// }
|
|
|
+// varIdls.add(varIds[0]);
|
|
|
+// }
|
|
|
+// if (!CollectionUtils.isEmpty(varIdls)) {
|
|
|
+// messageIds = this.getEmailMessageIdsByMessageId(varIdls,boxEnum.code, smtpPop.getId());
|
|
|
+// if (Objects.isNull(messageIds)) {
|
|
|
+// messageIds = new ArrayList<>();
|
|
|
+// }
|
|
|
+// }
|
|
|
+// }
|
|
|
+ List<EmailsEntity> entities = new ArrayList<>();
|
|
|
+ for (Message message : messagels) {
|
|
|
+ String[] varIds = message.getHeader("Message-ID");
|
|
|
+ if (Objects.isNull(varIds)) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ String messageId = varIds[0];
|
|
|
+ // 如果 messageId 尚未处理,执行处理逻辑
|
|
|
+ if (!CollectionUtils.isEmpty(mesageIds) && mesageIds.contains(messageId)) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ String oldMessageId = this.getEmailMessageIdsByMessageId(messageId,boxEnum.code, smtpPop.getId());
|
|
|
+// String[] inReplyTo = message.getHeader("In-Reply-To");
|
|
|
+// if (inReplyTo != null) {
|
|
|
+// String inReplyTo1 = message.getHeader("IN-REPLY-TO") != null ? message.getHeader("In-Reply-To")[0] : null;
|
|
|
+// String references1 = message.getHeader("References") != null ? message.getHeader("References")[0] : null;
|
|
|
+// }
|
|
|
+// Boolean existMessageId = messageIds.contains(messageId);
|
|
|
+ EmailsEntity entity;
|
|
|
+ if (Objects.isNull(oldMessageId)) {
|
|
|
+ entity = convertMessageToEmailVo(message, true);
|
|
|
+ if (Objects.isNull(entity)) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ entity.setMessageId(messageId);
|
|
|
+ entity.setSmtpPopId(smtpPop.getId());
|
|
|
+ entity.setOwnerBy(smtpPop.getOwnerBy());
|
|
|
+ } else {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ if (Objects.isNull(entity)) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ if (!CollectionUtils.isEmpty(folderRules)) {
|
|
|
+ /** 处理文件夹入栈规则 **/
|
|
|
+ folderRuleService.carveUpMailCustomFolder(entity, folderRules);
|
|
|
+ }
|
|
|
+ mesageIds.add(messageId);
|
|
|
+ if ("IMAP".equals(smtpPop.getProtocolType())) {
|
|
|
+ IMAPFolder folder = (IMAPFolder) message.getFolder();
|
|
|
+ Long msguid = folder.getUID(message);
|
|
|
+ entity.setMsgUid(msguid.toString());
|
|
|
+ } else if ("POP3".equals(smtpPop.getProtocolType())) {
|
|
|
+ POP3Folder folder = (POP3Folder) message.getFolder();
|
|
|
+ String msguid = folder.getUID(message);
|
|
|
+ entity.setMsgUid(msguid.toString());
|
|
|
+ }
|
|
|
+ if (!CollectionUtils.isEmpty(blackls)) {
|
|
|
+ if (blackls.contains(entity.getFrom())) {
|
|
|
+ entity.setIsTrash(1);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ Boolean b = saveOrUpdate(entity);
|
|
|
+ if (b) {
|
|
|
+ entities.add(entity);
|
|
|
+ log.error("==========entity.getId()=========="+entity.getId());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ log.info("==========邮件入库结束=========="+boxEnum.code);
|
|
|
+ String finalboxCode = boxEnum.code; // 提前取值
|
|
|
+ Boolean finalIsBackTask = isBackTask;
|
|
|
+ List<Long> finalIsMailIds = entities.stream().map(EmailsEntity::getId).collect(Collectors.toList());
|
|
|
+ log.error("finalIsMailIds = "+finalIsMailIds);
|
|
|
+ if (!CollectionUtils.isEmpty(finalIsMailIds)) {
|
|
|
+ CompletableFuture.runAsync(() -> {
|
|
|
+ updateFollowUpTime(entities, smtpPop.getOwnerBy());
|
|
|
+ // 发送新邮件提醒,绑定客户后,直接查询性能会好
|
|
|
+ log.error("操作完绑定客户"+ JSON.toJSON(finalIsMailIds)+"__"+isBackTask+"___EmailBoxEnum.code___"+finalboxCode+"____="+EmailBoxEnum.INBOX.code.equals(finalboxCode));
|
|
|
+ if (!CollectionUtils.isEmpty(finalIsMailIds) && finalIsBackTask && EmailBoxEnum.INBOX.code.equals(finalboxCode)) {
|
|
|
+ log.error("进入发送提醒");
|
|
|
+ sendNewMailRemind(finalIsMailIds,smtpPop.getOwnerBy(),smtpPop.getEmailAddress());
|
|
|
+ }
|
|
|
+ });
|
|
|
+ CompletableFuture.runAsync(() -> {
|
|
|
+ autoReplyMails(entities);
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ }catch(Exception e){
|
|
|
+ log.error("pullHeadMail -- error---"+smtpPop.getEmailAddress(), e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public void sendNewMailRemind(List<Long> mailIds,Long userId,String mailAccount) {
|
|
|
+ if (CollectionUtils.isEmpty(mailIds)) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ String messageContent = "您有"+mailIds.size()+"封新邮件,请前往查看!";
|
|
|
+ // 获取新绑定的邮箱
|
|
|
+ List<Long> cusIds = this.baseMapper.selectCusIdByMailId(mailIds);
|
|
|
+ if (!CollectionUtils.isEmpty(cusIds)) {
|
|
|
+ List<CustomerMailVO> customervos = this.baseMapper.selectCusInfoByCusId(cusIds);
|
|
|
+
|
|
|
+ if (!CollectionUtils.isEmpty(customervos)) {
|
|
|
+ StringBuilder sb = new StringBuilder();
|
|
|
+ String moreCus = "";
|
|
|
+ for (CustomerMailVO customer : customervos) {
|
|
|
+ if (sb.length() > 0) {
|
|
|
+ moreCus = "等";
|
|
|
+ sb.append("、");
|
|
|
+ }
|
|
|
+ sb.append("【");
|
|
|
+ sb.append(customer.getCountry());
|
|
|
+ sb.append("-");
|
|
|
+ sb.append(customer.getCustomerName());
|
|
|
+ sb.append("】");
|
|
|
+ }
|
|
|
+ messageContent = "您有来自"+sb+moreCus+"客户的"+mailIds.size()+"封新邮件,请前往查看!";
|
|
|
+ }
|
|
|
+ }
|
|
|
+ try {
|
|
|
+ Map<String,Object> messageMap = new HashMap<>();
|
|
|
+ messageMap.put("messageContent",messageContent);
|
|
|
+
|
|
|
+ Integer mailCount = this.baseMapper.countSmtpMailCount(userId);
|
|
|
+ if (mailCount > 1) {
|
|
|
+ messageMap.put("titleRemark","["+mailAccount+"]");
|
|
|
+ } else {
|
|
|
+ messageMap.put("titleRemark","");
|
|
|
+ }
|
|
|
+ Set<Long> toUserIds = new HashSet<>();
|
|
|
+ toUserIds.add(userId);
|
|
|
+
|
|
|
+ Object myClassInstance = SpringContextUtils.getBean("messageService");
|
|
|
+ Class<?> clazz = myClassInstance.getClass();
|
|
|
+
|
|
|
+// Class<?> clazz = Class.forName("com.storlead.message.service.impl.MessageService");
|
|
|
+
|
|
|
+ Method method = clazz.getMethod("autoMatchEventSendMessage",Map.class,String.class,String.class,Set.class, String[].class);
|
|
|
+ String[] argsArr = {"site","wecom","sms","mail"};
|
|
|
+ method.invoke(myClassInstance, messageMap,"11","NEW_EMAIL",toUserIds,argsArr);
|
|
|
+ }catch (Exception e) {
|
|
|
+ log.error("autoMatchEventSendMessage error",e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public void autoReplyMails(List<EmailsEntity> entities){
|
|
|
+ for (EmailsEntity entity : entities) {
|
|
|
+ try {
|
|
|
+ autoReplyMail(entity);
|
|
|
+ }catch (Exception e) {
|
|
|
+ log.error("---autoReplyMails error---",e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public void updateFollowUpTime(List<EmailsEntity> entities,Long ownerBy){
|
|
|
+ for (EmailsEntity entity : entities) {
|
|
|
+ try {
|
|
|
+ // 修改客户跟进实际
|
|
|
+ if (Integer.valueOf(1).equals(entity.getInOutMark())) {
|
|
|
+ bindLiaisonMailCustomerIdByMailIdAndUserId(entity.getId(), entity.getFrom(), ownerBy, 1);
|
|
|
+ } else {
|
|
|
+ String recipient = entity.getRecipient();
|
|
|
+ if (StrUtil.isNotBlank(entity.getRecipientCc())) {
|
|
|
+ if (StrUtil.isNotBlank(recipient)) {
|
|
|
+ recipient = recipient + "," + entity.getRecipientCc();
|
|
|
+ } else {
|
|
|
+ recipient = entity.getRecipientCc();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ bindLiaisonMailCustomerIdByMailIdAndUserId(entity.getId(), recipient, ownerBy, 2);
|
|
|
+ }
|
|
|
+
|
|
|
+ if ("SENT".equals(entity.getFolder())) {
|
|
|
+ Object myClassInstance = SpringContextUtils.getBean("customerServiceImpl");
|
|
|
+ Class<?> clazz = myClassInstance.getClass();
|
|
|
+ Set<String> mailAddress = new HashSet<>();
|
|
|
+ if (StrUtil.isNotBlank(entity.getRecipient())) {
|
|
|
+ List<String> recipientls = Arrays.asList(entity.getRecipient().toLowerCase().split(","));
|
|
|
+ mailAddress.addAll(recipientls);
|
|
|
+ }
|
|
|
+ if (StrUtil.isNotBlank(entity.getRecipientCc())) {
|
|
|
+ List<String> recipientccls = Arrays.asList(entity.getRecipientCc().toLowerCase().split(","));
|
|
|
+ mailAddress.addAll(recipientccls);
|
|
|
+ }
|
|
|
+ if (!CollectionUtils.isEmpty(mailAddress)) {
|
|
|
+ LocalDateTime sentDate = (Objects.isNull(entity.getSentDate())) ? LocalDateTime.now() : entity.getSentDate().toInstant()
|
|
|
+ .atZone(ZoneId.systemDefault()) // 使用系统默认时区
|
|
|
+ .toLocalDateTime();
|
|
|
+ Method method = clazz.getMethod("updateFollowUpTimeByEmail", Set.class, LocalDateTime.class);
|
|
|
+ method.invoke(myClassInstance, mailAddress, sentDate);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("updateFollowUpTimeByEmail --e", e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public void autoReplyMail(EmailsEntity entity) {
|
|
|
+ try {
|
|
|
+ SmtpPopSettingsEntity smtpPop = popSettingsService.getById(entity.getSmtpPopId());
|
|
|
+ if (Integer.valueOf(1).equals(smtpPop.getIsAutoReply()) && smtpPop.getReplyOnTime().before(entity.getSentDate())) {
|
|
|
+ if (entity.getFrom().equals(smtpPop.getEmailAddress())
|
|
|
+ || "system@storlead.com".equals(entity.getFrom())
|
|
|
+ || "system@storlead.com".equals(entity.getRecipient())) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ // 发过了不用发
|
|
|
+ String key = smtpPop.getEmailAddress()+"_"+entity.getFrom();
|
|
|
+ Object object =redisService.getCacheObject(key);
|
|
|
+ Long ttl = 0l;
|
|
|
+ if (Objects.nonNull(object)) {
|
|
|
+ ttl = redisService.getCacheExpire(key, TimeUnit.SECONDS);
|
|
|
+ }
|
|
|
+ if ((Objects.isNull(object) || ttl <= 0) && StrUtil.isNotBlank(smtpPop.getReplyContent())) {
|
|
|
+ LocalDateTime now = LocalDateTime.now();
|
|
|
+ // 今天23:59:59
|
|
|
+ LocalDateTime endOfDay = now.toLocalDate().atTime(23, 59, 59);
|
|
|
+ // 计算剩余时间(秒)
|
|
|
+ long timeout = ChronoUnit.SECONDS.between(now, endOfDay);
|
|
|
+ redisService.setCacheObject(key,"reply",timeout, TimeUnit.SECONDS);
|
|
|
+
|
|
|
+ AccessKeyEncryptor accessKeyEncryptor = AccessKeyEncryptor.getAccessKeyEncryptor("");
|
|
|
+ String pass = accessKeyEncryptor.decrypt(smtpPop.getEmailPassword());
|
|
|
+ smtpPop.setEmailPassword(pass);
|
|
|
+ EmailsEntity repEmail = new EmailsEntity();
|
|
|
+ repEmail.setRecipient(entity.getFrom());
|
|
|
+ repEmail.setSubject(smtpPop.getReplyTitle());
|
|
|
+ repEmail.setContent(smtpPop.getReplyContent());
|
|
|
+ this.sendEmail(repEmail,smtpPop);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }catch (Exception e) {
|
|
|
+ log.error("autoReplyMail errpr ",e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ @Override
|
|
|
+ public NewMailCountTipVO countMailSummaryNum(Long smtpPopId, Long ownerBy) {
|
|
|
+ return this.baseMapper.countMailSummaryNum(smtpPopId,ownerBy);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public NewMailCountTipVO countCustomerAndClueNumber(Long smtpPopId, Long ownerBy) {
|
|
|
+ return this.baseMapper.countCustomerAndClueNumber(smtpPopId,ownerBy);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public NewMailCountTipVO countCustomerFollowUpMailNum(Long smtpPopId, Long ownerBy) {
|
|
|
+ return this.baseMapper.countCustomerFollowUpMailNum(smtpPopId,ownerBy);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public LocalDateTime getCustomerLastFollowUpTime(Long customerId) {
|
|
|
+ return this.baseMapper.selectCustomerLastFollowUpTime(customerId);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public List<EmailsEntity> getDelayDeleteMail() {
|
|
|
+ return this.baseMapper.selectDelayDeleteMail();
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public IPage<CustomerEmailVo> selectCustomerEmailPage(Page<CustomerEmailVo> page, MailListDTO dto) {
|
|
|
+ return this.baseMapper.selectCustomerEmailPage(page,dto);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void receiveBodyContentEmails(SmtpPopSettingsEntity smtpPop,List<EmailsEntity> emailsls,EmailBoxEnum boxEnum) {
|
|
|
+ receiveBodyContent(smtpPop,emailsls,boxEnum);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public InputStream loadEmailsFile(SmtpPopSettingsEntity smtpPop, EmailsEntity email,String attachmentName) {
|
|
|
+ try {
|
|
|
+ MailProperties properties = new MailProperties(smtpPop);
|
|
|
+ MailConnection mailConnection = MailConnectionUtil.receiveEmailsConnection(properties);
|
|
|
+ if (Objects.isNull(mailConnection)) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ String folder = "Sent Items";
|
|
|
+ if (EmailBoxEnum.INBOX.code.equals(email.getFolder())) {
|
|
|
+ folder = "INBOX";
|
|
|
+ }
|
|
|
+ Message message = mailConnection.getMessageByUid(email.getMsgUid(),folder);
|
|
|
+ if (Objects.isNull(message)) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ Object content = message.getContent();
|
|
|
+ if (content instanceof Multipart) {
|
|
|
+ Multipart multipart = (Multipart) content;
|
|
|
+ for (int i = 0; i < multipart.getCount(); i++) {
|
|
|
+ BodyPart bodyPart = multipart.getBodyPart(i);
|
|
|
+ if (Part.ATTACHMENT.equalsIgnoreCase(bodyPart.getDisposition()) || bodyPart.isMimeType("application/octet-stream")) {
|
|
|
+ String fileName = bodyPart.getFileName();
|
|
|
+ fileName = MimeUtility.decodeText(fileName);
|
|
|
+ fileName = fileName.replace("\n", "").replace("\r", "");
|
|
|
+ if (fileName.equals(attachmentName)) {
|
|
|
+ return bodyPart.getInputStream();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }catch (Exception e) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void loadEmailsFiles(SmtpPopSettingsEntity smtpPop, List<EmailsEntity> emails,List<MailAttachmentEntity> attachments) {
|
|
|
+ try {
|
|
|
+ MailProperties properties = new MailProperties(smtpPop);
|
|
|
+ MailConnection mailConnection = MailConnectionUtil.receiveEmailsConnection(properties);
|
|
|
+ if (Objects.isNull(mailConnection)) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ Map<Long,List<MailAttachmentEntity>> attachmentMap = attachments.stream().collect(Collectors.groupingBy(MailAttachmentEntity::getEmailId));
|
|
|
+ for(EmailsEntity email : emails) {
|
|
|
+ List<MailAttachmentEntity> mAttachments = attachmentMap.get(email.getId());
|
|
|
+ if (CollectionUtils.isEmpty(mAttachments)) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ String folder = "Sent Items";
|
|
|
+ if (EmailBoxEnum.INBOX.code.equals(email.getFolder())) {
|
|
|
+ folder = "INBOX";
|
|
|
+ }
|
|
|
+ mailConnection.getFolder(folder);
|
|
|
+ Map<String, MailAttachmentEntity> attachmentMapName = mAttachments.stream()
|
|
|
+ .collect(Collectors.toMap(
|
|
|
+ attachment -> attachment.getFileName() + "." + attachment.getFileExt(), // 键:拼接 fileName 和 fileExt
|
|
|
+ attachment -> attachment,
|
|
|
+ (existing, replacement) -> existing
|
|
|
+ ));
|
|
|
+ Message message = mailConnection.getMessageByUid(email.getMsgUid(),folder);
|
|
|
+ if (Objects.isNull(message)) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ Object content = message.getContent();
|
|
|
+ if (content instanceof Multipart) {
|
|
|
+ Multipart multipart = (Multipart) content;
|
|
|
+ for (int i = 0; i < multipart.getCount(); i++) {
|
|
|
+ BodyPart bodyPart = multipart.getBodyPart(i);
|
|
|
+ if (Part.ATTACHMENT.equalsIgnoreCase(bodyPart.getDisposition()) || bodyPart.isMimeType("application/octet-stream")) {
|
|
|
+ String fileName = bodyPart.getFileName();
|
|
|
+ fileName = MimeUtility.decodeText(fileName);
|
|
|
+ fileName = fileName.replace("\n", "").replace("\r", "");
|
|
|
+ MailAttachmentEntity attachment = attachmentMapName.get(fileName);
|
|
|
+ if (Objects.isNull(attachment)) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ String filePath = mailFileProperties.getPath().getPath()+attachment.getFilePath();
|
|
|
+ if (new File(filePath).exists()) {
|
|
|
+ LambdaUpdateWrapper<MailAttachmentEntity> attachmentUpdate = new LambdaUpdateWrapper<>();
|
|
|
+ attachmentUpdate.set(MailAttachmentEntity::getDownload,Integer.valueOf(1));
|
|
|
+ attachmentUpdate.eq(MailAttachmentEntity::getId,attachment.getId());
|
|
|
+ mailAttachmentService.update(attachmentUpdate);
|
|
|
+ }
|
|
|
+ try {
|
|
|
+ File file = new File(filePath);
|
|
|
+ File parentDir = file.getParentFile();
|
|
|
+ // 如果父目录不存在,则递归创建
|
|
|
+ if (parentDir != null && !parentDir.exists()) {
|
|
|
+ parentDir.mkdirs(); // mkdirs() 会创建所有必要的父目录
|
|
|
+ }
|
|
|
+ try (FileOutputStream output = new FileOutputStream(file)) {
|
|
|
+ bodyPart.getInputStream().transferTo(output);
|
|
|
+ }
|
|
|
+ LambdaUpdateWrapper<MailAttachmentEntity> attachmentUpdate = new LambdaUpdateWrapper<>();
|
|
|
+ attachmentUpdate.set(MailAttachmentEntity::getDownload,Integer.valueOf(1));
|
|
|
+ attachmentUpdate.set(MailAttachmentEntity::getFileSize,file.length());
|
|
|
+ attachmentUpdate.eq(MailAttachmentEntity::getId,attachment.getId());
|
|
|
+ mailAttachmentService.update(attachmentUpdate);
|
|
|
+ }catch (Exception e) {
|
|
|
+ log.error("error --- ",e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }catch (Exception e) {
|
|
|
+ log.error("loadEmailsFiles ---",e);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ public static Message[] mergeMessageArrays(Message[] array1, Message[] array2) {
|
|
|
+ // 处理空数组的情况
|
|
|
+ if (array1 == null && array2 == null) {
|
|
|
+ return new Message[0]; // 两个数组都为空,返回空数组
|
|
|
+ } else if (array1 == null) {
|
|
|
+ return array2; // 如果第一个数组为空,返回第二个数组
|
|
|
+ } else if (array2 == null) {
|
|
|
+ return array1; // 如果第二个数组为空,返回第一个数组
|
|
|
+ }
|
|
|
+ // 如果两个数组都不为空,创建一个新的 Message[] 数组,大小为两个数组长度之和
|
|
|
+ Message[] mergedArray = new Message[array1.length + array2.length];
|
|
|
+ // 将第一个数组复制到新数组中
|
|
|
+ System.arraycopy(array1, 0, mergedArray, 0, array1.length);
|
|
|
+ // 将第二个数组复制到新数组的后半部分
|
|
|
+ System.arraycopy(array2, 0, mergedArray, array1.length, array2.length);
|
|
|
+ return mergedArray;
|
|
|
+ }
|
|
|
+
|
|
|
+ public void receiveBodyContent(SmtpPopSettingsEntity smtpPop,List<EmailsEntity> emailsls,EmailBoxEnum boxEnum) {
|
|
|
+ try {
|
|
|
+ MailProperties properties = new MailProperties(smtpPop);
|
|
|
+ MailConnection mailConnection = MailConnectionUtil.receiveEmailsConnection(properties);
|
|
|
+ if (Objects.isNull(mailConnection)) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (!CollectionUtils.isEmpty(emailsls)) {
|
|
|
+ if (Objects.isNull(mailConnection)) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ for (EmailsEntity email : emailsls) {
|
|
|
+ Message message = boxEnum.code.equals("INBOX") ? mailConnection.getMessageByUid(email.getMsgUid(),"INBOX") : mailConnection.getMessageByUid(email.getMsgUid(),"Sent Items");
|
|
|
+ if (Objects.isNull(message)) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ if (Integer.valueOf(0).equals(email.getIsOnlyHead())) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ String bodyContent = getEmailBodyContent(message);
|
|
|
+ LambdaUpdateWrapper<EmailsEntity> update = new LambdaUpdateWrapper<>();
|
|
|
+ update.set(EmailsEntity::getContent,bodyContent);
|
|
|
+ update.set(EmailsEntity::getIsOnlyHead,0);
|
|
|
+ update.eq(EmailsEntity::getId,email.getId());
|
|
|
+ update(update);
|
|
|
+ CompletableFuture.runAsync(() -> {
|
|
|
+ try {
|
|
|
+ pullMailAttachmentHead(email.getId(),email.getRecipientDate(),message.getContent(),smtpPop);
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("get message content - error", e);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }catch (Exception e) {
|
|
|
+ log.error("receiveHeadContent -- error",e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void addLoadMailContentTask(SmtpPopSettingsEntity smtpPop) {
|
|
|
+
|
|
|
+ ReceiveMailQueueThreadPool instance = ReceiveMailQueueThreadPool.getInstance();
|
|
|
+ String taskName = smtpPop.getEmailAddress()+"_"+smtpPop.getOwnerBy().toString()+"_load_content";
|
|
|
+ if (instance.getTaskInProgressByMail(taskName)) {
|
|
|
+ log.error("有任务正在进行--:>>>>>>>>>>>>>"+taskName);
|
|
|
+ } else {
|
|
|
+ instance.addTask(taskName,new Runnable() {
|
|
|
+ @Override
|
|
|
+ public void run() {
|
|
|
+ loadMailContentTask(smtpPop);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void loadMailContentTask(SmtpPopSettingsEntity smtpPop){
|
|
|
+ try {
|
|
|
+// while (true) {
|
|
|
+ LambdaQueryWrapper<EmailsEntity> wrapper = new LambdaQueryWrapper<>();
|
|
|
+ wrapper.select(EmailsEntity::getId,EmailsEntity::getMsgUid,EmailsEntity::getFolder
|
|
|
+ ,EmailsEntity::getRecipientDate,EmailsEntity::getIsOnlyHead,EmailsEntity::getSmtpPopId);
|
|
|
+ wrapper.eq(EmailsEntity::getIsOnlyHead, 1);
|
|
|
+ wrapper.eq(EmailsEntity::getIsDelete, CommonConstant.DEL_FLAG_0);
|
|
|
+ wrapper.eq(EmailsEntity::getSmtpPopId, smtpPop.getId());
|
|
|
+ List<EmailsEntity> taskEntities = list(wrapper);
|
|
|
+ if (CollectionUtils.isEmpty(taskEntities)) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ List<EmailsEntity> inboxLs = taskEntities.stream().filter(e -> EmailBoxEnum.INBOX.code.equals(e.getFolder())).collect(Collectors.toList());
|
|
|
+ if (!CollectionUtils.isEmpty(inboxLs)) {
|
|
|
+ receiveBodyContentEmails(smtpPop, inboxLs, EmailBoxEnum.INBOX);
|
|
|
+ }
|
|
|
+ List<EmailsEntity> sentLs = taskEntities.stream().filter(e -> EmailBoxEnum.SENT.code.equals(e.getFolder())).collect(Collectors.toList());
|
|
|
+ if (!CollectionUtils.isEmpty(sentLs)) {
|
|
|
+ receiveBodyContentEmails(smtpPop, sentLs, EmailBoxEnum.SENT);
|
|
|
+ }
|
|
|
+// if (CollectionUtils.isEmpty(sentLs) && CollectionUtils.isEmpty(sentLs)) {
|
|
|
+// ret;
|
|
|
+// }
|
|
|
+// }
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("Error in loadMailFiles", e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void addLoadMailFilesTask(SmtpPopSettingsEntity smtpPop) {
|
|
|
+
|
|
|
+ ReceiveMailQueueThreadPool instance = ReceiveMailQueueThreadPool.getInstance();
|
|
|
+ String taskName = smtpPop.getEmailAddress()+"_"+smtpPop.getOwnerBy()+"_load";
|
|
|
+ if (instance.getTaskInProgressByMail(taskName)) {
|
|
|
+ log.error("有任务正在进行--:>>>>>>>>>>>>>"+taskName);
|
|
|
+ } else {
|
|
|
+ instance.addTask(taskName,new Runnable() {
|
|
|
+ @Override
|
|
|
+ public void run() {
|
|
|
+ loadMailFiles(smtpPop);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void loadMailFiles(SmtpPopSettingsEntity smtpPop) {
|
|
|
+ try {
|
|
|
+// while (true) {
|
|
|
+ // Query for undownloaded attachments
|
|
|
+ LambdaQueryWrapper<MailAttachmentEntity> wrapper = new LambdaQueryWrapper<>();
|
|
|
+ wrapper.eq(MailAttachmentEntity::getSmtpPopId, smtpPop.getId());
|
|
|
+ wrapper.eq(MailAttachmentEntity::getDownload, 0);
|
|
|
+ List<MailAttachmentEntity> attachments = mailAttachmentService.list(wrapper);
|
|
|
+
|
|
|
+ // If no more attachments to download, break the loop
|
|
|
+ if (CollectionUtils.isEmpty(attachments)) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Get the corresponding email entities
|
|
|
+ List<Long> mailIds = attachments.stream()
|
|
|
+ .map(MailAttachmentEntity::getEmailId)
|
|
|
+ .collect(Collectors.toList());
|
|
|
+
|
|
|
+ LambdaQueryWrapper<EmailsEntity> mwrapper = new LambdaQueryWrapper<>();
|
|
|
+ mwrapper.select(EmailsEntity::getId,EmailsEntity::getOwnerBy,EmailsEntity::getFolder,EmailsEntity::getContent,EmailsEntity::getMsgUid);
|
|
|
+ mwrapper.in(EmailsEntity::getId, mailIds);
|
|
|
+ List<EmailsEntity> entities = list(mwrapper);
|
|
|
+
|
|
|
+ // If no corresponding emails, break the loop
|
|
|
+ if (CollectionUtils.isEmpty(entities)) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ // Download the attachments
|
|
|
+ loadEmailsFiles(smtpPop, entities, attachments);
|
|
|
+// }
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("Error in loadMailFiles", e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ private static Map<String,String> decodeAndPrintAddresses(Address[] addresses) throws MessagingException, IOException {
|
|
|
+
|
|
|
+ Map<String,String> map = new HashMap<>();
|
|
|
+ if (addresses == null) return new HashMap<>();
|
|
|
+ StringBuilder decodedAddresses = new StringBuilder();
|
|
|
+ for (Address address : addresses) {
|
|
|
+ InternetAddress internetAddress = (InternetAddress) address;
|
|
|
+ String personal = internetAddress.getPersonal();
|
|
|
+ String email = internetAddress.getAddress();
|
|
|
+ if (personal != null) {
|
|
|
+ personal = MimeUtility.decodeText(personal);
|
|
|
+ }
|
|
|
+ map.put(email,(personal != null ? personal : "N/A"));
|
|
|
+// decodedAddresses.append("[Name: ").append(personal != null ? personal : "N/A").append(", Email: ").append(email).append("] ");
|
|
|
+ }
|
|
|
+ return map;
|
|
|
+ }
|
|
|
+
|
|
|
+ private static String mapKeyToString(Map<String,String> map) {
|
|
|
+ if (map == null) return "";
|
|
|
+ String mapKey = map.entrySet().stream()
|
|
|
+ .map(entry -> entry.getKey())
|
|
|
+ .collect(Collectors.joining(","));
|
|
|
+ if (("N/A").equals(mapKey)) {
|
|
|
+ mapKey = "";
|
|
|
+ }
|
|
|
+ return mapKey;
|
|
|
+ }
|
|
|
+
|
|
|
+ private static String mapValueToString(Map<String,String> map) {
|
|
|
+ if (map == null) return "";
|
|
|
+ String mapKey = map.entrySet().stream()
|
|
|
+ .map(entry -> entry.getValue())
|
|
|
+ .collect(Collectors.joining(","));
|
|
|
+
|
|
|
+ if (("N/A").equals(mapKey)) {
|
|
|
+ mapKey = "";
|
|
|
+ }
|
|
|
+ return mapKey;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public Boolean downloadMailAttachment(Long mailId, Date recipientDate,Object messageContent,SmtpPopSettingsEntity smtpPop) {
|
|
|
+ try {
|
|
|
+ String recipient = DateUtils.date2Str(recipientDate, DateUtils.yyyyMMdd);
|
|
|
+ String downloadDir = mailFileProperties.getPath().getPath() + File.separator + smtpPop.getEmailAddress() + File.separator + recipient + File.separator;
|
|
|
+ Object content = messageContent;
|
|
|
+ if (content instanceof Multipart) {
|
|
|
+ Multipart multipart = (Multipart) content;
|
|
|
+ for (int i = 0; i < multipart.getCount(); i++) {
|
|
|
+ BodyPart bodyPart = multipart.getBodyPart(i);
|
|
|
+ if (Part.ATTACHMENT.equalsIgnoreCase(bodyPart.getDisposition())) {
|
|
|
+ saveDownloadAttachment(bodyPart, downloadDir, smtpPop.getId(), mailId);
|
|
|
+ } else if (bodyPart.isMimeType("application/octet-stream")) {
|
|
|
+ saveDownloadAttachment(bodyPart, downloadDir, smtpPop.getId(), mailId);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }catch (Exception e) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public Boolean pullMailAttachmentHead(Long mailId, Date recipientDate,Object mailContent,SmtpPopSettingsEntity smtpPop) {
|
|
|
+ try {
|
|
|
+ if (processedDownloadMailIds.putIfAbsent(mailId, true) == null) {
|
|
|
+ Integer mcount = mailAttachmentService.count(new LambdaQueryWrapper<MailAttachmentEntity>().eq(MailAttachmentEntity::getEmailId,mailId));
|
|
|
+ if(mcount > 0) {
|
|
|
+ return Boolean.TRUE;
|
|
|
+ }
|
|
|
+ String recipient = DateUtils.date2Str(recipientDate,DateUtils.yyyyMMdd);
|
|
|
+ String downloadDir = mailFileProperties.getPath().getPath()+ File.separator+smtpPop.getEmailAddress() +File.separator + recipient + File.separator;
|
|
|
+ Object content =mailContent;
|
|
|
+ if (content instanceof Multipart) {
|
|
|
+ Multipart multipart = (Multipart) content;
|
|
|
+ for (int i = 0; i < multipart.getCount(); i++) {
|
|
|
+ BodyPart bodyPart = multipart.getBodyPart(i);
|
|
|
+ if (Part.ATTACHMENT.equalsIgnoreCase(bodyPart.getDisposition()) || bodyPart.isMimeType("application/octet-stream")) {
|
|
|
+ saveAttachmentRecord(bodyPart, downloadDir,smtpPop.getId(), mailId);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ processedDownloadMailIds.remove(mailId);
|
|
|
+ }catch (Exception e) {
|
|
|
+ processedDownloadMailIds.remove(mailId);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public IPage<EmailsEntity> pageWithScope(Page page, MailDTO dto) {
|
|
|
+ return this.baseMapper.pageListNew(page,dto);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public IPage<EmailsEntity> pageWithScopeCus(Page page, MailDTO dto) {
|
|
|
+ return this.baseMapper.pageListCus(page,dto);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public IPage<EmailsEntity> pageWithScopeAllCus(Page page, MailDTO dto) {
|
|
|
+ return this.baseMapper.pageListNewAllCus(page,dto);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ private void saveAttachmentRecord(BodyPart bodyPart, String downloadDir,Long smtpPopId,Long emailId) throws MessagingException, IOException {
|
|
|
+ String fileName = bodyPart.getFileName();
|
|
|
+ fileName = MimeUtility.decodeText(fileName);
|
|
|
+ fileName = fileName.replace("\n", "").replace("\r", "");
|
|
|
+ String code = RandomGenerateHelper.generateRandomString(6);
|
|
|
+ // 如果不存在这创建路径
|
|
|
+ if (!new File(downloadDir).exists()) {
|
|
|
+ new File(downloadDir).mkdirs();
|
|
|
+ }
|
|
|
+ Integer size = bodyPart.getSize();
|
|
|
+ fileName = fileName+"."+code;
|
|
|
+ File file = new File(downloadDir + File.separator + fileName);
|
|
|
+ saveAttachmentToDatabase(file,code,size,smtpPopId, emailId);
|
|
|
+ }
|
|
|
+
|
|
|
+ public Boolean syncPullEmails(EmailsEntity entity, Message message,SmtpPopSettingsEntity smtpPop) {
|
|
|
+ try {
|
|
|
+ String recipient = DateUtils.date2Str(entity.getRecipientDate(),DateUtils.yyyyMMdd);
|
|
|
+ String downloadDir = mailFileProperties.getPath().getPath()+ File.separator+smtpPop.getEmailAddress() +File.separator + recipient + File.separator;
|
|
|
+ downloadAttachmentFromMessage(message,downloadDir,smtpPop.getId(),entity.getId());
|
|
|
+ }catch (Exception e) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public Boolean analysisDownLoadAttachment(EmailsEntity entity, Message message) {
|
|
|
+ try {
|
|
|
+ String recipient = DateUtils.date2Str(entity.getRecipientDate(),DateUtils.yyyyMMdd);
|
|
|
+ String downloadDir = mailFileProperties.getPath().getPath()+ File.separator+entity.getFrom() +File.separator + recipient + File.separator;
|
|
|
+ downloadAttachmentFromMessage(message,downloadDir,0L,entity.getId());
|
|
|
+ }catch (Exception e) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public EmailsEntity convertMessageToEmailVo(Message message,Boolean isPullHead) {
|
|
|
+
|
|
|
+ try {
|
|
|
+ EmailsEntity entity = new EmailsEntity();
|
|
|
+ String subject = Objects.isNull(message.getSubject()) ? "" : MimeUtility.decodeText(message.getSubject());
|
|
|
+ entity.setSubject(subject);
|
|
|
+ if (subject.contains("回复")) {
|
|
|
+ entity.setSubject(subject);
|
|
|
+ }
|
|
|
+ if (Objects.nonNull(message.getFolder())) {
|
|
|
+ if (message.getFolder().getFullName().equals("INBOX")) {
|
|
|
+ entity.setFolder(EmailBoxEnum.INBOX.code);
|
|
|
+ entity.setInOutMark(1);
|
|
|
+ }else {
|
|
|
+ entity.setFolder(EmailBoxEnum.SENT.code);
|
|
|
+ entity.setInOutMark(2);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ Map<String,String> fromMap = decodeAndPrintAddresses(message.getFrom());
|
|
|
+
|
|
|
+ entity.setFrom(mapKeyToString(fromMap));
|
|
|
+ entity.setFromName(mapValueToString(fromMap));
|
|
|
+
|
|
|
+ Map<String,String> toMap = decodeAndPrintAddresses(message.getRecipients(Message.RecipientType.TO));
|
|
|
+ entity.setRecipient(mapKeyToString(toMap));
|
|
|
+ entity.setRecipientName(mapValueToString(toMap));
|
|
|
+
|
|
|
+ Map<String,String> toMapCC = decodeAndPrintAddresses(message.getRecipients(Message.RecipientType.CC));
|
|
|
+ if (Objects.nonNull(toMapCC)) {
|
|
|
+ entity.setRecipientCc(mapKeyToString(toMapCC));
|
|
|
+ entity.setRecipientCcName(mapKeyToString(toMapCC));
|
|
|
+ }
|
|
|
+ entity.setEmailSize(Long.valueOf(message.getSize()));
|
|
|
+ if (Objects.nonNull(message.getSentDate())) {
|
|
|
+ entity.setSentDate(message.getSentDate());
|
|
|
+ }
|
|
|
+ if (Objects.nonNull(message.getReceivedDate())) {
|
|
|
+ entity.setRecipientDate(message.getReceivedDate());
|
|
|
+ }
|
|
|
+
|
|
|
+ boolean isSeen = message.isSet(Flags.Flag.SEEN);
|
|
|
+ entity.setIsRead(isSeen ? 1 : 0);
|
|
|
+ if (isPullHead) {
|
|
|
+ try {
|
|
|
+ Object content = message.getContent();
|
|
|
+ if (content instanceof String) {
|
|
|
+ entity.setIsOnlyHead(0);
|
|
|
+ entity.setContent(content.toString());
|
|
|
+ } else {
|
|
|
+ entity.setIsOnlyHead(1);
|
|
|
+ }
|
|
|
+ } catch (Exception e){
|
|
|
+ log.error("message.getContent() -- error",e);
|
|
|
+ return entity;
|
|
|
+ }
|
|
|
+
|
|
|
+ } else {
|
|
|
+ try {
|
|
|
+ Object content = message.getContent();
|
|
|
+ String argsStr = "";
|
|
|
+ if (content instanceof String) {
|
|
|
+ argsStr = message.getContent().toString();
|
|
|
+ } else if (content instanceof Multipart) {
|
|
|
+ Multipart multipart = (Multipart) content;
|
|
|
+ argsStr = parseMultipart(multipart);
|
|
|
+ argsStr = parseMultipartImage(argsStr,multipart);
|
|
|
+ }
|
|
|
+ entity.setIsOnlyHead(1);
|
|
|
+ entity.setContent(argsStr);
|
|
|
+ }catch (Exception e) {
|
|
|
+ log.error("message.getContent() -- error",e);
|
|
|
+ return entity;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return entity;
|
|
|
+ }catch (Exception e) {
|
|
|
+ log.error("convertMessageToEmailVo -- error",e);
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public Long getEmailIdByMessgeId(String messageId,Long smtpPopId) {
|
|
|
+ return this.baseMapper.getEmailsIdByMessageId(messageId,smtpPopId);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public EmailsEntity getEmailsByMessageId(String messageId,String folder,Long smtpPopId) {
|
|
|
+ return this.baseMapper.getEmailsByMessageId(messageId,folder,smtpPopId);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public List<String> getEmailMessageIdsByMessageIds(List<String> messageIds,String folder,Long smtpPopId) {
|
|
|
+ return this.baseMapper.getEmailMessageIdsByMessageIds(messageIds,folder,smtpPopId);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public String getEmailMessageIdsByMessageId(String messageId,String folder,Long smtpPopId) {
|
|
|
+ return this.baseMapper.getEmailMessageIdsByMessageId(messageId,folder,smtpPopId);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public Integer getEmailsByMessageId(String messageId,String fromAddress) {
|
|
|
+ LambdaQueryWrapper<EmailsEntity> w = new LambdaQueryWrapper<>();
|
|
|
+ w.eq(EmailsEntity::getMessageId,messageId);
|
|
|
+ w.eq(EmailsEntity::getFrom,fromAddress);
|
|
|
+ return this.baseMapper.selectCount(w);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public String getEmailBodyContent(Message message) {
|
|
|
+ try {
|
|
|
+ Object content = message.getContent();
|
|
|
+ String argsStr = "";
|
|
|
+ if (content instanceof String) {
|
|
|
+ argsStr = message.getContent().toString();
|
|
|
+ } else if (content instanceof Multipart) {
|
|
|
+ Multipart multipart = (Multipart) content;
|
|
|
+ argsStr = parseMultipart(multipart);
|
|
|
+ argsStr = parseMultipartImage(argsStr,multipart);
|
|
|
+ }
|
|
|
+ return argsStr;
|
|
|
+ }catch (Exception e) {
|
|
|
+ log.error("convertMessageToEmailVo -- error",e);
|
|
|
+ return "";
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void bindLiaisonMailCustomerIdByMailIdAndUserId(Long mailId, String mailAddress, Long userId,Integer inOutMark) {
|
|
|
+ try {
|
|
|
+ if (StrUtil.isBlank(mailAddress)) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+// Runnable ttlRunnable = TtlRunnable.get(new Runnable() {
|
|
|
+// @Override
|
|
|
+// public void run() {
|
|
|
+ String lowerMailAddress = mailAddress.toLowerCase();
|
|
|
+// Set<Long> cId = emailsMapper.getMailCustomerIdByMailIdAndUserId(mailId,lowerMailAddress,userId);
|
|
|
+// Set<Long> lId = new HashSet<>();
|
|
|
+// if (Objects.isNull(cId)) {
|
|
|
+// new HashSet<>();
|
|
|
+// }
|
|
|
+// List<MailLiaisonVO> vos = emailsMapper.getLiaisonMailCustomerIdByMailIdAndUserId(mailId,lowerMailAddress,userId);
|
|
|
+// if (!CollectionUtils.isEmpty(vos)) {
|
|
|
+// Set<Long> mcId = vos.stream().map(e -> e.getCustomerId()).collect(Collectors.toSet());
|
|
|
+// if (!CollectionUtils.isEmpty(mcId)) {
|
|
|
+// cId.addAll(mcId);
|
|
|
+// }
|
|
|
+// Set<Long> lIds = vos.stream().map(e -> e.getLiaisonId()).collect(Collectors.toSet());
|
|
|
+// if (!CollectionUtils.isEmpty(lIds)) {
|
|
|
+// lId.addAll(lIds);
|
|
|
+// }
|
|
|
+// }
|
|
|
+// if (!CollectionUtils.isEmpty(lId) || !CollectionUtils.isEmpty(cId)) {
|
|
|
+// String customerId = CollectionUtils.isEmpty(cId) ? null : org.apache.commons.lang.StringUtils.join(cId,",");
|
|
|
+// String liaisonIds = CollectionUtils.isEmpty(lId) ? null : org.apache.commons.lang.StringUtils.join(lId,",");
|
|
|
+// emailsMapper.bindMailCustomerIdByMailId(mailId,customerId,liaisonIds);
|
|
|
+// }
|
|
|
+
|
|
|
+ Object myClassInstance = SpringContextUtils.getBean("customerMailBingMarkServiceImpl");
|
|
|
+ Class<?> clazz = myClassInstance.getClass();
|
|
|
+ try {
|
|
|
+ Method method = clazz.getMethod("mateBindCustomerLiaisonMail",Long.class,Long.class,String.class,Integer.class);
|
|
|
+ method.invoke(myClassInstance,mailId,userId,lowerMailAddress,inOutMark);
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("mateBindCustomerLiaisonFromMail --e",e);
|
|
|
+ }
|
|
|
+ //}
|
|
|
+// });
|
|
|
+// ThreadPoolUtil.execute(ttlRunnable);
|
|
|
+ }catch (Exception e) {
|
|
|
+ log.error("bindLiaisonMailCustomerIdByMailIdAndUserId-------------------",e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private static Long getMessageId(Message message, Folder folder) throws MessagingException {
|
|
|
+ if (folder instanceof IMAPFolder) {
|
|
|
+ IMAPFolder imapFolder = (IMAPFolder) folder;
|
|
|
+ return imapFolder.getUID(message);
|
|
|
+ } else {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ private String parseMultipart(Multipart multipart) {
|
|
|
+ StringBuilder stringBuilder = new StringBuilder();
|
|
|
+ try {
|
|
|
+ StringBuilder plainTextContent = new StringBuilder() ;
|
|
|
+ StringBuilder plainHtmlContent = new StringBuilder() ;
|
|
|
+ for (int i = 0; i < multipart.getCount(); i++) {
|
|
|
+ BodyPart bodyPart = multipart.getBodyPart(i);
|
|
|
+ if (bodyPart.isMimeType("text/plain")) {
|
|
|
+ plainTextContent.append((String) bodyPart.getContent());
|
|
|
+ } else if (bodyPart.isMimeType("text/html")) {
|
|
|
+ String htmlContent = (String) bodyPart.getContent();
|
|
|
+ plainHtmlContent.append(htmlContent);
|
|
|
+ } else if (bodyPart.isMimeType("multipart/alternative")) {
|
|
|
+ stringBuilder.append(parseMultipart((Multipart) bodyPart.getContent()));
|
|
|
+ } else if (bodyPart.isMimeType("multipart/*")) {
|
|
|
+ stringBuilder.append(parseMultipart((Multipart) bodyPart.getContent()));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (StrUtil.isNotBlank(plainHtmlContent)) {
|
|
|
+ stringBuilder.append(plainHtmlContent);
|
|
|
+ } else {
|
|
|
+ stringBuilder.append(plainTextContent);
|
|
|
+ }
|
|
|
+ return stringBuilder.toString();
|
|
|
+ }catch (Exception e) {
|
|
|
+ log.error("parseMultipart - error",e);
|
|
|
+ return stringBuilder.toString();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private String parseMultipartImage(String htmlContent,Multipart multipart) {
|
|
|
+ try {
|
|
|
+ for (int i = 0; i < multipart.getCount(); i++) {
|
|
|
+ BodyPart bodyPart = multipart.getBodyPart(i);
|
|
|
+ String contentType = bodyPart.getContentType();
|
|
|
+ log.debug("contentType -="+contentType);
|
|
|
+ if (Part.INLINE.equalsIgnoreCase(bodyPart.getDisposition()) || bodyPart.getContentType().toLowerCase().startsWith("image/")) {
|
|
|
+ htmlContent = processHtmlWithBase64Images(htmlContent, bodyPart);
|
|
|
+ } else if (bodyPart.isMimeType("multipart/alternative")) {
|
|
|
+ htmlContent = parseMultipartImage(htmlContent,(Multipart) bodyPart.getContent());
|
|
|
+ } else if (bodyPart.isMimeType("multipart/*")) {
|
|
|
+ htmlContent = parseMultipartImage(htmlContent,(Multipart) bodyPart.getContent());
|
|
|
+ } else if (bodyPart.isMimeType("application/octet-stream")) {
|
|
|
+ htmlContent = processHtmlWithBase64Images(htmlContent, bodyPart);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }catch (Exception e) {
|
|
|
+ log.error("parseMultipartImage - ERROR",e);
|
|
|
+
|
|
|
+ }
|
|
|
+ return htmlContent;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 处理 HTML 内容中的图片引用,替换为 base64
|
|
|
+// private String processHtmlWithBase64Images(String htmlContent, Multipart multipart) throws MessagingException, IOException {
|
|
|
+// // 找到所有 <img> 标签并处理 src="cid:"
|
|
|
+// String regex = "src=\"cid:(.*?)\"";
|
|
|
+// java.util.regex.Pattern pattern = java.util.regex.Pattern.compile(regex);
|
|
|
+// java.util.regex.Matcher matcher = pattern.matcher(htmlContent);
|
|
|
+//
|
|
|
+// while (matcher.find()) {
|
|
|
+// String contentId = matcher.group(1);
|
|
|
+// BodyPart imagePart = findImagePartByContentId(multipart, contentId);
|
|
|
+//
|
|
|
+// if (imagePart != null) {
|
|
|
+// // 转换图片为 Base64 并替换 HTML 中的 src="cid:..."
|
|
|
+// String base64Image = convertImageToBase64(imagePart);
|
|
|
+// htmlContent = htmlContent.replace("cid:" + contentId, "data:image/png;base64," + base64Image);
|
|
|
+// }
|
|
|
+// }
|
|
|
+//
|
|
|
+// return htmlContent;
|
|
|
+// }
|
|
|
+
|
|
|
+ private String processHtmlWithBase64Images(String htmlContent, BodyPart bodyPart) throws MessagingException, IOException {
|
|
|
+ // 找到所有 <img> 标签并处理 src="cid:"
|
|
|
+ String contentId = ((MimeBodyPart) bodyPart).getContentID();
|
|
|
+// String contentId = ((IMAPBodyPart) bodyPart).getContentID();
|
|
|
+ if (StrUtil.isBlank(contentId)) {
|
|
|
+ if (bodyPart.getHeader("Content-ID") != null) {
|
|
|
+ contentId = bodyPart.getHeader("Content-ID").toString();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (StrUtil.isNotBlank(contentId)) {
|
|
|
+ BodyPart imagePart = bodyPart;
|
|
|
+ if (imagePart != null) {
|
|
|
+ // 转换图片为 Base64 并替换 HTML 中的 src="cid:..."
|
|
|
+ contentId = contentId.replaceAll("^<(.+)>$", "$1");
|
|
|
+ String base64Image = convertImageToBase64(imagePart);
|
|
|
+ htmlContent = htmlContent.replace("cid:" + contentId, "data:image/png;base64," + base64Image);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return htmlContent;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 根据 Content-ID 查找对应的图片部分
|
|
|
+ private BodyPart findImagePartByContentId(Multipart multipart, String contentId) throws MessagingException {
|
|
|
+ for (int i = 0; i < multipart.getCount(); i++) {
|
|
|
+ BodyPart bodyPart = multipart.getBodyPart(i);
|
|
|
+ if (bodyPart.getHeader("Content-ID") != null) {
|
|
|
+ String[] contentIdHeader = bodyPart.getHeader("Content-ID");
|
|
|
+ if (contentIdHeader[0].contains(contentId)) {
|
|
|
+ return bodyPart; // 找到匹配的图片
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return null; // 未找到匹配的图片
|
|
|
+ }
|
|
|
+
|
|
|
+ // 将图片转换为 Base64 字符串
|
|
|
+ private String convertImageToBase64(BodyPart bodyPart) throws IOException, MessagingException {
|
|
|
+ InputStream inputStream = bodyPart.getInputStream();
|
|
|
+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
|
|
+
|
|
|
+ byte[] buffer = new byte[1024];
|
|
|
+ int bytesRead;
|
|
|
+ while ((bytesRead = inputStream.read(buffer)) != -1) {
|
|
|
+ outputStream.write(buffer, 0, bytesRead);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 将图片转换为 Base64 编码
|
|
|
+ byte[] imageBytes = outputStream.toByteArray();
|
|
|
+ return Base64.getEncoder().encodeToString(imageBytes);
|
|
|
+ }
|
|
|
+
|
|
|
+ private void downloadAttachmentFromMessage(Message message, String downloadDir,Long smtpPopId,Long emailId) {
|
|
|
+ try {
|
|
|
+ Object content = message.getContent();
|
|
|
+ if (content instanceof Multipart) {
|
|
|
+ Multipart multipart = (Multipart) content;
|
|
|
+ for (int i = 0; i < multipart.getCount(); i++) {
|
|
|
+ BodyPart bodyPart = multipart.getBodyPart(i);
|
|
|
+ if (Part.ATTACHMENT.equalsIgnoreCase(bodyPart.getDisposition()) || bodyPart.isMimeType("application/octet-stream")) {
|
|
|
+ saveDownloadAttachment(bodyPart, downloadDir,smtpPopId,emailId);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }catch (Exception e) {
|
|
|
+ log.error("downloadAttachmentFromMessage -- error = ",e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void saveDownloadAttachment(BodyPart bodyPart, String downloadDir,Long smtpPopId,Long emailId) {
|
|
|
+ try {
|
|
|
+ String fileName = bodyPart.getFileName();
|
|
|
+ fileName = MimeUtility.decodeText(fileName);
|
|
|
+ fileName = fileName.replace("\n", "").replace("\r", "");
|
|
|
+ String code = RandomGenerateHelper.generateRandomString(6);
|
|
|
+ // 如果不存在这创建路径
|
|
|
+ Integer size = bodyPart.getSize();
|
|
|
+ if (!new File(downloadDir).exists()) {
|
|
|
+ new File(downloadDir).mkdirs();
|
|
|
+ }
|
|
|
+ fileName = fileName+"."+code;
|
|
|
+ File file = new File(downloadDir + File.separator + fileName);
|
|
|
+ try (FileOutputStream output = new FileOutputStream(file)) {
|
|
|
+ bodyPart.getInputStream().transferTo(output);
|
|
|
+ }
|
|
|
+ saveAttachmentToDatabase(file,code,size,smtpPopId,emailId);
|
|
|
+ }catch (Exception e) {
|
|
|
+ log.error("saveDownloadAttachment -- error",e);
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ private void saveAttachmentHeader(BodyPart bodyPart, String downloadDir,Long smtpPopId,Long emailId) throws MessagingException, IOException {
|
|
|
+ String fileName = bodyPart.getFileName();
|
|
|
+ fileName = MimeUtility.decodeText(fileName);
|
|
|
+ fileName = fileName.replace("\n", "").replace("\r", "");
|
|
|
+ String code = RandomGenerateHelper.generateRandomString(6);
|
|
|
+ // 如果不存在这创建路径
|
|
|
+ Integer size = bodyPart.getSize();
|
|
|
+ if (!new File(downloadDir).exists()) {
|
|
|
+ new File(downloadDir).mkdirs();
|
|
|
+ }
|
|
|
+ fileName = fileName+"."+code;
|
|
|
+ File file = new File(downloadDir + File.separator + fileName);
|
|
|
+ saveAttachmentToDatabase(file,code,size,smtpPopId,emailId);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ private void saveAttachmentToDatabase(File file,String code,Integer size,Long smtpPopId,Long emailId) {
|
|
|
+ String fileName = file.getName().replace("."+code,"");
|
|
|
+ String fName = FileNameUtils.getBaseName(fileName);
|
|
|
+ String fExt = FileNameUtils.getExtension(fileName);
|
|
|
+ LambdaQueryWrapper<MailAttachmentEntity> l = new LambdaQueryWrapper<>();
|
|
|
+ l.eq(MailAttachmentEntity::getFileName,fName);
|
|
|
+ l.eq(MailAttachmentEntity::getEmailId,emailId);
|
|
|
+ l.eq(MailAttachmentEntity::getFileExt,fExt);
|
|
|
+ l.eq(MailAttachmentEntity::getFileSize,Long.valueOf(size));
|
|
|
+ l.eq(MailAttachmentEntity::getSmtpPopId,smtpPopId);
|
|
|
+ l.last("limit 1");
|
|
|
+ Integer c = mailAttachmentService.count(l);
|
|
|
+ if (c == 0) {
|
|
|
+ MailAttachmentEntity attachment = new MailAttachmentEntity();
|
|
|
+ attachment.setEmailId(emailId);
|
|
|
+ attachment.setSmtpPopId(smtpPopId);
|
|
|
+ attachment.setFileCode(code);
|
|
|
+ attachment.setFileName(fName);
|
|
|
+ attachment.setFilePath(file.getAbsolutePath().replace(mailFileProperties.getPath().getPath(),""));
|
|
|
+ attachment.setFileExt(fExt);
|
|
|
+ attachment.setFileSize(Long.valueOf(size));
|
|
|
+ mailAttachmentService.saveOrUpdate(attachment);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private Session getSendEmailsSession(SmtpPopSettingsEntity smtpPop) {
|
|
|
+
|
|
|
+ Properties properties = new Properties();
|
|
|
+ properties.put("mail.smtp.host", smtpPop.getSmtpServer());
|
|
|
+ properties.put("mail.smtp.port", smtpPop.getSmtpPort());
|
|
|
+ properties.put("mail.smtp.auth", "true");
|
|
|
+ properties.put("mail.user", smtpPop.getEmailAddress());
|
|
|
+ properties.put("mail.smtp.starttls.enable",Integer.valueOf(1).equals(smtpPop.getSmtpTls()) ? "true" : "false");
|
|
|
+ properties.put("mail.smtp.ssl.enable", Integer.valueOf(1).equals(smtpPop.getSmtpSsl()) ? "true" : "false");
|
|
|
+
|
|
|
+ Session session = Session.getInstance(properties, new Authenticator() {
|
|
|
+ protected PasswordAuthentication getPasswordAuthentication() {
|
|
|
+ return new PasswordAuthentication(smtpPop.getEmailAddress(), smtpPop.getEmailPassword());
|
|
|
+ }
|
|
|
+ });
|
|
|
+ return session;
|
|
|
+ }
|
|
|
+
|
|
|
+ private EmailsEntity saveSendEmails(SendMailDTO dto,String fromAddress,String fromNickname,Long replyMsgId,Long sizeInBytes) {
|
|
|
+ try {
|
|
|
+ EmailsEntity entity = new EmailsEntity();
|
|
|
+ String subject = MimeUtility.decodeText(dto.getSubject());
|
|
|
+ entity.setSubject(subject);
|
|
|
+ entity.setSentDate(new Date());
|
|
|
+ entity.setIsRead(Integer.valueOf(1));
|
|
|
+ if (Objects.nonNull(dto.getDelaySendTime())) {
|
|
|
+ entity.setDelaySendTime(dto.getDelaySendTime());
|
|
|
+ entity.setStatus(-1);
|
|
|
+ } else {
|
|
|
+ entity.setStatus(0);
|
|
|
+ }
|
|
|
+ if (Objects.nonNull(replyMsgId)) {
|
|
|
+ entity.setReplyMsgId(replyMsgId);
|
|
|
+ }
|
|
|
+ if (Objects.nonNull(dto.getId())) {
|
|
|
+ entity.setId(dto.getId());
|
|
|
+ }
|
|
|
+ if (Objects.nonNull(dto.getIsReceipt())) {
|
|
|
+ entity.setIsReceipt(dto.getIsReceipt());
|
|
|
+ }
|
|
|
+ entity.setEmailSize(sizeInBytes);
|
|
|
+ entity.setFromName(fromNickname);
|
|
|
+ entity.setFrom(fromAddress);
|
|
|
+ if (!CollectionUtils.isEmpty(dto.getRecipientls())) {
|
|
|
+ entity.setRecipient(StringUtil.join(dto.getRecipientls(),","));
|
|
|
+ }
|
|
|
+ if (!CollectionUtils.isEmpty(dto.getRecipientCcls())) {
|
|
|
+ entity.setRecipientCc(StringUtil.join(dto.getRecipientCcls(),","));
|
|
|
+ }
|
|
|
+ if (!CollectionUtils.isEmpty(dto.getRecipientBccls())) {
|
|
|
+ entity.setRecipientBcc(StringUtil.join(dto.getRecipientBccls(),","));
|
|
|
+ }
|
|
|
+ entity.setSubject(dto.getSubject());
|
|
|
+ entity.setContent(dto.getContent());
|
|
|
+ entity.setFolder(EmailBoxEnum.SENTING.code);
|
|
|
+ return entity;
|
|
|
+ }catch (Exception e) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private EmailsEntity updateSendEmailStatus(Long emailId) {
|
|
|
+ try {
|
|
|
+ EmailsEntity entity = new EmailsEntity();
|
|
|
+ entity.setId(emailId);
|
|
|
+ entity.setStatus(Integer.valueOf(1));
|
|
|
+ entity.setFolder(EmailBoxEnum.SENT.code);
|
|
|
+ updateById(entity);
|
|
|
+ return entity;
|
|
|
+ }catch (Exception e) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void analysisMailEml(List<Message> messages,Set<String> cusMails,Long ownerBy) {
|
|
|
+ if (CollectionUtils.isEmpty(messages) || CollectionUtils.isEmpty(cusMails)) {
|
|
|
+ return;
|
|
|
+ } List<Message> messagels = messages;
|
|
|
+ for (Message message : messagels) {
|
|
|
+ Set<String> cusAddressls = cusMails;
|
|
|
+ try {
|
|
|
+ String[] r = message.getHeader("Message-ID");
|
|
|
+ if (Objects.isNull(r)) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ String messageId = message.getHeader("Message-ID")[0];
|
|
|
+ Map<String, String> fromMap = decodeAndPrintAddresses(message.getFrom());
|
|
|
+ String fromAddress = mapKeyToString(fromMap);
|
|
|
+ Integer count = this.getEmailsByMessageId(messageId, fromAddress);
|
|
|
+ if (!Integer.valueOf(0).equals(count)) {
|
|
|
+ log.error("getEmailsByMessageId-----" + messageId);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ EmailsEntity entity = convertMessageToEmailVo(message, false);
|
|
|
+ if (Objects.isNull(entity)) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ entity.setMessageId(messageId);
|
|
|
+
|
|
|
+ if (StrUtil.isBlank(entity.getFromName())) {
|
|
|
+ entity.setFromName(StringUtil.extractUsernames(entity.getFrom()));
|
|
|
+ }
|
|
|
+ if (StrUtil.isBlank(entity.getRecipientName())) {
|
|
|
+ entity.setRecipientName(StringUtil.extractUsernames(entity.getRecipient()));
|
|
|
+ }
|
|
|
+ if (StrUtil.isBlank(entity.getRecipientCcName())) {
|
|
|
+ entity.setRecipientCcName(StringUtil.extractUsernames(entity.getRecipientCc()));
|
|
|
+ }
|
|
|
+ if (cusAddressls.contains(entity.getFrom())) {
|
|
|
+ entity.setInOutMark(1);
|
|
|
+ entity.setFolder("INBOX");
|
|
|
+ } else {
|
|
|
+ entity.setInOutMark(2);
|
|
|
+ entity.setFolder("SENT");
|
|
|
+ }
|
|
|
+ if (Objects.isNull(entity.getRecipientDate())) {
|
|
|
+ entity.setRecipientDate(entity.getSentDate());
|
|
|
+ }
|
|
|
+ entity.setSourceType(1);
|
|
|
+ entity.setOwnerBy(ownerBy);
|
|
|
+ entity.setUpdateBy(1L);
|
|
|
+ entity.setCreateBy(1L);
|
|
|
+ entity.setIsOnlyHead(0);
|
|
|
+
|
|
|
+ Boolean b = saveOrUpdate(entity);
|
|
|
+ if (b) {
|
|
|
+ analysisDownLoadAttachment(entity, message);
|
|
|
+ /**
|
|
|
+ * 加载附件
|
|
|
+ */
|
|
|
+ if (Integer.valueOf(1).equals(entity.getInOutMark())) {
|
|
|
+ bindLiaisonMailCustomerIdByMailIdAndUserId(entity.getId(), entity.getFrom(), 1L, 1);
|
|
|
+ } else {
|
|
|
+ String recipient = entity.getRecipient();
|
|
|
+ if (StrUtil.isNotBlank(entity.getRecipientCc())) {
|
|
|
+ if (StrUtil.isNotBlank(recipient)) {
|
|
|
+ recipient = recipient + "," + entity.getRecipientCc();
|
|
|
+ } else {
|
|
|
+ recipient = entity.getRecipientCc();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ bindLiaisonMailCustomerIdByMailIdAndUserId(entity.getId(), recipient, 1L, 2);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("analysisMailEml -- error:", e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public List<EmailsEntity> analysisMailEmlls(List<Message> messages,Set<String> internalMails,Long ownerBy) {
|
|
|
+
|
|
|
+ List<EmailsEntity> entities = new ArrayList<>();
|
|
|
+
|
|
|
+ if (CollectionUtils.isEmpty(messages) || CollectionUtils.isEmpty(internalMails)) {
|
|
|
+ return entities;
|
|
|
+ }
|
|
|
+ List<Message> messagels = messages;
|
|
|
+ for (Message message : messagels) {
|
|
|
+
|
|
|
+ try {
|
|
|
+ String[] r = message.getHeader("Message-ID");
|
|
|
+ if (Objects.isNull(r)) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ String messageId = message.getHeader("Message-ID")[0];
|
|
|
+ Map<String, String> fromMap = decodeAndPrintAddresses(message.getFrom());
|
|
|
+ String fromAddress = mapKeyToString(fromMap);
|
|
|
+ Integer count = this.getEmailsByMessageId(messageId, fromAddress);
|
|
|
+ if (!Integer.valueOf(0).equals(count)) {
|
|
|
+ log.error("getEmailsByMessageId-----" + messageId);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ EmailsEntity entity = convertMessageToEmailVo(message, false);
|
|
|
+ if (Objects.isNull(entity)) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ entity.setMessageId(messageId);
|
|
|
+
|
|
|
+ if (StrUtil.isBlank(entity.getFromName())) {
|
|
|
+ entity.setFromName(StringUtil.extractUsernames(entity.getFrom()));
|
|
|
+ }
|
|
|
+ if (StrUtil.isBlank(entity.getRecipientName())) {
|
|
|
+ entity.setRecipientName(StringUtil.extractUsernames(entity.getRecipient()));
|
|
|
+ }
|
|
|
+ if (StrUtil.isBlank(entity.getRecipientCcName())) {
|
|
|
+ entity.setRecipientCcName(StringUtil.extractUsernames(entity.getRecipientCc()));
|
|
|
+ }
|
|
|
+ /**
|
|
|
+ * 如果发件箱是内部邮箱,则代表是发出去的邮件
|
|
|
+ */
|
|
|
+ if (internalMails.contains(entity.getFrom())) {
|
|
|
+ entity.setInOutMark(2);
|
|
|
+ entity.setFolder("SENT");
|
|
|
+ } else {
|
|
|
+ entity.setInOutMark(1);
|
|
|
+ entity.setFolder("INBOX");
|
|
|
+ }
|
|
|
+ if (Objects.isNull(entity.getRecipientDate())) {
|
|
|
+ entity.setRecipientDate(entity.getSentDate());
|
|
|
+ }
|
|
|
+ entity.setSourceType(1);
|
|
|
+ entity.setOwnerBy(ownerBy);
|
|
|
+ entity.setUpdateBy(1L);
|
|
|
+ entity.setCreateBy(1L);
|
|
|
+ entity.setIsOnlyHead(0);
|
|
|
+
|
|
|
+ Boolean b = saveOrUpdate(entity);
|
|
|
+ if (b) {
|
|
|
+ entities.add(entity);
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("analysisMailEml -- error:", e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return entities;
|
|
|
+ }
|
|
|
+
|
|
|
+// public void pullMailRecord(SmtpPopSettingsEntity smtpPop, String folderName, EmailBoxEnum boxEnum, List<Integer> messageIds) {
|
|
|
+// MailProperties properties = new MailProperties(smtpPop);
|
|
|
+// MailConnection mailConnection = MailConnectionUtil.receiveEmailsConnection(properties);
|
|
|
+// if (Objects.isNull(mailConnection)) {
|
|
|
+// return;
|
|
|
+// }
|
|
|
+// try {
|
|
|
+// Store store = mailConnection.getStore();
|
|
|
+// Folder inbox = store.getFolder(folderName);
|
|
|
+// inbox.open(Folder.READ_WRITE);
|
|
|
+//
|
|
|
+// int[] intArray = messageIds.stream().mapToInt(Integer::intValue).toArray();
|
|
|
+// Message[] messages = inbox.getMessages(intArray);
|
|
|
+// for (Message message : messages) {
|
|
|
+// String messageId = message.getHeader("Message-ID")[0];
|
|
|
+// EmailsEntity entity = convertMessageToEmailVo(message,false);
|
|
|
+// if (Objects.isNull(entity)) {
|
|
|
+// return;
|
|
|
+// }
|
|
|
+// entity.setSmtpPopId(smtpPop.getId());
|
|
|
+// entity.setMsgUid(messageId);
|
|
|
+// entity.setFolder(boxEnum.code);
|
|
|
+// Boolean b = this.save(entity);
|
|
|
+// if(b) {
|
|
|
+// syncPullEmails(entity,message,folderName,smtpPop);
|
|
|
+// }
|
|
|
+// }
|
|
|
+// mailConnection.close();
|
|
|
+// }catch (Exception e) {
|
|
|
+// log.error("receiveEmails - error =",e);
|
|
|
+// mailConnection.close();
|
|
|
+// }
|
|
|
+// }
|
|
|
+
|
|
|
+ public static void main(String[] args) {
|
|
|
+ try {
|
|
|
+ String baseDir = "D:/mail/attachment/rena@renice-tech.com/20240911";
|
|
|
+ String fileName = "Datasheet(128G SLC)-Renice X5 2.5 SATAII SSD V1.2 Version.pdf.KrhPNh";
|
|
|
+ Path filePath = Paths.get(baseDir, fileName);
|
|
|
+ File file = new File(filePath.toUri());
|
|
|
+ File parentDir = file.getParentFile();
|
|
|
+ // 如果父目录不存在,则递归创建
|
|
|
+ if (parentDir != null && !parentDir.exists()) {
|
|
|
+ parentDir.mkdirs(); // mkdirs() 会创建所有必要的父目录
|
|
|
+ }
|
|
|
+ String content = "这是要写入文件的字符串内容";
|
|
|
+
|
|
|
+ try (InputStream inputStream = new ByteArrayInputStream(content.getBytes(StandardCharsets.UTF_8));
|
|
|
+ FileOutputStream output = new FileOutputStream(file)) {
|
|
|
+ inputStream.transferTo(output); // 将字符串流写入文件
|
|
|
+ }
|
|
|
+ System.out.println("-----------------------"+filePath);
|
|
|
+ }catch (Exception e) {
|
|
|
+ log.error(e);
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+}
|