功能:前端设定时间,实现指定时间发送邮件。
技术:MQ异步延迟消息
代码完成后优化:一切实现好你会发现数据会有一定问题,因为消息是排列消费的,后安排的消息永远在之前消息消费后才会消费,所以你要保证时间最近的消息先去排队。前端设计时间要有一定时间限制,及设定时间不能设定五分钟内,后台逻辑只需要定时任务五分钟执行一次,查询未来五分钟需要执行的邮件任务,按照时间排序即可,将优先的任务消息,先排队消费,这样就能实现指定时间发送邮件。
整体思想:
延迟消息config封装:(SendMailDelayConfig:包括
SEND_MAIL_DELAY_REPEAT_TRADE_QUEUE_NAME转发监听队列,负责将拥堵在拥堵队列中的消息转发到业务处理消息监听逻辑中
SEND_MAIL_DELAY_DEAD_LETTER_QUEUE_NAME消息拥堵队列,时间结束前消息会拥堵在此,消息时间结束后会将消息转发到业务逻辑处理队列中
QUEUE_SEND_MAIL_DELAY业务处理队列,及发邮件监听消息,消息拥堵结束后会将消息发送到此处
),
延迟消息消息体封装:(DLXMessage:数据传递)
延迟消息发送:(SendMailDelayService:将业务逻辑中设定时间等参数发送到拥堵队列中SEND_MAIL_DELAY_DEAD_LETTER_QUEUE_NAME)
延迟消息转发监听:(SendMailDelayTradeReceiver:拥堵队列时间结束后,会被该监听器监听,监听队列名称SEND_MAIL_DELAY_REPEAT_TRADE_QUEUE_NAME,监听后将消息中数据转发到业务处理消息队列中message.getQueueName(),通常情况下该队列名称是动态的,及我们在入口处传递的,并将此队列名称放到消息体中,该队列名称一般为消息业务处理逻辑的消息名称:发邮件)
延迟消息业务处理监听 :(QUEUE_SEND_MAIL_DELAY:监听转发监听器推过来的消息,处理业务逻辑)
1.业务层代码:生成将要发送的邮件在草稿箱,获取定时时间等基础参数
if(!StringUtils.isEmpty(mailDto.getDelayTime())){
res = sendMailByMQService.sendDelayMailByMQ(mail.getId(),mailDto.getFollowId(),sdf.parse(mailDto.getDelayTime()));
System.err.println("延迟:"+mail.getId());
System.err.println("延迟:"+mailDto.getDelayTime());
}else{
res = sendMailByMQService.sendMailByMQ(mail.getId(),mailDto.getFollowId());
System.err.println("不延迟:"+mailDto.getDelayTime());
}
2.业务逻辑:封装方法,像指定消息封装设定时间
package com.shallnew.wmallgenie.rabbitmq.sender;
import com.alibaba.fastjson.JSONObject;
import com.shallnew.wmallgenie.dto.MailDto;
import com.shallnew.wmallgenie.dto.R;
import com.shallnew.wmallgenie.rabbitmq.config.SendMailByMQConfig;
import com.shallnew.wmallgenie.rabbitmq.config.SendMailConfig;
import com.shallnew.wmallgenie.rabbitmq.config.SendMailDelayConfig;
import com.shallnew.wmallgenie.rabbitmq.message.DelayMessageStruct;
import com.shallnew.wmallgenie.rabbitmq.message.MessageStruct;
import com.shallnew.wmallgenie.utils.StringConvertUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.text.SimpleDateFormat;
import java.util.Date;
@Component
@Slf4j
public class SendMailByMQService {
@Autowired
private AmqpTemplate rabbitTemplate;
@Autowired
private SendMailDelayService sendMailDelayService;
public R sendMailByMQ(Long id,String followId) {
MessageStruct messageStruct = new MessageStruct();
messageStruct.setId(id);
messageStruct.setFollowId(followId);
this.rabbitTemplate.convertAndSend(SendMailByMQConfig.SEND_MAILBYMQ_EXCHANGENAME, SendMailByMQConfig.SEND_MAILBYMQ_ROUTING_KEY, messageStruct);
return R.ok();
}
public R sendDelayMailByMQ(Long id,String followId,Date delayTime) {
DelayMessageStruct delayMessageStruct = new DelayMessageStruct();
delayMessageStruct.setId(id);
delayMessageStruct.setFollowId(followId);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
long time = delayTime.getTime()-new Date().getTime();
delayMessageStruct.setDelayTime(time);
String message = JSONObject.toJSONString(delayMessageStruct);
sendMailDelayService.sendMessage(SendMailDelayConfig.SEND_MAIL_DELAY_EXCHANGE,SendMailDelayConfig.QUEUE_SEND_MAIL_DELAY, message, time);
//this.rabbitTemplate.convertAndSend(SendMailByMQConfig.SEND_MAILBYMQ_EXCHANGENAME, SendMailByMQConfig.SEND_MAILBYMQ_ROUTING_KEY, delayMessageStruct);
return R.ok();
}
}
3.MQ延迟消息异步发送
package com.shallnew.wmallgenie.rabbitmq.sender;
import com.alibaba.fastjson.JSON;
import com.shallnew.wmallgenie.rabbitmq.config.MailDelayConfig;
import com.shallnew.wmallgenie.rabbitmq.config.SendMailDelayConfig;
import com.shallnew.wmallgenie.rabbitmq.message.DLXMessage;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.AmqpException;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessagePostProcessor;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
@Slf4j
public class SendMailDelayService {
@Autowired
private RabbitTemplate rabbitTemplate;
/**
* 延迟发送消息到队列
* @param queueName 队列名称
* @param message 消息内容
* @param times 延迟时间 单位毫秒
*/
public void sendMessage(String exchange,String queueName, String message, long times) {
//消息发送到死信队列上,当消息超时时,会发生到转发队列上,转发队列根据下面封装的queueName,把消息转发的指定队列上
//发送前,把消息进行封装,转发时应转发到指定 queueName 队列上
DLXMessage dlxMessage = new DLXMessage(SendMailDelayConfig.SEND_MAIL_DELAY_EXCHANGE,queueName,message,times);
MessagePostProcessor processor = new MessagePostProcessor(){
@Override
public Message postProcessMessage(Message message) throws AmqpException {
message.getMessageProperties().setExpiration(times + "");
return message;
}
};
rabbitTemplate.convertAndSend(exchange,
SendMailDelayConfig.SEND_MAIL_DELAY_DEAD_LETTER_QUEUE_NAME, JSON.toJSONString(dlxMessage), processor);
}
}
消息体封装类:
package com.shallnew.wmallgenie.rabbitmq.message;
import java.io.Serializable;
public class DLXMessage implements Serializable {
private static final long serialVersionUID = 9956432152000L;
private String exchange;
private String queueName;
private String content;
private long times;
public DLXMessage() {
super();
}
public DLXMessage(String queueName, String content, long times) {
super();
this.queueName = queueName;
this.content = content;
this.times = times;
}
public DLXMessage(String exchange, String queueName, String content, long times) {
super();
this.exchange = exchange;
this.queueName = queueName;
this.content = content;
this.times = times;
}
public static long getSerialVersionUID() {
return serialVersionUID;
}
public String getExchange() {
return exchange;
}
public void setExchange(String exchange) {
this.exchange = exchange;
}
public String getQueueName() {
return queueName;
}
public void setQueueName(String queueName) {
this.queueName = queueName;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public long getTimes() {
return times;
}
public void setTimes(long times) {
this.times = times;
}
}
延迟消息config
package com.shallnew.wmallgenie.rabbitmq.config;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.DirectExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.HashMap;
import java.util.Map;
@Configuration
public class SendMailDelayConfig {
//exchange name
public static final String SEND_MAIL_DELAY_EXCHANGE = "exchange.send.mail.delay";
//DLX repeat QUEUE 死信接收转发队列,时间设置时用该队列接收
public static final String SEND_MAIL_DELAY_REPEAT_TRADE_QUEUE_NAME = "queue.send.mail.delay.repeat";
//TTL QUEUE 死信拥堵队列
public static final String SEND_MAIL_DELAY_DEAD_LETTER_QUEUE_NAME = "queue.send.mail.delay.dead";
//Hello :最终发消息/处理业务队列
public static final String QUEUE_SEND_MAIL_DELAY = "queue.send.mail.delay";
//信道配置
@Bean
public DirectExchange sendMailDelayExchange() {
return new DirectExchange(SEND_MAIL_DELAY_EXCHANGE, true, false);
}
/********************* 业务队列定义与绑定 hello 测试 *****************/
@Bean
public Queue sendMailDelayQueue() {
Queue queue = new Queue(QUEUE_SEND_MAIL_DELAY,true);
return queue;
}
@Bean
public Binding sendMailDelayBinding() {
//队列绑定到exchange上,再绑定好路由键
return BindingBuilder.bind(sendMailDelayQueue()).to(sendMailDelayExchange()).with(QUEUE_SEND_MAIL_DELAY);
}
/********************* 业务队列定义与绑定 hello 测试 *****************/
//下面是延迟队列的配置
//转发队列
@Bean
public Queue repeatTradeSendMailDelayQueue() {
Queue queue = new Queue(SEND_MAIL_DELAY_REPEAT_TRADE_QUEUE_NAME,true,false,false);
return queue;
}
//绑定转发队列
@Bean
public Binding repeatTradeSendMailDelayBinding() {
return BindingBuilder.bind(repeatTradeSendMailDelayQueue()).to(sendMailDelayExchange()).with(SEND_MAIL_DELAY_REPEAT_TRADE_QUEUE_NAME);
}
//死信队列 -- 消息在死信队列上堆积,消息超时时,会把消息转发到转发队列,转发队列根据消息内容再把转发到指定的队列上
@Bean
public Queue deadLetterSendMailDelayQueue() {
Map<String, Object> arguments = new HashMap<>();
arguments.put("x-dead-letter-exchange", SEND_MAIL_DELAY_EXCHANGE);
arguments.put("x-dead-letter-routing-key", SEND_MAIL_DELAY_REPEAT_TRADE_QUEUE_NAME);
//拥堵队列
Queue queue = new Queue(SEND_MAIL_DELAY_DEAD_LETTER_QUEUE_NAME,true,false,false,arguments);
return queue;
}
//绑定死信队列
@Bean
public Binding deadLetterSendMailDelayBinding() {
return BindingBuilder.bind(deadLetterSendMailDelayQueue()).to(sendMailDelayExchange()).with(SEND_MAIL_DELAY_DEAD_LETTER_QUEUE_NAME);
}
}
延迟消息监听:消息转发(时间结束后转发到业务处理类)
package com.shallnew.wmallgenie.rabbitmq.receiver;
import com.alibaba.fastjson.JSON;
import com.rabbitmq.client.Channel;
import com.shallnew.wmallgenie.rabbitmq.config.MailDelayConfig;
import com.shallnew.wmallgenie.rabbitmq.config.SendMailDelayConfig;
import com.shallnew.wmallgenie.rabbitmq.message.DLXMessage;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.AmqpHeaders;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.handler.annotation.Headers;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.util.Map;
@Component
@Slf4j
public class SendMailDelayTradeReceiver {
@Autowired
private RabbitTemplate rabbitTemplate;
//监听转发队列,有消息时,把消息转发到目标队列
@RabbitListener(queues = SendMailDelayConfig.SEND_MAIL_DELAY_REPEAT_TRADE_QUEUE_NAME)
public void sendMailDelayTradeMessage(String content, Channel channel, @Headers Map<String,Object> headers) {
try {
//此时,才把消息发送到指定队列,而实现延迟功能
DLXMessage message = JSON.parseObject(content, DLXMessage.class);
System.err.println("将消息转发给其他队列"+message.getQueueName());
rabbitTemplate.convertAndSend(SendMailDelayConfig.SEND_MAIL_DELAY_EXCHANGE,message.getQueueName(), message.getContent());
System.err.println("转发到:"+message.getQueueName());
Long deliveryTay = (Long)headers.get(AmqpHeaders.DELIVERY_TAG);
channel.basicAck(deliveryTay,false);
} catch (IOException e) {
e.printStackTrace();
Long deliveryTay = (Long)headers.get(AmqpHeaders.DELIVERY_TAG);
try {
channel.basicAck(deliveryTay,false);
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
}
延迟消息监听,业务处理(发邮件)
package com.shallnew.wmallgenie.rabbitmq.receiver;
import com.alibaba.fastjson.JSON;
import com.rabbitmq.client.Channel;
import com.shallnew.wmallgenie.config.MatuConfig;
import com.shallnew.wmallgenie.contants.LocusEnum;
import com.shallnew.wmallgenie.dao.CsMsgPushMapper;
import com.shallnew.wmallgenie.dao.MailAccountMapper;
import com.shallnew.wmallgenie.dao.MailContentMapper;
import com.shallnew.wmallgenie.dao.MailFollowMapper;
import com.shallnew.wmallgenie.entity.*;
import com.shallnew.wmallgenie.rabbitmq.config.MailDelayConfig;
import com.shallnew.wmallgenie.rabbitmq.config.SendMailDelayConfig;
import com.shallnew.wmallgenie.rabbitmq.message.DelayMessageStruct;
import com.shallnew.wmallgenie.rabbitmq.sender.AnnaylizeOssDirSpaceService;
import com.shallnew.wmallgenie.rabbitmq.sender.ReceiverMailByOneAccountService;
import com.shallnew.wmallgenie.service.*;
import com.shallnew.wmallgenie.shiro.utils.DateUtils;
import com.shallnew.wmallgenie.utils.DownLoadUrlUtils;
import com.shallnew.wmallgenie.utils.RSAUtils;
import com.shallnew.wmallgenie.utils.mail.MailMQUtils;
import com.shallnew.wmallgenie.utils.mail.MailUtils;
import com.shallnew.wmallgenie.utils.xss.UUIDUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.AmqpHeaders;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.Message;
import org.springframework.messaging.handler.annotation.Headers;
import org.springframework.stereotype.Component;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context;
import javax.mail.internet.MimeMessage;
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.*;
@Component
@Slf4j
public class SendMailDelayReceiver {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private MailContentMapper mailContentMapper;
@Autowired
private MailAccountMapper accountMapper;
@Autowired
private MailFollowMapper followMapper;
@Autowired
private MailAttachmentService attachmentService;
@Autowired
private TemplateEngine templateEngine;
@Autowired
private CustomerService customerService;
@Autowired
private MailAccountService accountService;
@Autowired
private SupplierService supplierService;
@Autowired
private CsGroupService groupService;
@Autowired
private AnnaylizeOssDirSpaceService annaylizeOssDirSpaceService;
@Autowired
private CustomLocusService customLocusService;
@Autowired
private CustomCommunityService customCommunityService;
@Autowired
private CsUserService csUserService;
@Autowired
private ReceiverMailByOneAccountService receiverMailByOneAccountService;
@Autowired
private CsMsgPushMapper msgPushMapper;
@Autowired
private SupplierContactService supplierContactService;
/**
* 延迟消息
*/
@RabbitListener(queues = SendMailDelayConfig.QUEUE_SEND_MAIL_DELAY)
public void delayMessage(Message msg, Channel channel, @Headers Map<String,Object> headers) {
DelayMessageStruct delayMessageStruct = JSON.parseObject(msg.getPayload()+"", DelayMessageStruct.class);
Long id = delayMessageStruct.getId();
MailContent mailDto = mailContentMapper.selectByPrimaryKey(id);
List<MailAttachment> attachmentList = attachmentService.queryByMail(id);
List<Map> list = new ArrayList<>();
for (MailAttachment mailAttachment:attachmentList
) {
Map map = new HashMap();
map.put("fileName",mailAttachment.getFilename());
map.put("url",mailAttachment.getAttachmentUrl());
list.add(map);
}
MailAccountWithBLOBs accountEntity = accountMapper.queryMailPassword(mailDto.getFromAccount(),null,mailDto.getUserId());//查找发件人授权码
if(null == accountEntity){
return ;
}
String pwd = accountEntity.getPassword();//发件人授权码(未解密)
String privateKey = accountEntity.getPrivateKey();//解密秘钥
String target = RSAUtils.decryptByPrivateKey(pwd, privateKey);
String emailPassword = target;
String emailSMTPHost = accountEntity.getServerAddrS();//发件服务器地址
Short serverSSL = accountEntity.getServerSslS();//判断是否需要SSL加密
Short serverStartTLS = accountEntity.getServerStarttls();
//获取正文
String content = DownLoadUrlUtils.downLoadMailContent(mailDto.getContentUrl());
content = content.replaceAll("dt2b://","http://").replaceAll("dt2bs://","https://").replaceAll("@‘","");
//发送邮件加像素
String uuId = UUIDUtil.getUUID();
String sendContent = content +"<img style=\"display:none;width:0px;height:0\" name=\"MAILPIXEL\" src=\""+ MatuConfig.pixelprefix+"?id="+uuId+"&time="+new Date().getTime()+"\">";
long dateTime = new Date().getTime();
sendContent = sendContent +"<span style=\"display:none;\" id=\"SEND_MATU"+dateTime+"SEND_MATU"+"\" ></span>";//用于imap收邮件标记解析
//将所有地址图片上传到邮件
//sendContent= sendContent+ StringConstant.SENDMAILJSBODY.replace("UUID",uuId);
mailDto.setContent(sendContent);
try {
MimeMessage message = MailMQUtils.createMimeMessage(mailDto.getFromAccount(),mailDto.getFromMail(), mailDto.getToMail(), mailDto.getWcc(), mailDto.getBcc(), mailDto.getSubject(), mailDto.getContent(), emailPassword, emailSMTPHost, serverSSL, serverStartTLS, list);
//查询是否管理全部供应商
List<Integer> groupIdList = new ArrayList<>();
List<Integer> supplierTypeList = new ArrayList<>();
List<CsGroup> groupList = groupService.queryByUserGroup(mailDto.getUserId());
for(CsGroup csGroup:groupList) {
groupIdList.add(csGroup.getId());
if (csGroup.getGroupName().equalsIgnoreCase("管理员")) {
supplierTypeList.add(1);
break;
}else if(csGroup.getSupplierType().equalsIgnoreCase("1")){
supplierTypeList.add(Integer.valueOf(csGroup.getSupplierType()));
break;
}else{
supplierTypeList.add(Integer.valueOf(csGroup.getSupplierType()));
}
}
Map param = new HashMap<>();
if(supplierTypeList.contains(0)){
param.put("createUserId",mailDto.getUserId());
}
//1 查询所有 2 自定义 3 普通供应商 4 物流供应商 5 个人 + 自定义 6 个人 + 普通供应商 7 个人 + 物流供应商
//8 普通 + 物流 9 普通 + 自定义 10 物流 + 自定义 11 普通 + 个人 + 自定义 12 物流 + 个人 + 自定义
if (supplierTypeList.contains(1)) { // 所有
param.put("status",1);
param.put("companyId", mailDto.getCompanyId());
} else if (supplierTypeList.contains(3) && supplierTypeList.contains(4)) { // 普通 + 物流
param.put("status",1);
param.put("companyId", mailDto.getCompanyId());
} else if (supplierTypeList.contains(3) && supplierTypeList.contains(2)) { // 普通 + 自定义
param.put("status",9);
param.put("companyId", mailDto.getCompanyId());
param.put("groupId", groupIdList);
} else if (supplierTypeList.contains(4) && supplierTypeList.contains(2)) { // 物流 + 自定义
param.put("status",10);
param.put("companyId", mailDto.getCompanyId());
param.put("groupId", groupIdList);
} else if(supplierTypeList.contains(0) && supplierTypeList.contains(2)) { // 个人 + 自定义
param.put("status",5);
param.put("createUserId",mailDto.getUserId());
param.put("groupId",groupIdList);
} else if(supplierTypeList.contains(0) && supplierTypeList.contains(3)) { // 个人 + 普通
param.put("status",6);
param.put("createUserId",mailDto.getUserId());
param.put("groupId",groupIdList);
} else if(supplierTypeList.contains(0) && supplierTypeList.contains(4)) { // 个人 + 物流
param.put("status",7);
param.put("createUserId",mailDto.getUserId());
param.put("groupId",groupIdList);
} else {
if (supplierTypeList.contains(3)) {
param.put("status",3);
param.put("companyId", mailDto.getCompanyId());
} else if (supplierTypeList.contains(4)) {
param.put("status",4);
param.put("companyId", mailDto.getCompanyId());
} else if (supplierTypeList.contains(2)) {
param.put("status",2);
param.put("companyId", mailDto.getCompanyId());
param.put("groupId", groupIdList);
} else {
param.put("status",0);
param.put("companyId", mailDto.getCompanyId());
param.put("createUserId", mailDto.getUserId());
}
}
if(mailDto.getUserId() != null && mailDto.getUserId() != 0) {
param.put("userId", mailDto.getUserId());
}
param.put("companyId",mailDto.getCompanyId());
List<String> supplierMailsRes = supplierContactService.listByUserId(param);
List<String> supplierMails = new ArrayList<>();
for (String s1:supplierMailsRes
) {
if(!StringUtils.isEmpty(s1)){
supplierMails.add(s1.toLowerCase());
}
}
//判断是否为imap收邮件是的发邮件不需要保存本地数据
//收邮件方式
if(accountEntity.getServerType() == 1) {//Imap
mailDto.setContent(content);
//发送保存
String uuid = UUIDUtil.getUUID();
Date now = new Date();
List<String> toMailList = new ArrayList();
List<String> tom = Arrays.asList(mailDto.getToMail().split(","));
toMailList = new ArrayList(tom);
List<String> wccMail = Arrays.asList(mailDto.getWcc().split(","));
List<String> wccMailList = new ArrayList(wccMail);
List<String> bccMail = Arrays.asList(mailDto.getBcc().split(","));
List<String> bccMailList = new ArrayList(bccMail);
List<String> finalToMailList = toMailList;
wccMailList.forEach(s -> finalToMailList.add(s));
bccMailList.forEach(s -> finalToMailList.add(s));
//是否归并标记
boolean istogether = false;
//内部联系人
List<String> userMails = accountService.queryByCompany(mailDto.getCompanyId());
List<String> innerMails = new ArrayList<>();
for (String s : userMails
) {
if (!StringUtils.isEmpty(s)) {
innerMails.add(s.toLowerCase());
}
}
//供应商
//查询角色
//List<Integer> groupIdList = new ArrayList<>();
List<CsGroup> group = groupService.queryByUserGroup(mailDto.getUserId());
group.forEach(csGroup -> groupIdList.add(csGroup.getId()));
List<String> supplierContactList = supplierService.queryShareSupplierMailAccountList(groupIdList);
List<String> supplierContactMails = new ArrayList<>();
for (String s : supplierContactList
) {
if (!StringUtils.isEmpty(s)) {
supplierContactMails.add(s.toLowerCase());
}
}
String hContent = "";
//把邮件保存到数据库
MailContent mailEntity = new MailContent();
Set<String> s = new HashSet();
for (String toMail:finalToMailList
) {
s.add(toMail);
}
for (String toMail : s) {
istogether = false;//默认不归并
if (StringUtils.isEmpty(toMail)) {
continue;
}
String toAccount;
Integer toStart = mailDto.getToMail().indexOf("<") + 1;//寻找开始下标
Integer toEnd = mailDto.getToMail().indexOf(">");//寻找结束下标
if (toStart != -1 && toEnd != -1) {
toAccount = toMail.substring(toStart, toEnd);
} else {
toAccount = toMail;
}
List<Map<String, Object>> myshareList = customerService.queryMySharingCustomerByUserIdCompanyIdAndMail(toAccount, mailDto.getUserId(), mailDto.getCompanyId());
//我的客户
//List<String> cusList = customerContactService.queryCustomerMailByUserIdAndMail(toAccount,mailDto.getUserId());
if (myshareList.size() > 0 || innerMails.contains(toMail.toLowerCase()) || supplierContactMails.contains(toMail.toLowerCase()) || supplierMails.contains(toMail.toLowerCase())) {
istogether = true;//表示需要归并
}
mailEntity = new MailContent();
mailEntity.setUserId(accountEntity.getUserId());
mailDto.setUserId(accountEntity.getUserId());
mailEntity.setFromMail(mailDto.getFromMail());
mailEntity.setFromAccount(mailDto.getFromAccount());
mailEntity.setBelongAccount(mailDto.getBelongAccount());//邮件归属记录便于查询
mailEntity.setCompanyId(mailDto.getCompanyId());
/*Integer toStart = mailDto.getToMail().indexOf("<") + 1;//寻找开始下标
Integer toEnd = mailDto.getToMail().indexOf(">");//寻找结束下标
String toAccount;*/
if (toStart != -1 && toEnd != -1) {
toAccount = toMail.substring(toStart, toEnd);
} else {
toAccount = toMail;
}
//邮件发送时标记标签以及颜色
mailEntity.setTagName(mailDto.getTagName());
mailEntity.setTagColor(mailDto.getTagColor());
mailEntity.setToAccount(toAccount);
if (toMail != null && !toMail.equals("")) {
mailEntity.setToMail(mailDto.getToMail());
}
mailEntity.setFlowCell((short) 0);
mailEntity.setSubject(mailDto.getSubject());
if (mailDto.getBcc() != null) {
mailEntity.setBcc(mailDto.getBcc());
}
if (mailDto.getWcc() != null) {
mailEntity.setWcc(mailDto.getWcc());
}
mailEntity.setIsSend((short) 1);
mailEntity.setContent(null);
String fileName = UUIDUtil.getUUID() + "-" + new Date().getTime() + ".txt";
InputStream is = new ByteArrayInputStream(content.getBytes("UTF-8"));
//InputStream is = bodyPart.getInputStream();
//ByteArrayInputStream stream= new ByteArrayInputStream(str.getBytes());
BufferedInputStream bis = new BufferedInputStream(is);
//R path = OssUpload.upload(bis, company.getNameEn().replaceAll(" ","")+"/mail/" + fileName);
//http://dt2b.oss-cn-hangzhou.aliyuncs.com/
mailEntity.setContentUrl(mailDto.getContentUrl());
String contentText = mailDto.getContent();
String flowFlag = "";
String mailFlag = "";
String lastMailFlag = "";
String gjmail = "";
if (contentText.indexOf("class=\"MT_MID_") >= 0) {
String[] contents = contentText.split("class=\"MT_MID_");
String[] flags = contents[contents.length - 1].split("_");
mailFlag = flags[0];
flowFlag = flags[1];
lastMailFlag = flags[2].trim();
mailEntity.setMailFlag(mailFlag.trim());
mailEntity.setMailLastflag(Long.valueOf(flags[2].trim()));
String[] gjmailArra = flags[3].split("\"");//可能是下次跟进,也可能是下次跟进时间加邮箱
gjmail = gjmailArra[0].trim();
} else {
}
//TODO 邮件大小为-1,错误
mailEntity.setMailSize("" + message.getSize());
if (list != null && list.size() > 0) {
mailEntity.setIsEnclose(1);
} else {
mailEntity.setIsEnclose(0);
}
mailEntity.setSendTime(now);
mailEntity.setReceiveTime(now);
if (null != mailDto.getWcc() && !mailDto.getWcc().isEmpty()) {
mailEntity.setWcc(mailDto.getWcc());
}
if (null != mailDto.getBcc() && !mailDto.getBcc().isEmpty()) {
mailEntity.setBcc(mailDto.getBcc());
}
mailEntity.setFlagRead((short) 1);
mailEntity.setType((short) 1);
mailEntity.setDeleteStatus(0);
if (istogether) {
mailEntity.setBoxId(-1L);
} else {
mailEntity.setBoxId(3L);//已发箱
}
String msgId = message.getMessageID();
int startIndex = msgId.indexOf("<");
int endIndex = msgId.indexOf(">");
//mailEntity.setMsgId(msgId.substring(startIndex,endIndex));
mailEntity.setMsgId(uuid);
mailEntity.setSendStatus(1);//发送成功
mailEntity.setSendmailFlag(""+dateTime);
mailContentMapper.insertSelective(mailEntity);
//发邮件加像素记录
//uuId像素标记保存
//异步分析磁盘
CustomLocus customLocus = new CustomLocus();
customLocus.setCreateTime(new Date());
customLocus.setSourceId(mailEntity.getId());
customLocus.setUid(uuId);
customLocus.setType(LocusEnum.MP.toString());
customLocus.setIsRead(false);//设置未读
customLocusService.insertSelective(customLocus);
//跟进时间到期提醒消息
hContent = "<div><p><span>主题:</span><span>" + mailEntity.getSubject() + "</span></p><p><span>发件时间:</span><span>" + DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,mailEntity.getSendTime()) + "</span></p><p><span>收件人:</span><span>" + mailEntity.getToMail() +
(mailEntity.getWcc()==null?"":(" "+mailEntity.getWcc()))+(mailEntity.getBcc()==null?"":(" "+mailEntity.getBcc()))+"</span></p></div>";//客户交流社区里的正文
//添加标签
if (delayMessageStruct.getFollowId() != null && !delayMessageStruct.getFollowId().equals("")) {
SimpleDateFormat dateformat = new SimpleDateFormat("yyyy-MM-dd");
MailFollow follow = new MailFollow();
follow.setMailId(mailEntity.getId());
follow.setTagId(Long.parseLong(delayMessageStruct.getFollowId()));
follow.setFollowTime(new Date());
if (!StringUtils.isEmpty(mailDto.getNextFollowTime())) {
follow.setNextFollowTime(dateformat.parse(mailDto.getNextFollowTime()));
}
if (!StringUtils.isEmpty(flowFlag)) {
//将mailFlag相同的id跟踪记录删除
followMapper.deleteMailFollowMailFlagAndId(mailFlag, mailEntity.getId(), mailDto.getUserId());
}
followMapper.insertSelective(follow);
}
//保存附件
if (list != null && list.size() > 0) {
for (Map map : list) {
MailAttachment attachment = new MailAttachment();
attachment.setMailId(mailEntity.getId());
attachment.setInline(false);
attachment.setAttachmentUrl(map.get("url").toString());
attachment.setFilename(map.get("fileName").toString());
attachment.setFilesize(map.get("fileSize") == null ? "0" : map.get("fileSize").toString());
attachment.setUserId(mailEntity.getUserId());
attachment.setUploadTime(new Date());
attachmentService.insertSelective(attachment);
}
}
if(myshareList.size()>0){
//存入客户社区:客户访问
CsUser csUser = csUserService.queryByuserid(mailDto.getUserId());
CustomCommunity customCommunity = new CustomCommunity();
customCommunity.setTittle("【" + csUser.getRealname() + "】于" +DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,mailEntity.getSendTime()) + "向" + mailEntity.getToAccount() + "发送邮件");
//String htmlContent = "<div><p><span>主题:</span><span>" + mailEntity.getSubject() + "</span></p><p><span>发件人:</span><span>" + mailEntity.getFromAccount() + "</span></p><p><span>收件人:</span><span>" + mailEntity.getToAccount() + "</span></p></div>";//客户交流社区里的正文
String htmlContent = "主题:" + mailEntity.getSubject() + " 发件人:" + mailEntity.getFromAccount() + " 收件人:" + mailEntity.getToMail();//客户交流社区里的正文
if(!StringUtils.isEmpty(mailEntity.getWcc())){
htmlContent = htmlContent+" 抄送:"+mailEntity.getWcc();
}
customCommunity.setContent(htmlContent);
customCommunity.setSourceId(mailEntity.getId());
customCommunity.setType(LocusEnum.MS.toString());
customCommunity.setCreateTime(mailEntity.getSendTime());
customCommunity.setUserId(mailEntity.getUserId());
customCommunityService.insertSelective(customCommunity);
}
}
if(mailDto.getNextFollowTime()!=null){
CsMsgPush csMsgPush = new CsMsgPush();
hContent = "主题:"+mailEntity.getSubject() +",发件时间:"+DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,mailEntity.getSendTime())+",收件人:"+mailEntity.getToMail();
csMsgPush.setId(UUIDUtil.getUUID());
csMsgPush.setMsgContent(hContent);
csMsgPush.setMsgSendTime(DateUtils.parseDate(mailDto.getNextFollowTime()));
csMsgPush.setMsgStatus((short)0);
csMsgPush.setCreateTime(new Date());
csMsgPush.setMsgType(4);//邮件
csMsgPush.setUserId(mailEntity.getUserId());
csMsgPush.setSourceId(""+mailEntity.getId());
msgPushMapper.insertSelective(csMsgPush);
}
annaylizeOssDirSpaceService.annaylizeOssDirSpace("" + message.getSize(), mailDto.getCompanyId());
mailContentMapper.deleteByPrimaryKey(id);
//邮件发送后启动收邮件
receiverMailByOneAccountService.receiverMailByOneAccount(mailDto.getFromAccount(),mailDto.getCompanyId(),accountEntity.getUserId());
}else {
mailDto.setContent(content);
//发送保存
String uuid = UUIDUtil.getUUID();
Date now = new Date();
List<String> toMailList = new ArrayList();
List<String> tom = Arrays.asList(mailDto.getToMail().split(","));
toMailList = new ArrayList(tom);
List<String> wccMail = Arrays.asList(mailDto.getWcc().split(","));
List<String> wccMailList = new ArrayList(wccMail);
List<String> bccMail = Arrays.asList(mailDto.getBcc().split(","));
List<String> bccMailList = new ArrayList(bccMail);
List<String> finalToMailList = toMailList;
wccMailList.forEach(s -> finalToMailList.add(s));
bccMailList.forEach(s -> finalToMailList.add(s));
//是否归并标记
boolean istogether = false;
//内部联系人
List<String> userMails = accountService.queryByCompany(mailDto.getCompanyId());
List<String> innerMails = new ArrayList<>();
for (String s : userMails
) {
if (!StringUtils.isEmpty(s)) {
innerMails.add(s.toLowerCase());
}
}
//供应商
//查询角色
//List<Integer> groupIdList = new ArrayList<>();
List<CsGroup> group = groupService.queryByUserGroup(mailDto.getUserId());
group.forEach(csGroup -> groupIdList.add(csGroup.getId()));
List<String> supplierContactList = supplierService.queryShareSupplierMailAccountList(groupIdList);
List<String> supplierContactMails = new ArrayList<>();
for (String s : supplierContactList
) {
if (!StringUtils.isEmpty(s)) {
supplierContactMails.add(s.toLowerCase());
}
}
String hContent = "";
//把邮件保存到数据库
MailContent mailEntity = new MailContent();
Set<String> s = new HashSet();
for (String toMail:finalToMailList
) {
s.add(toMail);
}
for (String toMail : s) {
istogether = false;//默认不归并
if (StringUtils.isEmpty(toMail)) {
continue;
}
String toAccount;
Integer toStart = mailDto.getToMail().indexOf("<") + 1;//寻找开始下标
Integer toEnd = mailDto.getToMail().indexOf(">");//寻找结束下标
if (toStart != -1 && toEnd != -1) {
toAccount = toMail.substring(toStart, toEnd);
} else {
toAccount = toMail;
}
List<Map<String, Object>> myshareList = customerService.queryMySharingCustomerByUserIdCompanyIdAndMail(toAccount, mailDto.getUserId(), mailDto.getCompanyId());
//我的客户
//List<String> cusList = customerContactService.queryCustomerMailByUserIdAndMail(toAccount,mailDto.getUserId());
if (myshareList.size() > 0 || innerMails.contains(toMail.toLowerCase()) || supplierContactMails.contains(toMail.toLowerCase()) || supplierMails.contains(toMail.toLowerCase())) {
istogether = true;//表示需要归并
}
mailEntity = new MailContent();
mailEntity.setUserId(accountEntity.getUserId());
mailDto.setUserId(accountEntity.getUserId());
mailEntity.setFromMail(mailDto.getFromMail());
mailEntity.setFromAccount(mailDto.getFromAccount());
mailEntity.setBelongAccount(mailDto.getBelongAccount());//邮件归属记录便于查询
mailEntity.setCompanyId(mailDto.getCompanyId());
/*Integer toStart = mailDto.getToMail().indexOf("<") + 1;//寻找开始下标
Integer toEnd = mailDto.getToMail().indexOf(">");//寻找结束下标
String toAccount;*/
if (toStart != -1 && toEnd != -1) {
toAccount = toMail.substring(toStart, toEnd);
} else {
toAccount = toMail;
}
//邮件发送时标记标签以及颜色
mailEntity.setTagName(mailDto.getTagName());
mailEntity.setTagColor(mailDto.getTagColor());
mailEntity.setToAccount(toAccount);
if (toMail != null && !toMail.equals("")) {
mailEntity.setToMail(mailDto.getToMail());
}
mailEntity.setFlowCell((short) 0);
mailEntity.setSubject(mailDto.getSubject());
if (mailDto.getBcc() != null) {
mailEntity.setBcc(mailDto.getBcc());
}
if (mailDto.getWcc() != null) {
mailEntity.setWcc(mailDto.getWcc());
}
mailEntity.setIsSend((short) 1);
mailEntity.setContent(null);
String fileName = UUIDUtil.getUUID() + "-" + new Date().getTime() + ".txt";
InputStream is = new ByteArrayInputStream(content.getBytes("UTF-8"));
//InputStream is = bodyPart.getInputStream();
//ByteArrayInputStream stream= new ByteArrayInputStream(str.getBytes());
BufferedInputStream bis = new BufferedInputStream(is);
//R path = OssUpload.upload(bis, company.getNameEn().replaceAll(" ","")+"/mail/" + fileName);
//http://dt2b.oss-cn-hangzhou.aliyuncs.com/
mailEntity.setContentUrl(mailDto.getContentUrl());
String contentText = mailDto.getContent();
String flowFlag = "";
String mailFlag = "";
String lastMailFlag = "";
String gjmail = "";
if (contentText.indexOf("class=\"MT_MID_") >= 0) {
String[] contents = contentText.split("class=\"MT_MID_");
String[] flags = contents[contents.length - 1].split("_");
mailFlag = flags[0];
flowFlag = flags[1];
lastMailFlag = flags[2].trim();
mailEntity.setMailFlag(mailFlag.trim());
mailEntity.setMailLastflag(Long.valueOf(flags[2].trim()));
String[] gjmailArra = flags[3].split("\"");//可能是下次跟进,也可能是下次跟进时间加邮箱
gjmail = gjmailArra[0].trim();
} else {
}
//TODO 邮件大小为-1,错误
mailEntity.setMailSize("" + message.getSize());
if (list != null && list.size() > 0) {
mailEntity.setIsEnclose(1);
} else {
mailEntity.setIsEnclose(0);
}
mailEntity.setSendTime(now);
mailEntity.setReceiveTime(now);
if (null != mailDto.getWcc() && !mailDto.getWcc().isEmpty()) {
mailEntity.setWcc(mailDto.getWcc());
}
if (null != mailDto.getBcc() && !mailDto.getBcc().isEmpty()) {
mailEntity.setBcc(mailDto.getBcc());
}
mailEntity.setFlagRead((short) 1);
mailEntity.setType((short) 1);
mailEntity.setDeleteStatus(0);
if (istogether) {
mailEntity.setBoxId(-1L);
} else {
mailEntity.setBoxId(3L);//已发箱
}
String msgId = message.getMessageID();
int startIndex = msgId.indexOf("<");
int endIndex = msgId.indexOf(">");
//mailEntity.setMsgId(msgId.substring(startIndex,endIndex));
mailEntity.setMsgId(uuid);
mailEntity.setSendStatus(1);//发送成功
mailContentMapper.insertSelective(mailEntity);
//发邮件加像素记录
//uuId像素标记保存
//异步分析磁盘
CustomLocus customLocus = new CustomLocus();
customLocus.setCreateTime(new Date());
customLocus.setSourceId(mailEntity.getId());
customLocus.setUid(uuId);
customLocus.setType(LocusEnum.MP.toString());
customLocus.setIsRead(false);//设置未读
customLocusService.insertSelective(customLocus);
//跟进时间到期提醒消息
hContent = "<div><p><span>主题:</span><span>" + mailEntity.getSubject() + "</span></p><p><span>发件时间:</span><span>" + DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,mailEntity.getSendTime()) + "</span></p><p><span>收件人:</span><span>" + mailEntity.getToMail() +
(mailEntity.getWcc()==null?"":(" "+mailEntity.getWcc()))+(mailEntity.getBcc()==null?"":(" "+mailEntity.getBcc()))+"</span></p></div>";//客户交流社区里的正文
//添加标签
if (delayMessageStruct.getFollowId() != null && !delayMessageStruct.getFollowId().equals("")) {
SimpleDateFormat dateformat = new SimpleDateFormat("yyyy-MM-dd");
MailFollow follow = new MailFollow();
follow.setMailId(mailEntity.getId());
follow.setTagId(Long.parseLong(delayMessageStruct.getFollowId()));
follow.setFollowTime(new Date());
if (!StringUtils.isEmpty(mailDto.getNextFollowTime())) {
follow.setNextFollowTime(dateformat.parse(mailDto.getNextFollowTime()));
}
if (!StringUtils.isEmpty(flowFlag)) {
//将mailFlag相同的id跟踪记录删除
followMapper.deleteMailFollowMailFlagAndId(mailFlag, mailEntity.getId(), mailDto.getUserId());
}
followMapper.insertSelective(follow);
}
//保存附件
if (list != null && list.size() > 0) {
for (Map map : list) {
MailAttachment attachment = new MailAttachment();
attachment.setMailId(mailEntity.getId());
attachment.setInline(false);
attachment.setAttachmentUrl(map.get("url").toString());
attachment.setFilename(map.get("fileName").toString());
attachment.setFilesize(map.get("fileSize") == null ? "0" : map.get("fileSize").toString());
attachment.setUserId(mailEntity.getUserId());
attachment.setUploadTime(new Date());
attachmentService.insertSelective(attachment);
}
}
if(myshareList.size()>0){
//存入客户社区:客户访问
CsUser csUser = csUserService.queryByuserid(mailDto.getUserId());
CustomCommunity customCommunity = new CustomCommunity();
customCommunity.setTittle("【" + csUser.getRealname() + "】于" +DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,mailEntity.getSendTime()) + "向" + mailEntity.getToAccount() + "发送邮件");
//String htmlContent = "<div><p><span>主题:</span><span>" + mailEntity.getSubject() + "</span></p><p><span>发件人:</span><span>" + mailEntity.getFromAccount() + "</span></p><p><span>收件人:</span><span>" + mailEntity.getToAccount() + "</span></p></div>";//客户交流社区里的正文
String htmlContent = "主题:" + mailEntity.getSubject() + " 发件人:" + mailEntity.getFromAccount() + " 收件人:" + mailEntity.getToMail();//客户交流社区里的正文
if(!StringUtils.isEmpty(mailEntity.getWcc())){
htmlContent = htmlContent+" 抄送:"+mailEntity.getWcc();
}
customCommunity.setContent(htmlContent);
customCommunity.setSourceId(mailEntity.getId());
customCommunity.setType(LocusEnum.MS.toString());
customCommunity.setCreateTime(mailEntity.getSendTime());
customCommunity.setUserId(mailEntity.getUserId());
customCommunityService.insertSelective(customCommunity);
}
}
if(mailDto.getNextFollowTime()!=null){
CsMsgPush csMsgPush = new CsMsgPush();
hContent = "主题:"+mailEntity.getSubject() +",发件时间:"+DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,mailEntity.getSendTime())+",收件人:"+mailEntity.getToMail();
csMsgPush.setId(UUIDUtil.getUUID());
csMsgPush.setMsgContent(hContent);
csMsgPush.setMsgSendTime(DateUtils.parseDate(mailDto.getNextFollowTime()));
csMsgPush.setMsgStatus((short)0);
csMsgPush.setCreateTime(new Date());
csMsgPush.setMsgType(4);//邮件
csMsgPush.setUserId(mailEntity.getUserId());
csMsgPush.setSourceId(""+mailEntity.getId());
msgPushMapper.insertSelective(csMsgPush);
}
annaylizeOssDirSpaceService.annaylizeOssDirSpace("" + message.getSize(), mailDto.getCompanyId());
mailContentMapper.deleteByPrimaryKey(id);
Long deliveryTay = (Long) headers.get(AmqpHeaders.DELIVERY_TAG);
channel.basicAck(deliveryTay, false);
}
} catch (Exception e) {
/* MailContent m = new MailContent();
m.setId(id);
m.setIsSyn((short)1);
mailContentMapper.updateByPrimaryKey(m);*/
sendTipMail(mailDto.getSubject(),mailDto.getFromMail(),new Date(),e.getMessage(),mailDto.getToMail());
//发送失败
MailContent m = new MailContent();
m.setId(id);
m.setSendStatus(0);//发送失败
mailContentMapper.updateByPrimaryKeySelective(m);
e.printStackTrace();
Long deliveryTay = (Long)headers.get(AmqpHeaders.DELIVERY_TAG);
try {
channel.basicAck(deliveryTay,false);
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
public void sendTipMail(String subject, String fromMail, Date date,String reson,String toMail) {
//CsCompany company = companyMapper.selectByPrimaryKey(companyId);
MailAccountWithBLOBs accountEntity = accountMapper.queryMailPassword(MatuConfig.servermail,null,null);//查找发件人授权码
if(accountEntity==null){
return;
}
String pwd = accountEntity.getPassword();//发件人授权码(未解密)
String privateKey = accountEntity.getPrivateKey();//解密秘钥
String target = RSAUtils.decryptByPrivateKey(pwd, privateKey);
String emailPassword = target;
String emailSMTPHost = accountEntity.getServerAddrS();//发件服务器地址
Short serverSSL = accountEntity.getServerSslS();//判断是否需要SSL加密
Short serverStartTLS = accountEntity.getServerStarttls();
List<Map> list = new ArrayList();
Context con = new Context(new Locale(""));
con.setVariable("subject", subject);
con.setVariable("date", date);
con.setVariable("reson", reson);
con.setVariable("toMail", toMail);
String html = this.templateEngine.process("mail/hello", con);
//创建并发送邮件
try {
MimeMessage message = MailUtils.createMimeMessage(MatuConfig.servermail,MatuConfig.servermail, fromMail, null, null, "系统发送邮件失败通知!", html, emailPassword, emailSMTPHost, serverSSL, serverStartTLS, list);
} catch (Exception e) {
e.printStackTrace();
}
}
}