package com.yc.crm.mail.service;
|
|
import com.sun.mail.imap.IMAPBodyPart;
|
import com.sun.mail.imap.IMAPStore;
|
import com.yc.crm.mail.entity.FoundationEntity;
|
import com.yc.crm.mail.entity.MailFileEntity;
|
import com.yc.crm.mail.entity.T482102Entity;
|
import com.yc.crm.mail.entity.t482101HEntity;
|
import com.yc.entity.attachment.AttachmentEntity;
|
import com.yc.service.BaseService;
|
import org.apache.commons.io.FileUtils;
|
import org.apache.commons.lang3.StringUtils;
|
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.stereotype.Service;
|
|
import javax.mail.*;
|
import javax.mail.internet.*;
|
import javax.servlet.http.HttpServletRequest;
|
import java.io.*;
|
import java.text.SimpleDateFormat;
|
import java.time.LocalDate;
|
import java.time.ZoneId;
|
import java.util.*;
|
|
import static com.yc.crm.mail.service.MailImpl.shoppingImageServer;
|
|
/**
|
* @BelongsProject: eCoWorksV3
|
* @BelongsPackage: com.yc.crm.mail.service
|
* @author: xinyb
|
* @CreateTime: 2024-09-12 10:30
|
* @Description:
|
*/
|
@Service
|
public class MailServiceImpl extends BaseService implements MailServiceIfc {
|
|
@Autowired
|
MailIfc mailIfc;
|
@Autowired
|
MailAccountIfc mailAccountIfc;
|
|
@Override
|
public void receivingEmails(T482102Entity emailEntity, FoundationEntity foundation) throws MessagingException {
|
String protocol = emailEntity.getReceiveProtocol().toLowerCase();//接收协议 imap pop3
|
String server = emailEntity.getReceiveHost();//"imap.qq.com";
|
Integer port = emailEntity.getReceivePort();//993
|
String user = emailEntity.getReceiveEmail();//邮箱
|
String pwd = emailEntity.getReceivePassword();//密码
|
|
Properties properties = new Properties();
|
properties.put("mail.store.protocol", protocol); // IMAP over SSL
|
if (protocol.contains("imap")) {//接收协议imap
|
properties.put("mail.imaps.host", server);
|
properties.put("mail.imaps.port", port);
|
} else if (protocol.contains("pop3")) {//接收协议pop3
|
properties.put("mail.pop3.host", server);
|
properties.put("mail.pop3.port", port);
|
} else {//其他(再加)
|
properties.put("mail.imaps.host", server);
|
properties.put("mail.imaps.port", port);
|
}
|
// properties.put("mail.imaps.starttls.enable", "true");//// IMAP 协议设置 STARTTLS
|
|
HashMap IAM = new HashMap();
|
//带上IMAP ID信息,由key和value组成,例如name,version,vendor,support-email等。
|
IAM.put("name", user);
|
IAM.put("version", emailEntity.getDocVersion() + "");
|
IAM.put("vendor", emailEntity.getCompanyName());
|
IAM.put("support-email", emailEntity.getEmail());
|
//创建会话
|
Session session = Session.getInstance(properties, new Authenticator() {
|
@Override
|
protected PasswordAuthentication getPasswordAuthentication() {
|
return new PasswordAuthentication(user, pwd);
|
}
|
});
|
//存储对象
|
IMAPStore store = (IMAPStore) session.getStore(protocol);//imap协议或pop3协议类型(推荐你使用IMAP协议来存取服务器上的邮件。)
|
//连接
|
store.connect(server, user, pwd);
|
store.id(IAM);//163邮箱需要,不然会报:A3 NO SELECT Unsafe Login. Please contact kefu@188.com for help
|
Folder folder = null;
|
try {
|
// 获得收件箱
|
folder = store.getFolder("INBOX");
|
// 以读写模式打开收件箱
|
folder.open(Folder.READ_WRITE);
|
|
//false 表示未读 ,true已读,获得收件箱的邮件列表
|
// FlagTerm flagTerm = new FlagTerm(new Flags(Flags.Flag.SEEN), true);
|
// Message[] messages = folder.search(flagTerm);
|
|
//获取收件箱邮件(全部)
|
Message[] messages = folder.getMessages();
|
|
//根据时间
|
// SimpleDateFormat format=new SimpleDateFormat("YYYY-MM-dd HH:mm:ss");//
|
// SearchTerm sinceTerm=new FromStringTerm(emailEntity.getCreateTime());//开始时间
|
// SearchTerm beforeTerm=new FromStringTerm(format.format(new Date()));//结束时间
|
// Message[] messages = folder.search(new AndTerm(sinceTerm,beforeTerm));
|
|
//邮箱封装保存
|
// setMailContent(messages, emailEntity, foundation);
|
} catch (NoSuchProviderException e) {
|
throw e;
|
} catch (MessagingException e) {
|
throw e;
|
// } catch (IOException e) {
|
// throw new RuntimeException(e);
|
} catch (Exception e) {
|
throw new RuntimeException(e);
|
} finally {
|
try {
|
if (folder != null) {
|
folder.close(false);
|
}
|
if (store != null) {
|
store.close();
|
}
|
} catch (MessagingException e) {
|
throw e;
|
}
|
}
|
}
|
|
|
@Override
|
public void sendEmails(t482101HEntity t482101H, HttpServletRequest request) throws Exception {
|
try {
|
//根据当前用户查询绑定的邮箱信息
|
T482102Entity emailEntity = mailAccountIfc.getAccountInfo(t482101H.getUserCode(), t482101H.getSender());//返回邮箱的账号信息
|
if (emailEntity == null || StringUtils.isBlank(emailEntity.getSmtpEmail())) {
|
if (StringUtils.isBlank(t482101H.getDocCode())) {
|
t482101H.setMailType(0);//草稿箱状态
|
t482101H = mailIfc.saveReceivingMail(t482101H);//保存到草稿箱内
|
}
|
throw new MessagingException("找不到邮箱:" + t482101H.getSender() + "配置信息请完善。邮件已保存到草稿箱#" + t482101H.getDocCode());
|
}
|
//有发送的邮件保存到后台数据库
|
//邮箱服务器配置
|
Properties properties = new Properties();
|
properties.setProperty("mail.smtp.auth", "true");// // 设置SMTP是否需要认证 指定客户端是否向邮件服务器提交认证
|
properties.setProperty("mail.transport.protocol", "smtp");//设置传输协议 指定采用的邮件发送协议。
|
properties.put("mail.smtp.ssl.enable", emailEntity.isSmtpSSL() + "");// // 设置启用SSL加密
|
properties.setProperty("mail.smtp.host", emailEntity.getSmtpHost());
|
properties.setProperty("mail.smtp.port", emailEntity.getSmtpPort() + "");
|
|
// properties.setProperty("mail.smtp.starttls.enable", "true");//// SMTP 协议设置 STARTTLS 开启tls
|
// properties.setProperty("mail.smtp.socketFactory.port", emailEntity.getSmtpPort() + "");
|
|
//
|
String sendEmail = emailEntity.getSmtpEmail();//发件人
|
String sendPassword = emailEntity.getSmtpPassword();//密码
|
String recipientEmail = StringUtils.join(t482101H.getReceiver(), ",");//收件人
|
Session session = Session.getInstance(properties, new Authenticator() {
|
@Override
|
protected PasswordAuthentication getPasswordAuthentication() {
|
return new PasswordAuthentication(sendEmail, sendPassword);
|
}
|
});
|
|
MimeMessage message = new MimeMessage(session);
|
message.setFrom(new InternetAddress(sendEmail));
|
message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(recipientEmail));
|
message.setSubject(t482101H.getSubject());
|
|
String Unique_ID = "<onBus_" + UUID.randomUUID().toString().toUpperCase() + "@mail.com>";//系统单号唯一码
|
message.setHeader("Message-ID", Unique_ID);//系统内部唯一码
|
t482101H.setMessageId(Unique_ID);//messageId赋值
|
|
if (t482101H.getCc() != null && t482101H.getCc().size() > 0) {//抄送
|
message.setRecipients(Message.RecipientType.CC, InternetAddress.parse(StringUtils.join(t482101H.getCc(), ",")));
|
}
|
if (t482101H.getBcc() != null && t482101H.getBcc().size() > 0) {//密送
|
message.setRecipients(Message.RecipientType.BCC, InternetAddress.parse(StringUtils.join(t482101H.getBcc(), ",")));
|
}
|
|
//创建多部分消息
|
Multipart multipart = new MimeMultipart();
|
|
MimeBodyPart textPart = new MimeBodyPart();
|
textPart.setText(t482101H.getContent());//内容
|
multipart.addBodyPart(textPart);
|
|
//下面附件内容
|
if (StringUtils.isNotBlank(t482101H.getAttachmentList())) {//有附件内容
|
//获取到附件内容
|
List<AttachmentEntity> attachmentEntities = mailIfc.getAttachmentEntityList(t482101H.getAttachmentList());
|
if (attachmentEntities != null && attachmentEntities.size() > 0) {
|
for (AttachmentEntity a : attachmentEntities) {
|
InputStream inputStream = new ByteArrayInputStream(a.getOriginalPicture());
|
File file = new File(a.getOriginalFileName());
|
FileUtils.copyInputStreamToFile(inputStream, file);
|
MimeBodyPart bodyPart = new MimeBodyPart();
|
bodyPart.attachFile(file);
|
bodyPart.setFileName(a.getOriginalFileName());
|
multipart.addBodyPart(bodyPart);
|
}
|
}
|
}
|
message.setContent(multipart);
|
try {
|
if (StringUtils.isBlank(t482101H.getDocCode())) {//不在草稿箱有单号
|
mailIfc.saveReceivingMail(t482101H);//保存后发送
|
} else {
|
t482101H.setMailType(2);//发件箱状态
|
mailIfc.updateMailDrafts(t482101H);//更新成发件箱
|
}
|
Transport.send(message);//发送
|
} catch (MessagingException m) {//发送异常处理
|
t482101H.setMailType(0);//草稿箱状态
|
mailIfc.updateMailDrafts(t482101H);//更新成草稿箱
|
throw new MessagingException("发送邮件异常,邮件已保存在草稿箱。异常原因:" + m.getMessage() + "#" + t482101H.getDocCode());
|
}
|
} catch (Exception e) {
|
throw e;
|
}
|
}
|
|
/**
|
* 收件箱返回的信息进行封装处理
|
*
|
* @param messages
|
* @return
|
* @throws MessagingException
|
* @throws IOException
|
*/
|
public void setMailContent(Message[] messages, T482102Entity email, FoundationEntity foundation) throws Exception {
|
try {
|
List<t482101HEntity> t482101HEntityList = new ArrayList<>();
|
List<String> messageIdList = mailIfc.getMessageIdList(email.getReceiveEmail());//存在系统表里的邮件
|
Message m = null;
|
LocalDate startTime = LocalDate.parse(email.getCreateTime().split(" ")[0]);//创建时间
|
LocalDate endTime = LocalDate.parse(email.getUpdateTime().split(" ")[0]);//更新时间
|
if (startTime.equals(endTime)) {
|
startTime = endTime.minusDays(30);
|
} else {
|
startTime = endTime;
|
endTime = LocalDate.now();
|
}
|
Date nowTime = new Date();
|
for (int i = 0; i < messages.length; i++) {
|
m = messages[i];
|
LocalDate sendDate = m.getSentDate().toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
|
if ((sendDate.isAfter(startTime) || sendDate.isEqual(startTime)) &&
|
(sendDate.isBefore(endTime) || sendDate.isEqual(endTime))) {//时间段获取邮件
|
t482101HEntity mail = new t482101HEntity();
|
String messageId = m.getHeader("Message-ID")[0];
|
if (messageIdList != null && messageIdList.contains(messageId)) {//存在就不组装
|
continue;
|
}
|
mail.setMessageId(messageId);//获取邮件唯一ID
|
mail.setMailType(1);//收件
|
if (m.isSet(Flags.Flag.SEEN)) {//邮件已标记为已读
|
mail.setReadFlag(1);//已读
|
}
|
if (m.isExpunged()) {//检查一个消息是否已被删除。
|
mail.setDeleteFlag(1);//已删除
|
}
|
if (m.isSet(Flags.Flag.ANSWERED)) {//邮件是否已回复
|
|
}
|
if (m.isSet(Flags.Flag.DRAFT)) {//是否是草稿箱
|
mail.setMailType(0);//是草稿箱
|
}
|
mail.setUserCode(foundation.getUserCode());
|
mail.setUserName(foundation.getUserName());
|
mail.setCompanyId(foundation.getCompanyId());
|
mail.setCompanyName(foundation.getCompanyName());
|
mail.setClassType(1);
|
mail.setSubject(m.getSubject());//标题
|
Date date = m.getReceivedDate();//时间
|
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
mail.setReceiveTime(formatter.format(date));
|
String result = "";
|
StringBuilder plainText = new StringBuilder();//纯文本
|
if (m.isMimeType("text/plain")) {
|
plainText.append(m.getContent());
|
} else if (m.isMimeType("text/html")) {//html格式
|
result = m.getContent().toString();
|
} else if (m.isMimeType("multipart/*")) {
|
MailFileEntity mailFile = new MailFileEntity();//附件
|
List<MailFileEntity.MailBodyPart> part = new ArrayList<>();
|
String unId = UUID.randomUUID().toString().toUpperCase();
|
StringBuilder attachment = new StringBuilder();
|
result = getTextFromMimeMultipart((MimeMultipart) m.getContent(), plainText, part, unId, attachment);
|
mailFile.setPart(part);
|
mailFile.setUnId(unId);//生成uuid
|
mail.setMailFile(mailFile);//附件添加到里面
|
if (StringUtils.isNotBlank(attachment)) {//附件游标保存
|
mail.setAttachFlag(1);
|
mail.setAttachmentList(unId + attachment.toString());
|
}
|
} else {
|
result = m.getContent().toString();
|
}
|
mail.setContent(result);//保存内容
|
mail.setPlainText(plainText.toString().trim());//明文
|
String from = MimeUtility.decodeText(m.getFrom()[0].toString());
|
InternetAddress internetAddress = new InternetAddress(from);
|
mail.setSender(internetAddress.getAddress());//发件人
|
from = MimeUtility.decodeText(m.getRecipients(Message.RecipientType.TO)[0].toString());
|
internetAddress = new InternetAddress(from);
|
// mail.setReceiver(internetAddress.getAddress());//收件人
|
List<String> receivers = new ArrayList<>();//抄送人
|
receivers.add(email.getReceiveEmail());
|
mail.setReceiver(receivers);//统一成一个收件人
|
|
Address[] ccAddress = m.getRecipients(Message.RecipientType.CC);
|
if (ccAddress != null && ccAddress.length > 0) {
|
List<String> cc = new ArrayList<>();//抄送人
|
for (Address c : ccAddress) {
|
from = MimeUtility.decodeText(c.toString());
|
internetAddress = new InternetAddress(from);
|
cc.add(internetAddress.getAddress());
|
}
|
mail.setCc(cc);
|
}
|
Address[] bccAddress = m.getRecipients(Message.RecipientType.BCC);
|
if (bccAddress != null && bccAddress.length > 0) {
|
List<String> bcc = new ArrayList<>();//密送
|
for (Address c : bccAddress) {
|
from = MimeUtility.decodeText(c.toString());
|
internetAddress = new InternetAddress(from);
|
bcc.add(internetAddress.getAddress());
|
}
|
mail.setBcc(bcc);//密送人
|
}
|
t482101HEntityList.add(mail);
|
}
|
}
|
if (t482101HEntityList.size() > 0) {
|
mailAccountIfc.updateEmailTime(email.getAccountId());//更新一次配置
|
mailIfc.saveReceivingMailList(t482101HEntityList);//保存
|
}
|
} catch (Exception e) {
|
throw e;
|
}
|
}
|
|
/**
|
* @param mimeMultipart 邮箱对象
|
* @param plainText 纯文本
|
* @param part 邮件附件集合
|
* @return
|
* @throws Exception
|
*/
|
// 辅助方法,用于递归获取纯文本邮件内容
|
private String getTextFromMimeMultipart(MimeMultipart mimeMultipart, StringBuilder plainText, List<MailFileEntity.MailBodyPart> part, String unId, StringBuilder attachment) throws Exception {
|
int count = mimeMultipart.getCount();
|
if (count == 0) {
|
throw new MessagingException("Multipart with no body parts");
|
}
|
boolean multipartAlternative = isMultipartAlternative(mimeMultipart);
|
StringBuilder result = new StringBuilder();
|
if (multipartAlternative) {
|
for (int i = 0; i < count; i++) {
|
BodyPart bodyPart = mimeMultipart.getBodyPart(i);
|
if (bodyPart.isMimeType("text/plain")) {//这个是获取纯文本
|
plainText.append(bodyPart.getContent());
|
}
|
if (bodyPart.isMimeType("text/html")) {//这个是获取html格式
|
result.append(bodyPart.getContent());
|
}
|
}
|
} else {
|
for (int i = 0; i < count; i++) {
|
BodyPart bodyPart = mimeMultipart.getBodyPart(i);
|
if (bodyPart.isMimeType("image/*")) {//图片
|
MailFileEntity.MailBodyPart p = new MailFileEntity.MailBodyPart();
|
String fileName = MimeUtility.decodeText(bodyPart.getFileName());
|
p.setFileName(fileName);//有些邮件没有扩展名
|
String cId = ((IMAPBodyPart) bodyPart).getContentID();//获取cId
|
if (StringUtils.isNotBlank(cId)) {//在有扩展名时候
|
if (cId.lastIndexOf(".") != -1) {
|
p.setFileType(cId.substring(cId.lastIndexOf(".") + 1));
|
p.setFileName(cId);//有些邮件没有扩展名
|
}
|
}
|
if (StringUtils.isBlank(p.getFileType()) && StringUtils.isNotBlank(fileName)) {
|
if (fileName.lastIndexOf(".") != -1) {
|
p.setFileType(fileName.substring(fileName.lastIndexOf(".") + 1));
|
}
|
}
|
p.setFileSize(bodyPart.getSize());
|
p.setByteFile(convertInputStreamToByteArray(bodyPart.getInputStream()));
|
String fieldId = UUID.randomUUID().toString();//系统自定义一个随机字段
|
p.setFieldId(fieldId);
|
String nextResult = result.toString();
|
if (nextResult.contains(cId)) {//有嵌套内容
|
//替换
|
nextResult = nextResult.replace("cid:" + cId + "", shoppingImageServer + "/uploads/attachment/82/482101/" + unId + "@p@" + p.getPhysicalFile());
|
result.setLength(0);//清空先
|
result.append(nextResult);
|
}
|
part.add(p);
|
} else if (Part.ATTACHMENT.equalsIgnoreCase(bodyPart.getDisposition())) {//附件
|
MailFileEntity.MailBodyPart p = new MailFileEntity.MailBodyPart();
|
String fileName = MimeUtility.decodeText(bodyPart.getFileName());
|
p.setFileName(fileName);
|
if (StringUtils.isNotBlank(fileName)) {
|
p.setFileType(fileName.substring(fileName.lastIndexOf(".") + 1));
|
}
|
p.setFileSize(bodyPart.getSize());
|
p.setByteFile(convertInputStreamToByteArray(bodyPart.getInputStream()));
|
String fieldId = UUID.randomUUID().toString();//系统自定义一个随机字段
|
p.setFieldId(fieldId);
|
attachment.append(";" + fieldId);
|
part.add(p);
|
} else if (bodyPart.isMimeType("multipart/*")) {
|
result.append(getTextFromMimeMultipart((MimeMultipart) bodyPart.getContent(), plainText, part, unId, attachment));
|
}
|
}
|
}
|
return result.toString();
|
}
|
|
/**
|
* 辅助方法,判断是否为multipart/alternative类型的邮件
|
*
|
* @param mimeMultipart
|
* @return
|
* @throws Exception
|
*/
|
private boolean isMultipartAlternative(MimeMultipart mimeMultipart) throws Exception {
|
boolean textPlainFound = false;
|
boolean textHtmlFound = false;
|
int count = mimeMultipart.getCount();
|
for (int i = 0; i < count; i++) {
|
BodyPart bodyPart = mimeMultipart.getBodyPart(i);
|
if (bodyPart.isMimeType("text/plain")) {
|
textPlainFound = true;
|
} else if (bodyPart.isMimeType("text/html")) {
|
textHtmlFound = true;
|
}
|
}
|
return textPlainFound && textHtmlFound;
|
}
|
|
/**
|
* 转换 byte
|
*
|
* @param inputStream
|
* @return
|
* @throws IOException
|
*/
|
private byte[] convertInputStreamToByteArray(InputStream inputStream) throws IOException {
|
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
|
byte[] buffer = new byte[1024];
|
int length;
|
while ((length = inputStream.read(buffer)) != -1) {
|
byteArrayOutputStream.write(buffer, 0, length);
|
}
|
return byteArrayOutputStream.toByteArray();
|
}
|
}
|