java 多人发送邮件_java中使用FIFO队列:java.util.Queue实现多台服务器发邮件的代码...

最近由于注册用户的增多,qq企业邮箱发送邮件会被封禁账号导致注册后面的用户收不到周总结,所以紧急开发了一套多账号,多服务器发送邮件的程序。

大概的设计思路如下:

5f44669d9023f819b9cfa4031178418d.png

1.服务器可以无限扩展,但由于qq企业邮箱是限定域名,所以要想多服务器还得有多域名,多账号也不行。

2.最核心的代码是FIFO分配指定长度的邮件列表这一步,通过java线程同步Queue实现。

3.发送失败的要加到重试队列继续发送。

4.经测试每分钟发一封邮件,qq企业邮箱最大可以发送7000封邮件,这样最代码2个账号[email protected]和[email protected]就可以发送到15000个邮件,该方案绝对是性价比超高的,目前市面上每封邮件1分钱,那15000也得150元人民币,如果你每周呢?

5.可以指定某个用户id来只发送某个范围的邮件列表

6.可以指定clear参数来清空所有邮件列表,不过该参数慎用,避免多发送邮件。

下面分享下核心代码,有思路和代码做参考,我想大家肯定可以自己搭建起来了:

分配邮件端核心java代码:private final static Map> map = new HashMap>();

// 申请发邮件的邮箱地址,每次根据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 allUsers = null;

List users = new ArrayList();

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();

if (user_id == null) {

user_id = 0l;

}

Page 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 weekSummaryShareIds = findIds(startDate, endDate);

ModelMap model = new ModelMap();

Collection 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 weekRankUsers = rankService.findAllByType(

ModuleConstants.RANK_TYPE_USER_CONTRIBUTE_WEEK,

ParamConstants.DEFAULT_PAGE,

ParamConstants.DEFAULT_TOP_LESS_COUNT,

ModuleConstants.RANKSORT);

model.put("weekRankUsers", weekRankUsers);

Page 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 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 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 failed1 = new ArrayList();

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 failed2 = new ArrayList();

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 failed3 = new ArrayList();

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 failed4 = new ArrayList();

i = 1;

for (Object userJson : failed3) {

send(userJson, title, template, i, failed4, failed3.size());

i++;

}

System.out.println("最终发送失败的邮箱列表:" + failed4);

} catch (Exception e) {

e.printStackTrace();

}

}

}

线上正式环境运行截图:

5f44669d9023f819b9cfa4031178418d.png

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值