diff --git a/jeecg-boot-base-core/src/main/java/org/jeecg/common/email/EmailServiceManager.java b/jeecg-boot-base-core/src/main/java/org/jeecg/common/email/EmailServiceManager.java index aab5724c..e1982487 100644 --- a/jeecg-boot-base-core/src/main/java/org/jeecg/common/email/EmailServiceManager.java +++ b/jeecg-boot-base-core/src/main/java/org/jeecg/common/email/EmailServiceManager.java @@ -21,6 +21,7 @@ import org.jeecg.common.util.DateUtils; import org.jeecg.common.util.RedisUtil; import org.jeecg.modules.base.entity.postgre.SysEmail; import org.jetbrains.annotations.NotNull; + import javax.mail.*; import javax.mail.internet.InternetAddress; import javax.mail.internet.MimeMessage; @@ -56,13 +57,21 @@ public class EmailServiceManager { * 系统启动时间 */ private Date systemStartupTime; - /** 邮件接收数量 */ + /** + * 邮件接收数量 + */ private Integer receiveNum; - /** smtp协议的存储对象 */ + /** + * smtp协议的存储对象 + */ private IMAPStore store = null; - /** 邮件附件临时存储路径 */ + /** + * 邮件附件临时存储路径 + */ private String temporaryStoragePath; - /** 收件箱 */ + /** + * 收件箱 + */ private Folder folder = null; private RedisUtil redisUtil; @@ -72,25 +81,27 @@ public class EmailServiceManager { private final ReentrantLock lock = new ReentrantLock(); @NotNull - public static EmailServiceManager getInstance(){ + public static EmailServiceManager getInstance() { return new EmailServiceManager(); } /** * 初始化邮件服务管理器 + * * @param email 邮件属性 */ - public void init(SysEmail email){ + public void init(SysEmail email) { this.email = email; } /** * 初始化邮件服务管理器 + * * @param email 邮件属性 */ public void init(SysEmail email, Integer receiveNum, String temporaryStoragePath, - Date systemStartupTime, SpectrumPathProperties pathProperties,TaskProperties taskProperties, - RedisUtil redisUtil){ + Date systemStartupTime, SpectrumPathProperties pathProperties, TaskProperties taskProperties, + RedisUtil redisUtil) { this.email = email; this.receiveNum = receiveNum; this.temporaryStoragePath = temporaryStoragePath; @@ -103,18 +114,18 @@ public class EmailServiceManager { /** * 测试邮件服务连通性 */ - public boolean testConnectEmailServer(){ + public boolean testConnectEmailServer() { Socket socket = new Socket(); boolean flag = false; try { - socket.connect(new InetSocketAddress(email.getEmailServerAddress(),email.getPort()),3000); - log.info("{}邮件服务连接测试成功",email.getName()); + socket.connect(new InetSocketAddress(email.getEmailServerAddress(), email.getPort()), 3000); + log.info("{}邮件服务连接测试成功", email.getName()); flag = true; } catch (IOException e) { - log.error("{}邮件服务连接测试失败,请检查邮件服务属性配置是否正确或邮件服务未开启,原因: ",email.getName(),e); - }finally { + log.error("{}邮件服务连接测试失败,请检查邮件服务属性配置是否正确或邮件服务未开启,原因: ", email.getName(), e); + } finally { try { - if(null != socket){ + if (null != socket) { socket.close(); } } catch (IOException e) { @@ -129,12 +140,12 @@ public class EmailServiceManager { */ public Message[] receiveMail() throws Exception { String status = EmailLogManager.STATUS_SUCCESS; - try{ + try { //配置邮件服务属性 Properties properties = new Properties(); properties.put("mail.store.protocol", "imap"); properties.put("mail.imap.host", email.getEmailServerAddress()); - properties.put("mail.imap.port",email.getPort()); + properties.put("mail.imap.port", email.getPort()); properties.put("mail.imap.connectiontimeout", "3000"); properties.put("mail.imap.timeout", "3000"); if (email.getIsQiye() == 1) { @@ -145,10 +156,10 @@ public class EmailServiceManager { HashMap IAM = new HashMap(); //带上IMAP ID信息,由key和value组成,例如name,version,vendor,support-email等。 - IAM.put("name","myname"); - IAM.put("version","1.0.0"); - IAM.put("vendor","myclient"); - IAM.put("support-email","testmail@test.com"); + IAM.put("name", "myname"); + IAM.put("version", "1.0.0"); + IAM.put("vendor", "myclient"); + IAM.put("support-email", "testmail@test.com"); //获取邮件回话 final Session session = Session.getDefaultInstance(properties); @@ -157,22 +168,26 @@ public class EmailServiceManager { //获取smtp协议的存储对象 store = (IMAPStore) session.getStore(); //连接 - store.connect(email.getUsername(),email.getPassword()); - // 解决163普通邮箱无法建立连接问题 - store.id(IAM); + store.connect(email.getUsername(), email.getPassword()); + if (email.getEmailServerType()==1) { + + // 解决163普通邮箱无法建立连接问题 + store.id(IAM); + } + //获取收件箱 folder = store.getFolder("INBOX");//INBOX folder.open(Folder.READ_WRITE); //如果邮箱邮件数量 > 0 final int messageCount = folder.getMessageCount(); - if(messageCount > 0){ + if (messageCount > 0) { Message[] messages = null; - if(Objects.isNull(this.systemStartupTime)){ - int finalNum = messageCount > this.receiveNum?this.receiveNum:messageCount; + if (Objects.isNull(this.systemStartupTime)) { + int finalNum = messageCount > this.receiveNum ? this.receiveNum : messageCount; //邮箱邮件下标是从1开始的 - return folder.getMessages(1,finalNum); + return folder.getMessages(1, finalNum); } - SearchTerm searchTerm = new ReceivedDateTerm(ComparisonTerm.GE,this.systemStartupTime); + SearchTerm searchTerm = new ReceivedDateTerm(ComparisonTerm.GE, this.systemStartupTime); messages = folder.search(searchTerm); Arrays.sort(messages, (o1, o2) -> { try { @@ -183,21 +198,21 @@ public class EmailServiceManager { } return 0; }); - if(this.receiveNum >= messages.length){ + if (this.receiveNum >= messages.length) { return messages; - }else{ - return Arrays.copyOfRange(messages,0,this.receiveNum-1); + } else { + return Arrays.copyOfRange(messages, 0, this.receiveNum - 1); } } - } catch (Exception e){ + } catch (Exception e) { status = EmailLogManager.STATUS_ERROR; - log.error("Email connection is abnormal, account is {}, service is {},the reason is {}.",email.getName(),email.getEmailServerAddress(),e.getMessage()); + log.error("Email connection is abnormal, account is {}, service is {},the reason is {}.", email.getName(), email.getEmailServerAddress(), e.getMessage()); throw e; } finally { - EmailLogEvent connectEvent = new EmailLogEvent(EmailLogManager.GS_TYPE_GET,email,status,EmailLogManager.CONNECT); + EmailLogEvent connectEvent = new EmailLogEvent(EmailLogManager.GS_TYPE_GET, email, status, EmailLogManager.CONNECT); EmailLogManager.getInstance().setConnectLogEvent(connectEvent); //GetAllId C++原业务是把远程邮箱邮件同步到C++,本次java编写没有这一步,所以和Connect绑定,若Connect成功则GetAllId成功 - EmailLogEvent getAllEvent = new EmailLogEvent(EmailLogManager.GS_TYPE_GET,status,EmailLogManager.GETALLID); + EmailLogEvent getAllEvent = new EmailLogEvent(EmailLogManager.GS_TYPE_GET, status, EmailLogManager.GETALLID); EmailLogManager.getInstance().setGetAllIdLogEvent(getAllEvent); } return null; @@ -206,14 +221,14 @@ public class EmailServiceManager { /* * 测试收件邮箱账号是否可以正常使用 * */ - public boolean canReceive(){ + public boolean canReceive() { Integer port = email.getPort(); String username = email.getUsername(); String password = email.getPassword(); String host = email.getEmailServerAddress(); Properties props = new Properties(); - props.put("mail.store.protocol","imap"); + props.put("mail.store.protocol", "imap"); props.put("mail.imap.host", host); props.put("mail.imap.port", port); @@ -224,26 +239,26 @@ public class EmailServiceManager { } }); - try(Store store = session.getStore()) { + try (Store store = session.getStore()) { store.connect(host, username, password); return store.isConnected(); } catch (Exception e) { - log.error("收件邮箱服务[Host: {}, Port: {}, Username: {}]连接异常: {}",host, port, username, e.getMessage()); + log.error("收件邮箱服务[Host: {}, Port: {}, Username: {}]连接异常: {}", host, port, username, e.getMessage()); return false; } } /* - * 测试收件邮箱账号是否可以正常使用(开启了SSL安全验证的邮箱) - * */ - public boolean canReceiveSSL(){ + * 测试收件邮箱账号是否可以正常使用(开启了SSL安全验证的邮箱) + * */ + public boolean canReceiveSSL() { Integer port = email.getPort(); String username = email.getUsername(); String password = email.getPassword(); String host = email.getEmailServerAddress(); Properties props = new Properties(); - props.put("mail.store.protocol","imap"); + props.put("mail.store.protocol", "imap"); props.put("mail.imap.host", host); props.put("mail.imap.port", port); props.put("mail.imap.auth", "true"); @@ -257,19 +272,19 @@ public class EmailServiceManager { } }); - try(Store store = session.getStore()) { + try (Store store = session.getStore()) { store.connect(host, username, password); return store.isConnected(); } catch (Exception e) { - log.error("收件邮箱服务SSL[Host: {}, Port: {}, Username: {}]连接异常: {}",host, port, username, e.getMessage()); + log.error("收件邮箱服务SSL[Host: {}, Port: {}, Username: {}]连接异常: {}", host, port, username, e.getMessage()); return false; } } /* - * 测试发件邮箱账号是否可以正常使用 - * */ - public boolean canSend(){ + * 测试发件邮箱账号是否可以正常使用 + * */ + public boolean canSend() { Integer port = email.getPort(); String username = email.getUsername(); String password = email.getPassword(); @@ -288,19 +303,19 @@ public class EmailServiceManager { } }); - try (Transport transport = session.getTransport()){ + try (Transport transport = session.getTransport()) { transport.connect(host, username, password); return true; } catch (Exception e) { - log.error("发件邮箱服务[Host: {}, Port: {}, Username: {}]连接异常: {}",host, port, username, e.getMessage()); + log.error("发件邮箱服务[Host: {}, Port: {}, Username: {}]连接异常: {}", host, port, username, e.getMessage()); return false; } } /* - * 测试发件邮箱账号是否可以正常使用(开启了SSL安全验证的邮箱) - * */ - public boolean canSendSSL(){ + * 测试发件邮箱账号是否可以正常使用(开启了SSL安全验证的邮箱) + * */ + public boolean canSendSSL() { Integer port = email.getPort(); String username = email.getUsername(); String password = email.getPassword(); @@ -321,11 +336,11 @@ public class EmailServiceManager { } }); - try (Transport transport = session.getTransport()){ + try (Transport transport = session.getTransport()) { transport.connect(host, username, password); return true; } catch (Exception e) { - log.error("发件邮箱服务SSL[Host: {}, Port: {}, Username: {}]连接异常: {}",host, port, username, e.getMessage()); + log.error("发件邮箱服务SSL[Host: {}, Port: {}, Username: {}]连接异常: {}", host, port, username, e.getMessage()); return false; } } @@ -361,7 +376,7 @@ public class EmailServiceManager { // 发送邮件 Transport transport = session.getTransport(); - transport.connect(email.getUsername(),email.getPassword()); + transport.connect(email.getUsername(), email.getPassword()); transport.sendMessage(message, message.getAllRecipients()); // 关闭资源 @@ -371,7 +386,7 @@ public class EmailServiceManager { /** * 发送邮件 群发 */ - public void sendMail(MessageDTO messageDTO){ + public void sendMail(MessageDTO messageDTO) { // 邮箱连接属性 Properties props = new Properties(); props.put("mail.transport.protocol", "smtp"); @@ -396,24 +411,24 @@ public class EmailServiceManager { InternetAddress.parse(messageDTO.getToUser())); // 发送邮件 transport = session.getTransport(); - transport.connect(email.getUsername(),email.getPassword()); - transport.sendMessage(message,message.getAllRecipients()); + transport.connect(email.getUsername(), email.getPassword()); + transport.sendMessage(message, message.getAllRecipients()); } catch (MessagingException e) { // 无效的电子邮箱导致群发失败,剔除无效邮箱然后重新发送 Address[] invalid; if (e instanceof SMTPAddressFailedException) { invalid = ((SMTPAddressFailedException) e).getInvalidAddresses(); - reSendMail(invalid,messageDTO); + reSendMail(invalid, messageDTO); } else if (e instanceof SendFailedException) { invalid = ((SendFailedException) e).getInvalidAddresses(); - reSendMail(invalid,messageDTO); + reSendMail(invalid, messageDTO); } - }finally { - if (transport != null){ + } finally { + if (transport != null) { try { transport.close(); } catch (MessagingException e) { - log.error("Transport关闭失败,{}",e); + log.error("Transport关闭失败,{}", e); } } } @@ -425,20 +440,20 @@ public class EmailServiceManager { * @param invalid 无效电子邮箱列表 * @param messageDTO 消息dto */ - private void reSendMail(Address[] invalid,MessageDTO messageDTO){ + private void reSendMail(Address[] invalid, MessageDTO messageDTO) { List invalidEmails = Arrays.stream(invalid) .map(address -> address.toString()) .collect(Collectors.toList()); - log.warn("部分或者全部邮件发送失败,无效的电子邮箱:{}",invalidEmails); + log.warn("部分或者全部邮件发送失败,无效的电子邮箱:{}", invalidEmails); String[] allEmails = messageDTO.getToUser().split(SymbolConstant.COMMA); String[] emails = new String[]{}; for (String address : invalidEmails) { - emails = ArrayUtil.removeEle(allEmails,address); + emails = ArrayUtil.removeEle(allEmails, address); } // 如果移除无效电子邮箱后,待发送邮箱不为空 String toUser = Arrays.stream(emails) .collect(Collectors.joining(SymbolConstant.COMMA)); - if (StrUtil.isNotBlank(toUser)){ + if (StrUtil.isNotBlank(toUser)) { messageDTO.setToUser(toUser); sendMail(messageDTO); } @@ -446,10 +461,11 @@ public class EmailServiceManager { /** * 获取邮件主题 + * * @param message * @return */ - public String getMailSubject(@NotNull Message message,Integer batchesCounter) throws MessagingException { + public String getMailSubject(@NotNull Message message, Integer batchesCounter) throws MessagingException { String subject = ""; String status = EmailLogManager.STATUS_SUCCESS; try { @@ -459,34 +475,36 @@ public class EmailServiceManager { } catch (MessagingException e) { status = EmailLogManager.STATUS_ERROR; throw e; - }finally { - EmailLogEvent event = new EmailLogEvent(batchesCounter,Thread.currentThread().getId(),EmailLogManager.GS_TYPE_GET,status,EmailLogManager.GETIDHEADER); - EmailLogManager.getInstance().offer(Thread.currentThread().getId(),event); + } finally { + EmailLogEvent event = new EmailLogEvent(batchesCounter, Thread.currentThread().getId(), EmailLogManager.GS_TYPE_GET, status, EmailLogManager.GETIDHEADER); + EmailLogManager.getInstance().offer(Thread.currentThread().getId(), event); } return subject; } /** * 获取邮件内容 + * * @param part * @return * @throws MessagingException * @throws IOException */ public void getMailContent(@NotNull Part part, StringBuilder content) throws MessagingException, IOException { - if(part.isMimeType(MailContentType.PLAIN.getContentType())){ + if (part.isMimeType(MailContentType.PLAIN.getContentType())) { content.append(part.getContent()); - }else if(part.isMimeType("multipart/*")){ + } else if (part.isMimeType("multipart/*")) { Multipart multipart = (Multipart) part.getContent(); - for(int i=0;i saveAttachment(@NotNull Part part) throws MessagingException, IOException { List filePathList = Lists.newArrayList(); Multipart multipart = (Multipart) part.getContent(); - for(int i=0;i outputStream, Message message) throws MessagingException, IOException { message.writeTo(outputStream.get()); } + /** * 删除邮件 + * * @param message * @throws MessagingException */ - public void removeMail(@NotNull Message message,Integer batchesCounter){ + public void removeMail(@NotNull Message message, Integer batchesCounter) { String status = EmailLogManager.STATUS_SUCCESS; String subject = ""; Date receivedDate = null; try { subject = MimeUtility.decodeText(message.getSubject()); receivedDate = message.getReceivedDate(); - message.setFlag(Flags.Flag.DELETED,true); + message.setFlag(Flags.Flag.DELETED, true); // log.info("EmailServiceManager: Remove Email:{},receiveTime:{}",message.getSubject(), DateUtils.formatDate(message.getReceivedDate(),"yyyy-MM-dd HH:mm:ss")); } catch (MessagingException | UnsupportedEncodingException e) { status = EmailLogManager.STATUS_ERROR; - log.error("Email deletion failed, the subject of the email is :{}, the reason is :",subject, e); + log.error("Email deletion failed, the subject of the email is :{}, the reason is :", subject, e); e.printStackTrace(); } catch (Exception e) { log.error(e.getMessage(), e); } finally { - EmailLogEvent removeEvent = new EmailLogEvent(batchesCounter,Thread.currentThread().getId(),EmailLogManager.GS_TYPE_GET,status,EmailLogManager.DELETEID,subject,DateUtils.formatDate(receivedDate,"yyyy-MM-dd HH:mm:ss:SSS")); - EmailLogManager.getInstance().offer(Thread.currentThread().getId(),removeEvent); + EmailLogEvent removeEvent = new EmailLogEvent(batchesCounter, Thread.currentThread().getId(), EmailLogManager.GS_TYPE_GET, status, EmailLogManager.DELETEID, subject, DateUtils.formatDate(receivedDate, "yyyy-MM-dd HH:mm:ss:SSS")); + EmailLogManager.getInstance().offer(Thread.currentThread().getId(), removeEvent); //这里删除和彻底删除一起写入日志,java和C++处理有差异,java是在连接关闭时彻底删除的 - EmailLogEvent expungeEvent = new EmailLogEvent(batchesCounter,Thread.currentThread().getId(),EmailLogManager.GS_TYPE_GET,status,EmailLogManager.EXPUNGE,subject,DateUtils.formatDate(receivedDate,"yyyy-MM-dd HH:mm:ss:SSS")); - EmailLogManager.getInstance().offer(Thread.currentThread().getId(),expungeEvent); + EmailLogEvent expungeEvent = new EmailLogEvent(batchesCounter, Thread.currentThread().getId(), EmailLogManager.GS_TYPE_GET, status, EmailLogManager.EXPUNGE, subject, DateUtils.formatDate(receivedDate, "yyyy-MM-dd HH:mm:ss:SSS")); + EmailLogManager.getInstance().offer(Thread.currentThread().getId(), expungeEvent); } } /** * 关闭邮件服务连接资源 */ - public void close(List messageIds){ + public void close(List messageIds) { try { - if(null != folder){ + if (null != folder) { folder.expunge(); folder.close(); } - if(null != store){ + if (null != store) { store.close(); } log.info("{}: EmailServiceManage资源关闭完成.", Thread.currentThread().getName()); @@ -760,7 +780,7 @@ public class EmailServiceManager { // redisUtil.del(key); // } } catch (MessagingException e) { - log.error("Email closure failed, email address is: {}, reason is: {}",email.getUsername(),e); + log.error("Email closure failed, email address is: {}, reason is: {}", email.getUsername(), e); e.printStackTrace(); } } @@ -768,18 +788,19 @@ public class EmailServiceManager { /** * 校验邮件 * 若此次获取的邮件是上次删除失败的邮件直接删除 + * * @param message */ - public boolean check(Message message,String messageId){ + public boolean check(Message message, String messageId) { boolean exist = false; try { - String key = RedisConstant.EMAIL_MSG_ID+StringConstant.COLON+messageId; - int numberKey = redisUtil.get(key) != null? (int) redisUtil.get(key):0; + String key = RedisConstant.EMAIL_MSG_ID + StringConstant.COLON + messageId; + int numberKey = redisUtil.get(key) != null ? (int) redisUtil.get(key) : 0; // exist = redisUtil.hasKey(key); - if(numberKey >= taskProperties.getForceDeletedNumber()){ + if (numberKey >= taskProperties.getForceDeletedNumber()) { exist = true; - log.info("Check: Remove Email:{},receiveTime:{}",message.getSubject(), DateUtils.formatDate(message.getReceivedDate(),"yyyy-MM-dd HH:mm:ss")); - message.setFlag(Flags.Flag.DELETED,true); + log.info("Check: Remove Email:{},receiveTime:{}", message.getSubject(), DateUtils.formatDate(message.getReceivedDate(), "yyyy-MM-dd HH:mm:ss")); + message.setFlag(Flags.Flag.DELETED, true); redisUtil.del(key); } return exist; diff --git a/jeecg-boot-base-core/src/main/java/org/jeecg/modules/base/entity/postgre/SysEmail.java b/jeecg-boot-base-core/src/main/java/org/jeecg/modules/base/entity/postgre/SysEmail.java index 42ed02c6..2b70faf3 100644 --- a/jeecg-boot-base-core/src/main/java/org/jeecg/modules/base/entity/postgre/SysEmail.java +++ b/jeecg-boot-base-core/src/main/java/org/jeecg/modules/base/entity/postgre/SysEmail.java @@ -94,4 +94,6 @@ public class SysEmail implements Serializable { */ @TableField(value = "update_by") private String updateBy; + @TableField(value = "email_server_type") + private Integer emailServerType; }