RabbitMQ延迟队列实现定时发邮件
功能:前端設定時間,實現指定時間發送郵件。
技術: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 {@Autowiredprivate AmqpTemplate rabbitTemplate;@Autowiredprivate 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 {@Autowiredprivate 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(){@Overridepublic 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 namepublic 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";//信道配置@Beanpublic DirectExchange sendMailDelayExchange() {return new DirectExchange(SEND_MAIL_DELAY_EXCHANGE, true, false);}/********************* 業務隊列定義與綁定 hello 測試 *****************/@Beanpublic Queue sendMailDelayQueue() {Queue queue = new Queue(QUEUE_SEND_MAIL_DELAY,true);return queue;}@Beanpublic Binding sendMailDelayBinding() {//隊列綁定到exchange上,再綁定好路由鍵return BindingBuilder.bind(sendMailDelayQueue()).to(sendMailDelayExchange()).with(QUEUE_SEND_MAIL_DELAY);}/********************* 業務隊列定義與綁定 hello 測試 *****************///下面是延遲隊列的配置//轉發隊列@Beanpublic Queue repeatTradeSendMailDelayQueue() {Queue queue = new Queue(SEND_MAIL_DELAY_REPEAT_TRADE_QUEUE_NAME,true,false,false);return queue;}//綁定轉發隊列@Beanpublic Binding repeatTradeSendMailDelayBinding() {return BindingBuilder.bind(repeatTradeSendMailDelayQueue()).to(sendMailDelayExchange()).with(SEND_MAIL_DELAY_REPEAT_TRADE_QUEUE_NAME);}//死信隊列 -- 消息在死信隊列上堆積,消息超時時,會把消息轉發到轉發隊列,轉發隊列根據消息內容再把轉發到指定的隊列上@Beanpublic 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;}//綁定死信隊列@Beanpublic 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 {@Autowiredprivate 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 {@Autowiredprivate RabbitTemplate rabbitTemplate;@Autowiredprivate MailContentMapper mailContentMapper;@Autowiredprivate MailAccountMapper accountMapper;@Autowiredprivate MailFollowMapper followMapper;@Autowiredprivate MailAttachmentService attachmentService;@Autowiredprivate TemplateEngine templateEngine;@Autowiredprivate CustomerService customerService;@Autowiredprivate MailAccountService accountService;@Autowiredprivate SupplierService supplierService;@Autowiredprivate CsGroupService groupService;@Autowiredprivate AnnaylizeOssDirSpaceService annaylizeOssDirSpaceService;@Autowiredprivate CustomLocusService customLocusService;@Autowiredprivate CustomCommunityService customCommunityService;@Autowiredprivate CsUserService csUserService;@Autowiredprivate ReceiverMailByOneAccountService receiverMailByOneAccountService;@Autowiredprivate CsMsgPushMapper msgPushMapper;@Autowiredprivate 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) {//ImapmailDto.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();}} }總結
以上是生活随笔為你收集整理的RabbitMQ延迟队列实现定时发邮件的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Python实例:pdf文档转txt
- 下一篇: MFC三张图按钮三种状态