企业项目中经常使用到邮件发送,尤其在流程审批伴随大量的触发邮件,为提供效率邮件自然设置为异步发送,但单纯多线程异步又造成了先后混乱的现象。所以做了个简单的单线程异步发送队列来处理。
1、把原有的邮件发送服务类做了个修改
ublic class MailSendService { private @Value("${system.sendmail.from}") String mailForm; @Autowired private JavaMailSender javaMailSender; // 邮件发送对象,采用的是spring中的实现类org.springframework.mail.javamail.JavaMailSenderImpl @Autowired private MailBoxDao mailBoxDao; //邮件信息记录处理DAO @Autowired private MailTemplateDao mailTemplateDao; //邮件模板处理DAO /** * 一个默认的邮件发送线程对象 */ private static MailSendTask mailSendTask; /** * 发送简单邮件 * @Methods Name sendByTempate * @Create In 2014年11月11日 By lee * @param templateCode * @param to * @param titleParam * @param contextParam */ public void sendByTempate(String templateCode, String to, Map<String,String> titleParam, Map<String,String> contentParam){ sendByTempate(templateCode, to, null, null, titleParam, contentParam, null); } /** * 发送邮件 * @Methods Name sendByTempate * @Create In 2014年11月11日 By lee * @param templateCode * @param to * @param cc * @param bcc * @param titleParam * @param contextParam * @param fileParam */ public void sendByTempate(String templateCode, String to, String cc, String bcc, Map<String,String> titleParam, Map<String,String> contentParam, List<String> fileParam){ MailTemplate template = mailTemplateDao.findByCode(templateCode); MailBox mailBox = new MailBox(); mailBox.setTouser(to); mailBox.setCc(bcc); mailBox.setBcc(bcc); mailBox.setTitle(emailParam(template.getTitle(),titleParam)); mailBox.setContent(emailParam(template.getContent(),contentParam)); mailBox.setFilePath(StrUtils.join(fileParam, ";")); mailBox.setSendState(MailBox.STATE_READY); mailBox = mailBoxDao.save(mailBox); readSend(mailBox); } private String emailParam(String str, Map<String,String> paramMap) { if (paramMap != null && !paramMap.isEmpty()) { for(String paramKey : paramMap.keySet()){ String paramValue = paramMap.get(paramKey); str = StrUtils.replace(str, "{"+paramKey+"}", paramValue); } } return str; } /** * 准备发送,进去发送队列 * @Methods Name readSend * @Create In 2014年11月11日 By lee * @param mailBox */ private void readSend(MailBox mailBox){ if(mailSendTask==null){ mailSendTask = new MailSendTask(mailForm,javaMailSender,mailBoxDao); new Thread(mailSendTask).start(); List<MailBox> boxs = mailBoxDao.findBySendState(MailBox.STATE_READY); for(MailBox box : boxs){ mailSendTask.addItem(box); } }else{ mailSendTask.addItem(mailBox); } } }
新增一个邮件发送任务类
/** * 邮件发送任务 * @ClassName: MailSendTask * @Description: TODO * @Create In 2014年11月11日 By lee */ public class MailSendTask implements Runnable { private static Log logger = LogFactory.getLog(MailSendTask.class); private static BlockingQueue<MailBox> calls = new LinkedBlockingQueue<MailBox>(500); private String mailForm = "lee"; private JavaMailSender javaMailSender; // 邮件发送对象,采用的是spring中的实现类org.springframework.mail.javamail.JavaMailSenderImpl private MailBoxDao mailBoxDao; public MailSendTask(String mailForm, JavaMailSender javaMailSender,MailBoxDao mailBoxDao) { this.javaMailSender = javaMailSender; this.mailBoxDao = mailBoxDao; this.mailForm = mailForm; } @Override public void run() { logger.info("邮件发送线程启动"); while (true) { try { MailBox mailBox = calls.take(); sendMail(mailBox); } catch (InterruptedException e) { e.printStackTrace(); } } } public void addItem(MailBox mailBox) { try { calls.put(mailBox); } catch (InterruptedException e) { e.printStackTrace(); } } private void sendMail(MailBox mailBox){ JavaMailSenderImpl senderImpl = new JavaMailSenderImpl(); MimeMessage mimeMessage = senderImpl.createMimeMessage(); try{ // 设置utf-8或GBK编码,否则邮件会有乱码 MimeMessageHelper messageHelper = new MimeMessageHelper(mimeMessage, true, "utf-8"); if (StrUtils.isNotEmpty(mailBox.getTouser())) { //设定收件人 mimeMessage.setRecipients(Message.RecipientType.TO, getAddressArray(mailBox.getTouser())); } if (StrUtils.isNotEmpty(mailBox.getCc())) { //设定抄送 mimeMessage.setRecipients(Message.RecipientType.CC, getAddressArray(mailBox.getCc())); } if (StrUtils.isNotEmpty(mailBox.getBcc())) { //设定密送 mimeMessage.setRecipients(Message.RecipientType.BCC, getAddressArray(mailBox.getBcc())); } messageHelper.setFrom(mailForm);// 发送者 messageHelper.setSubject(mailBox.getTitle());// 主题 // 邮件内容,注意加参数true messageHelper.setText(mailBox.getContent(), true); // 附件内容 if (StrUtils.isNotEmpty(mailBox.getFilePath())) { String[] filePaths = mailBox.getFilePath().split(";"); for (String filePath : filePaths) { File file = new File(filePath); //使用MimeUtility.encodeWord()来解决附件名称的中文问题 messageHelper.addAttachment(MimeUtility.encodeWord(file.getName()), file); } } javaMailSender.send(mimeMessage); mailBox.setSendState(MailBox.STATE_FINISH); mailBox.setSendTime(DateUtils.getCurrentDateTimeStr()); mailBoxDao.save(mailBox); }catch(Exception e){ logger.error("邮件发送失败"); } } /** * 组装收件地址 * @Methods Name getAddressArray * @Create In 2014年11月10日 By lee * @param addressStr * @return * @throws AddressException */ private InternetAddress[] getAddressArray(String addressStr) throws AddressException{ String[] abcc = addressStr.split(";"); InternetAddress[] adds = new InternetAddress[abcc.length]; for (int i = 0; i < abcc.length; i++) { adds[i] = new InternetAddress(abcc[i]); } return adds; }
两个相关实体类
public class MailBox extends IdEntity { public static final int STATE_READY = 0; //待发送 public static final int STATE_FINISH = 1; //已发送 private String title; //邮件标题 private String content; // 邮件内容 private Integer sendState; // 发送状态 0,待发 1,已发送 private String sendTime; // 发送时间 private String sendNums; // 发送次数 private String touser; // 收件人 private String cc; // 抄送人 private String bcc; // 密送人 private String filePath; // 文件路径
public class MailTemplate extends IdEntity { public static final int USED = 1; //在用 public static final int UNUSED = 0; //未用 private String code; //关键字 private String descn; //描述 private String title; //模板标题 private String content; //模板内容
相关推荐
106、使用doctrine队列异步发送邮件1
AsyncMailSend Desc: 基于Redis消息队列实现的异步化框架,将页面注册与邮件发送解耦,实现在注册成功后异步发送邮件的功能。 运行项目的时候: 需先开启Redis服务。
本文实例讲述了PHP扩展Swoole实现...在实现“异步队列”这点上,有人采用MySQL表或者redis来存放待发送的邮件,然后,每分钟定时读取待发送列表,然后处理。这便是定时异步任务队列。但当前提交的任务要一分钟后才能
本文实例讲述了Swoole实现异步投递...此外利用task还可以实现PHP的数据库连接池,异步队列等。 【使用须知】 必须设置Task进程数: task_worker_num 投递一个异步任务到task_worker池中:Server->task 必须注
django-rq-mail 是一个基于的简单 Python 库,用于存储发送的电子邮件,并在后台与工作人员一起处理。 由于 django-rq-mail 基于 ,它完全由支持。 建筑学 django-rq-mail 添加了新元素来享受。 出于 django-rq-...
比如说,我发送一万封邮件,如果单纯使用一个for循环来发送,则执行时间要很长,要等很久才能发完,同时很容易导致阻塞、超时等问题。当邮件更多,比如一百万封的时候,问题会更加明显。这时最好的解决方案就是把这...
插件为Fastadmin的,在插件管理中无需解压就可安装。依赖thinkphp官方提供的think-queue队列,默认集成了异步邮件和短信发送功能
Django Post Office是一个简单的应用程序,用于在Django中发送和管理您的电子邮件。 一些很棒的功能是: 允许您异步发送电子邮件 多后端支持 支持HTML电子邮件 支持HTML电子邮件中的内联图像 支持基于数据库的电子...
URL收集: 爬虫从一个或多个初始URL开始,递归或迭代地发现新的URL,构建一个URL队列。这些URL可以通过链接分析、站点地图、搜索引擎等方式获取。 请求网页: 爬虫使用HTTP或其他协议向目标URL发起请求,获取网页的...
在Lumen开发的微服务可实时或按队列发送电子邮件。 当前功能 实时发送电子邮件 异步发送电子邮件 将电子邮件保存在数据库中 显示保存在数据库中的所有电子邮件 删除保存在数据库中的电子邮件 即将推出的功能 延迟...
2.使用异步队列设计来完成对站内信、登录异常、点赞问题等事件的处理,提升系统的用户交互体验,采用邮件发送技术对用户关心的资讯进行邮件通知。 3.采用七牛云对象存储,通过提供的SDK进行对资讯中的图片、用户...
单个队列消息的最大大小为64 KB,一个队列中可以包含数百万条消息,最多达到存储帐户的总容量限制。 队列存储通常用于创建待异步处理的作业积压。 内容是什么? 项目中包括将数据添加到队列,删除数据,更新数据,...
前言 Laravel 队列为不同的后台队列服务提供统一的 API,例如 ...其中还包含了一个 null 队列驱动用于那些放弃队列的任务 为什么使用队列? 一般来说使用队列是为了: 异步 重试 也许你还有其他的理由使用队列,
使用java.mail通过smtp服务发送邮件,可以发送图片、附件、文本、可以动态通过json指定发送内容,有接口说明文档,提供消息队列异步处理机制(可通过参数控制同步或异步处理)
消息队列中间件是分布式系统中重要的组件,主要解决应用耦合、异步消息、流量削锋等问题。实现高性能、高可用、可伸缩和最终一致性架构。是大型分布式系统不可缺少的中间件。目前在生产环境,使用较多的消息队列有...
SQL Server 2005 的一个主要成就是可以实现可靠、可扩展且功能完善的数据库应用程序。与 .NET Framework 2.0 公共语言运行库 (CLR) 的集成使开发人员可以将重要的业务逻辑与存储过程合并,而 T-SQL 和 XML 中的新增...
消息队列中间件是分布式系统中重要的组件,主要解决应用耦合,异步消息,流量削锋等问题。实现高性能,高可用,可伸缩和最终一致性架构。是大型分布式系统不可缺少的中间件。目前在生产环境,使用较多的消息队列有...
发送到一个或多个队列(本地和/或远程) 同步或异步读取消息选择XML或JSON序列化自动消息分发以实现负载平衡参与环境交易可配置,强大的自动重试失败时移至错误队列自动创建本地队列简单的日志支持将错误消息返回到...
SlmQueue ...创建一个PDF文件 通过HTTP连接到第三方服务器 在所有情况下,您都希望尽快向访问者提供响应,而不要让他们等待如此漫长的过程。 SlmQueue使您可以在现有应用程序中非常轻松地实现作业队列系
电子邮件排队,并且队列异步发送 支持发送html电子邮件和带有多个附件(MIME)的电子邮件 附件可以添加为字符串,流或文件路径 支持utf-8标头和正文 内置类型声明 自动处理 要求 对SMTP服务器的身份验证访问 如果您...