最代码官方
2014-05-25 23:27:57
原精
java中使用FIFO队列:java.util.Queue实现多台服务器发邮件的代码
最近由于注册用户的增多,qq企业邮箱发送邮件会被封禁账号导致注册后面的用户收不到周总结,所以紧急开发了一套多账号,多服务器发送邮件的程序。
大概的设计思路如下:
1.服务器可以无限扩展,但由于qq企业邮箱是限定域名,所以要想多服务器还得有多域名,多账号也不行。
2.最核心的代码是FIFO分配指定长度的邮件列表这一步,通过java线程同步Queue实现。
3.发送失败的要加到重试队列继续发送。
4.经测试每分钟发一封邮件,qq企业邮箱最大可以发送7000封邮件,这样最代码2个账号service@javaniu.com和service@zuidaima.com就可以发送到15000个邮件,该方案绝对是性价比超高的,目前市面上每封邮件1分钱,那15000也得150元人民币,如果你每周呢?
5.可以指定某个用户id来只发送某个范围的邮件列表
6.可以指定clear参数来清空所有邮件列表,不过该参数慎用,避免多发送邮件。
下面分享下核心代码,有思路和代码做参考,我想大家肯定可以自己搭建起来了:
分配邮件端核心java代码:
private final static Map<Long, Queue<User>> map = new HashMap<Long, Queue<User>>(); // 申请发邮件的邮箱地址,每次根据mailTaskCount配置来取个数 public @ResponseBody JSONObject apply_mails( @PathVariable("id") Long id, @RequestParam(value = "start_date", required = false) String startDate, @RequestParam(value = "end_date", required = false) String endDate, @RequestParam(value = "clear", required = false) String clear, @RequestParam(value = "user_id", required = false) Long user_id) throws IOException, TemplateException { JSONObject json = new JSONObject(); String error = ""; if (StringUtils.isBlank(startDate) || StringUtils.isBlank(endDate)) { error = "参数非法,startDate和endDate"; json.put("error", error); return json; } final Task task = taskService.findOneById(id); if (task.getType() != ModuleConstants.TASK_TYPE_WEEK_SUMMARY) { error = "任务" + id + "不是周总结"; json.put("error", error); return json; } Queue<User> allUsers = null; List<User> users = new ArrayList<User>(); synchronized (map) {//注意线程安全 if (StringUtils.isNotBlank(clear)) {// clear map.put(id, null); error = "任务清空成功"; json.put("error", error); return json; } allUsers = map.get(id); if (allUsers == null) { allUsers = new LinkedList<User>(); if (user_id == null) { user_id = 0l; } Page<User> page = userService .findAllReceiveMailUsersGreaterThanId(user_id, 1, Integer.MAX_VALUE); allUsers.addAll(page.getContent()); map.put(id, allUsers); } int size = allUsers.size(); if (size == 0) { error = "任务" + id + "执行完毕!"; json.put("error", error); return json; } int i = 0; while (i < mailTaskCount) { User _user = allUsers.poll(); if (_user == null) { break; } users.add(_user); i++; } } File templateFile = new File(deployPath + "/apply_week_summary_" + id + ".html"); String templdate = ""; if (templateFile.exists()) { templdate = FileUtils.readFileToString(templateFile, "utf-8"); } else { List<Long> weekSummaryShareIds = findIds(startDate, endDate); ModelMap model = new ModelMap(); Collection<Project> weekSummaryShares = projectService .findAllByIds(weekSummaryShareIds); Configuration configuration = freemarkerConfig.getConfiguration(); configuration.setDirectoryForTemplateLoading(new File(deployPath + "/WEB-INF/template/")); Template template = configuration .getTemplate("apply_week_summary.htm"); Page<Rank> weekRankUsers = rankService.findAllByType( ModuleConstants.RANK_TYPE_USER_CONTRIBUTE_WEEK, ParamConstants.DEFAULT_PAGE, ParamConstants.DEFAULT_TOP_LESS_COUNT, ModuleConstants.RANKSORT); model.put("weekRankUsers", weekRankUsers); Page<Rank> monthRankUsers = rankService.findAllByType( ModuleConstants.RANK_TYPE_USER_CONTRIBUTE_MONTH, ParamConstants.DEFAULT_PAGE, ParamConstants.DEFAULT_TOP_LESS_COUNT, ModuleConstants.RANKSORT); model.put("monthRankUsers", monthRankUsers); model.put("task", task); model.put("weekSummaryShares", weekSummaryShares); Sort sort = new Sort(Direction.DESC, "secondSort"); Page<Project> downloadProjects = projectService.findAllByType( ModuleConstants.PROJECT_TYPE_SHARE_CODE, 1, ParamConstants.DEFAULT_TOP_COUNT, sort); model.put("downloadProjects", downloadProjects); sort = new Sort(Direction.DESC, "thirdSort"); Page<Project> commentProjects = projectService.findAllByType( ModuleConstants.PROJECT_TYPE_SHARE_CODE, 1, ParamConstants.DEFAULT_TOP_COUNT, sort); model.put("commentProjects", commentProjects); StringWriter stringWriter = new StringWriter(); stringWriter.flush(); stringWriter.close(); template.process(model, stringWriter); FileUtils.writeStringToFile(templateFile, stringWriter.toString(), "utf-8"); templdate = stringWriter.toString(); } json.put("template", templdate); JSONArray usersJson = new JSONArray(); for (User user : users) { JSONObject userJson = new JSONObject(); userJson.put("id", user.getId()); userJson.put("uuid", user.getUuid()); String code = Security.encryptUnsubscribeWeeklyEmail(user.getId() + "_" + new Date().getTime()); userJson.put("unsubscribe_weekly_email_code", code); userJson.put("email", user.getEmail()); usersJson.add(userJson); } json.put("users", usersJson); json.put("error", error); json.put("title", task.getTitle()); return json; }
发送邮件端核心java代码:
public static void main(String[] args) { if (args.length < 3) { System.out .println("需要3个参数:\n第一个是task id\n第二个是开始时间,如:2014-05-05\n第三个是结束时间,如:2014-05-09\n第四个参数user_id\n第五个参数是clear,如true"); return; } String task_id = args[0]; String start_date = args[1]; String end_date = args[2]; String user_id = "0"; if (args.length >= 4) { user_id = args[3]; } String clear = ""; if (args.length >= 5) { clear = args[4]; } String url = String.format(APPLY_EMAIL_URL, task_id, start_date, end_date, user_id, clear); while (true) { String response = request(url); JSONObject json = JSONObject.fromObject(response); String error = json.getString("error"); if (StringUtils.isNotBlank(error)) { System.out.println("发送邮件结束:error:" + error); break; } JSONArray usersJson = json.getJSONArray("users"); if (usersJson.size() == 0) { System.out.println("发送邮件结束"); break; } String template = json.getString("template"); String title = json.getString("title"); int i = 1; try { List<JSONObject> failed1 = new ArrayList<JSONObject>(); for (Object _userJson : usersJson) { send(_userJson, title, template, i, failed1, usersJson.size()); i++; } if (failed1.size() == 0) { System.out.println("发送邮件结束一批"); continue; } System.out.println("第一次发送失败的邮箱列表" + failed1); Thread.sleep(1 * 60 * 60 * 1000); List<JSONObject> failed2 = new ArrayList<JSONObject>(); i = 1; for (Object userJson : failed1) { send(userJson, title, template, i, failed2, failed1.size()); i++; } if (failed2.size() == 0) { System.out.println("failed1发送邮件结束一批"); continue; } System.out.println("第二次发送失败的邮箱列表" + failed2); Thread.sleep(1 * 60 * 60 * 1000); List<JSONObject> failed3 = new ArrayList<JSONObject>(); i = 1; for (Object userJson : failed2) { send(userJson, title, template, i, failed3, failed2.size()); i++; } if (failed3.size() == 0) { System.out.println("failed2发送邮件结束一批"); continue; } System.out.println("第三次发送失败的邮箱列表" + failed3); Thread.sleep(1 * 60 * 60 * 1000); List<JSONObject> failed4 = new ArrayList<JSONObject>(); i = 1; for (Object userJson : failed3) { send(userJson, title, template, i, failed4, failed3.size()); i++; } System.out.println("最终发送失败的邮箱列表:" + failed4); } catch (Exception e) { e.printStackTrace(); } } }
线上正式环境运行截图:
猜你喜欢
- java邮件发送service
- Java实现email邮件发送
- 自己封装的一个java邮件发送系统
- java发送邮件代码,即实现纯代码客户端发送邮件
- java mail邮件发送(含邮箱设置说明的)
- java mail实现发送html网页,text文本格式的邮件
- [个人笔记]java开发实现163邮件发送(支持附件)
- Java开发邮件接收发送系统源代码下载
- Java web 发送邮件(带附件)功能的简单示例---(新手分享-。-)
- 【demo】自己写的一个 SpringMail 异步发送邮件的demo。 javamail 邮件异步发送
- JavaMail邮件发送-能发送附件和带背景音乐的邮件的小系统
- java通过授权码机制调用腾讯邮箱smtp服务发送邮件
请下载代码后再发表评论
相关代码
最近下载
最近浏览
1358849392 LV21
2023年6月9日
浪里格朗 LV4
2023年1月31日
xuexizhuanyong23 LV16
2022年7月3日
1143011510 LV15
2021年7月14日
nini444
2021年5月25日
暂无贡献等级
李涛11111 LV8
2021年4月27日
喵小兵 LV10
2021年3月13日
dongzhan LV12
2020年12月22日
gwck2020 LV1
2020年12月10日
Jason137 LV8
2020年12月6日