first commit

This commit is contained in:
Ray
2026-02-19 03:37:37 +08:00
commit ccfd8c79a4
2813 changed files with 453657 additions and 0 deletions

View File

@@ -0,0 +1,3 @@
Manifest-Version: 1.0
Class-Path:

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
<display-name>Email</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
</web-app>

View File

@@ -0,0 +1,4 @@
email.host=
email.username=
email.password=
email.from=

View File

@@ -0,0 +1,22 @@
package email;
public class Config {
/**
* host
*/
public static final String host = EmailPropertiesUtil.getProperty("email.host");
/**
*username
*/
public static final String username = EmailPropertiesUtil.getProperty("email.username");
/**
* password
*/
public static final String password = EmailPropertiesUtil.getProperty("email.password");
/**
* from
*/
public static final String from = EmailPropertiesUtil.getProperty("email.from");
}

View File

@@ -0,0 +1,133 @@
package email;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.Properties;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* 读取Properties综合类,默认绑定到classpath下的config.properties文件。
*/
public class EmailPropertiesUtil {
private static Log log = LogFactory.getLog(EmailPropertiesUtil.class);
private static String CONFIG_FILENAME = "config/email.properties";
private static Properties prop = null;
public EmailPropertiesUtil() {
if (prop == null) {
loadProperties();
}
};
private synchronized static void loadProperties() {
byte buff[]=null;
try {
//Open the props file
InputStream is=EmailPropertiesUtil.class.getResourceAsStream("/" + CONFIG_FILENAME);
prop = new Properties();
//Read in the stored properties
prop.load(is);
}
catch (Exception e) {
System.err.println("读取配置文件失败!!!");
prop = null;
log.error(e.getMessage(), e);
}
}
/**
* 得到属性值
* @param key
* @return
*/
public static String getProperty(String key) {
if (prop == null) {
loadProperties();
}
String value = prop.getProperty(key);
if(value ==null){
return null;
}
return value.trim();
}
/**
* 得到内容包含汉字的属性值
* @param key
* @return
*/
public static String getGBKProperty(String key) {
String value = getProperty(key);
try {
value = new String(value.getBytes("ISO8859-1"),"GBK");
} catch (UnsupportedEncodingException e) {
}
if(value ==null){
return null;
}
return value.trim();
}
/**
* 得到属性值,
* @param key
* @param defaultValue
* @return
*/
public static String getProperty(String key, String defaultValue) {
if (prop == null) {
loadProperties();
}
String value = prop.getProperty(key, defaultValue);
if(value ==null){
return null;
}
return value.trim();
}
/**
* 得到内容包含汉字的属性值,如果不存在则使用默认值
* @param key
* @return
*/
public static String getGBKProperty(String key, String defaultValue) {
try {
defaultValue = new String(defaultValue.getBytes("GBK"), "ISO8859-1");
String value = getProperty(key, defaultValue);
value = new String(value.getBytes("ISO8859-1"), "GBK");
if (value == null) {
return null;
}
return value.trim();
} catch (UnsupportedEncodingException e) {
return null;
}
}
public static String getUTFProperty(String key, String defaultValue) {
try {
defaultValue = new String(defaultValue.getBytes("UTF-8"),
"ISO8859-1");
String value = getProperty(key, defaultValue);
value = new String(value.getBytes("ISO8859-1"), "UTF-8");
if (value == null) {
return null;
}
return value.trim();
} catch (UnsupportedEncodingException e) {
return null;
}
}
public static void main(String[] args) {
System.out.println(EmailPropertiesUtil.getProperty("mail.username"));
}
}

View File

@@ -0,0 +1,64 @@
package email;
import java.io.File;
import java.util.Map;
/**
* 短信发送异步发送写入SmsMessageQueue队列返回
*
*/
public interface EmailSendService {
/**
* 发送EMAIL
*
* @param tomail
* 目标邮件地址
* @param subject
* 邮件标题
* @param content
* 邮件内容
*/
public void sendEmail(String tomail, String subject, String content);
/**
* 发送Velocity模板EMAIL
*
*
* @param tomail
* 目标邮件地址
*
* @param subject
* 邮件标题
* @param ftlname
* 模板名称, 模板文件需存放到ftl包下
* 如果为空直接发送content内容否则根据map和ftlname构造content邮件内容
*
* @param map
* 模板参数替换值
*/
public void sendEmail(String tomail, String subject, String ftlname, Map<String, Object> map);
/**
* 发送Velocity模板EMAIL
*
*
* @param tomail
* 目标邮件地址
*
* @param subject
* 邮件标题
* @param ftlname
* 模板名称, 模板文件需存放到ftl包下
* 如果为空直接发送content内容否则根据map和ftlname构造content邮件内容
*
* @param map
* 模板参数替换值
* @param file
* 附件
* @param filename
* 附件名称
*/
public void sendEmail(String tomail, String subject, String content, String ftlname, Map<String, Object> map, File file, String filename);
}

View File

@@ -0,0 +1,66 @@
package email;
import java.util.Properties;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSenderImpl;
public class EmailUtils {
private static JavaMailSenderImpl javaMailSender;
private static final String userName = "1231222222221@163.com";
private static final String password = "bbbbbbaaaaa";
private static final String host = "smtp.163.com";
private static final int port = 25;
// 定义收件人列表
private static final String[] revicedUserName = { "122322222221@qq.com" };
static {
javaMailSender = new JavaMailSenderImpl();
javaMailSender.setHost(host);// 链接服务器
javaMailSender.setPort(port);
javaMailSender.setUsername(userName);// 账号
javaMailSender.setPassword(password);// 密码
javaMailSender.setDefaultEncoding("UTF-8");
Properties properties = new Properties();
properties.setProperty("mail.smtp.auth", "true");// 开启认证
properties.setProperty("mail.debug", "true");// 启用调试
properties.setProperty("mail.smtp.timeout", "10000");// 设置链接超时
properties.setProperty("mail.smtp.port", Integer.toString(port));// 设置端口
javaMailSender.setJavaMailProperties(properties);
}
/***
* 发送项目异常 代码提醒
*
* @param msg
*/
public static void sendEmail(final String msg) {
// 开启线程异步发送 防止发送请求时间过长
new Thread(new Runnable() {
@Override
public void run() {
if (revicedUserName != null && revicedUserName.length > 0) {
SimpleMailMessage mailMessage = new SimpleMailMessage();
mailMessage.setFrom(userName);
mailMessage.setSubject("====后台管理项目异常====");
mailMessage.setText(msg);
mailMessage.setTo(revicedUserName);
// 发送邮件
javaMailSender.send(mailMessage);
}
}
}).start();
}
public static void main(String[] args) {
sendEmail("代码开始抽风报警了------");
}
}

View File

@@ -0,0 +1,11 @@
<!DOCTYPE head PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title></title>
<meta HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf-8">
</head>
<body>
我是测试
</body>
</html>

View File

@@ -0,0 +1,32 @@
package email.internal;
import java.io.File;
import java.util.Map;
import email.EmailSendService;
import email.sender.EmailMessage;
import email.sender.EmailMessageQueue;
public class EmailSendServiceImpl implements EmailSendService {
@Override
public void sendEmail(String tomail, String subject, String content) {
EmailMessageQueue.add( new EmailMessage(tomail, subject, content, null, null, null,null));
}
@Override
public void sendEmail(String tomail, String subject, String ftlname, Map<String, Object> map) {
EmailMessageQueue.add( new EmailMessage( tomail, subject, null, ftlname, map, null,null));
}
@Override
public void sendEmail(String tomail, String subject, String content, String ftlname, Map<String, Object> map,
File file, String filename) {
EmailMessageQueue.add( new EmailMessage( tomail, subject, content, ftlname, map, file,filename));
}
}

View File

@@ -0,0 +1,11 @@
package email.internal;
import lombok.Data;
import java.util.List;
@Data
public class FreemakerBizDataDemo {
private List<String> list;
}

View File

@@ -0,0 +1,70 @@
package email.internal;
import freemarker.cache.TemplateLoader;
import freemarker.core.BugException;
import freemarker.core.TextBlock;
import freemarker.core._CoreAPI;
import freemarker.debug.impl.DebuggerService;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateExceptionHandler;
import java.io.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class FreemakerDemo {
public static void main(String[] args) throws Exception {
String tplContent = "listvalue:<br/><#list list as v>${v} - ${v_index} [${v_has_next?string(\"y\",\"n\")}]</#list>";
String tplFileName = "none.ftl";
// this.freeMarkerConfigurer.getConfiguration()
Configuration cfg = new Configuration(); //Freemarker的起始类,要使用Freemarker功能必须通过该类
cfg.setDirectoryForTemplateLoading(new File("D:/tmp"));//freemarker从什么地方加载模板文件
cfg.setTemplateExceptionHandler(TemplateExceptionHandler.IGNORE_HANDLER);//忽略异常
TemplateLoader templateLoader = cfg.getTemplateLoader();
final StringWriter sw = new StringWriter();
final char[] buf = new char[4096];
try (Reader reader = templateLoader.getReader(new File("D:/tmp/none.ftl"), "UTF-8")) {
fetchChars:
while (true) {
int charsRead = reader.read(buf);
if (charsRead > 0) {
sw.write(buf, 0, charsRead);
} else if (charsRead < 0) {
break fetchChars;
}
}
}
tplContent = sw.toString();
//Template template = Template.getPlainTextTemplate(tplFileName, tplContent, cfg);
Template template;
try {
template = new Template(tplFileName, tplFileName, new StringReader(tplContent), cfg);
template.setEncoding("UTF-8");
} catch (IOException e) {
throw new BugException("Plain text template creation failed", e);
}
//Template template = cfg.getTemplate(tplFileName, "UTF-8");
Map<String, List<String>> dataMap = new HashMap<String, List<String>>();
List<String> list = new ArrayList<String>();
for (int i = 0; i < 10; i++) {
list.add("listvalue" + i);
}
dataMap.put("list", list);
FreemakerBizDataDemo data = new FreemakerBizDataDemo();
data.setList(list);
StringWriter out = new StringWriter(1024);
// template.process(dataMap, out);
template.process(new Object(), out);
String finishedContent = out.toString();
System.out.println("==========> finishedContent:" + finishedContent);
}
}

View File

@@ -0,0 +1,10 @@
package email.internal;
import email.sender.EmailMessage;
public interface InternalEmailSenderService {
/**
* 邮件发送
*/
public void send(EmailMessage emailMessage) throws Exception ;
}

View File

@@ -0,0 +1,255 @@
package email.internal;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.*;
import java.util.stream.Collectors;
import javax.annotation.PostConstruct;
import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeUtility;
import email.sender.EmailServer;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.core.io.FileSystemResource;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.ui.freemarker.FreeMarkerTemplateUtils;
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;
import email.sender.EmailMessage;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import kernel.util.StringUtils;
public class InternalEmailSenderServiceImpl implements InternalEmailSenderService {
//private static final Log logger = LogFactory.getLog(InternalEmailSenderServiceImpl.class);
private static org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(InternalEmailSenderServiceImpl.class);
private JavaMailSenderImpl mailSender;
private SimpleMailMessage mailMessage;
private FreeMarkerConfigurer freeMarkerConfigurer;
private int currentIndex = 0; // 当前选择的邮箱账号索引
private String hosts;
private String ports;
private String usernames;
private String passwords;
private String froms;
private List<String> host;
private List<Integer> port;
private List<String> username;
private List<String> password;
private List<String> from;
@PostConstruct
public void init(){
this.host = Arrays.asList(hosts.split("&&"));
this.port = Arrays.stream(ports.split("&&"))
.map(Integer::parseInt)
.collect(Collectors.toList());
this.username = Arrays.asList(usernames.split("&&"));
this.password = Arrays.asList(passwords.split("&&"));
this.from = Arrays.asList(froms.split("&&"));
}
public static void main(String[] args) throws Exception {
JavaMailSenderImpl sender = new JavaMailSenderImpl();
System.out.println("---- 准备发送 email...");
//服务器
sender.setHost("smtp.titan.email");
//协议
sender.setProtocol("smtps");//"smtps"
//端口号
sender.setPort(465);
//邮箱账号
sender.setUsername("support@e-metashop.com");
//邮箱授权码
sender.setPassword("Gyuws;[1o3iu2u2Feisf");
//编码
sender.setDefaultEncoding("Utf-8");
Properties p = new Properties();
p.setProperty("mail.smtp.auth", "true");
p.setProperty("mail.smtp.starttls.enable", "true");
sender.setJavaMailProperties(p);
MimeMessage mailMsg = sender.createMimeMessage();
MimeMessageHelper messageHelper = new MimeMessageHelper(mailMsg, true, "UTF-8");
messageHelper.setTo("tongyiwzh@qq.com");// 接收邮箱
messageHelper.setFrom("support@e-metashop.com");// 发送邮箱
messageHelper.setSentDate(new Date());// 发送时间
messageHelper.setSubject("测试邮件发送");// 邮件标题
messageHelper.setText("测试邮件内容4443333311111111");// 邮件内容
sender.send(mailMsg);// 发送
System.out.println("---- 发送 email成功");
}
public static void test1() throws Exception {
JavaMailSenderImpl sender = new JavaMailSenderImpl();
//服务器
sender.setHost("smtp.office365.com");//"smtp.qq.com"
//协议
//sender.setProtocol("smtps");//"smtps"
//端口号
sender.setPort(587);//465
//邮箱账号
sender.setUsername("sendtoautotocodesendto@outlook.com");//"*********@qq.com"
//邮箱授权码
sender.setPassword("1FW*VDZ#eN!");
//编码
sender.setDefaultEncoding("Utf-8");
Properties p = new Properties();
//p.setProperty("mail.smtp.ssl.enable", "true");// outlook不能用
p.setProperty("mail.smtp.auth", "true");
p.setProperty("mail.smtp.starttls.enable", "true");
// p.setProperty("mail.smtp.host", "smtp.office365.com");// 可免
// p.setProperty("mail.smtp.port", "587");// 可免
sender.setJavaMailProperties(p);
MimeMessage mailMsg = sender.createMimeMessage();
MimeMessageHelper messageHelper = new MimeMessageHelper(mailMsg, true, "UTF-8");
messageHelper.setTo("tongyiwzh@qq.com");// 接收邮箱
messageHelper.setFrom("sendtoautotocodesendto@outlook.com");// 发送邮箱
messageHelper.setSentDate(new Date());// 发送时间
messageHelper.setSubject("测试邮件发送");// 邮件标题
messageHelper.setText("测试邮件内容444333333");// 邮件内容
sender.send(mailMsg);// 发送
System.out.println("---- 发送 email成功");
}
@Override
public void send(EmailMessage emailMessage) throws Exception {
try {
//// 设置发送邮件的信息
if (currentIndex >= this.host.size()) {
currentIndex = 0; // 重置计数器
}
this.mailSender.setPort(port.get(currentIndex));
this.mailSender.setUsername(username.get(currentIndex));
this.mailSender.setPassword(password.get(currentIndex));
this.mailSender.setHost(host.get(currentIndex));
MimeMessage mailMsg = this.mailSender.createMimeMessage();
MimeMessageHelper messageHelper = new MimeMessageHelper(mailMsg, true, "UTF-8");
messageHelper.setTo(emailMessage.getTomail());// 接收邮箱
// messageHelper.setFrom(this.mailMessage.getFrom());// 发送邮箱
messageHelper.setFrom(from.get(currentIndex));// 发送邮箱
messageHelper.setSentDate(new Date());// 发送时间
messageHelper.setSubject(emailMessage.getSubject());// 邮件标题
currentIndex++;
// 邮件内容
String content = "";
if (StringUtils.isNullOrEmpty(emailMessage.getFtlname())) {
content = emailMessage.getContent();
} else {
content = this.getMailText(emailMessage.getFtlname(), emailMessage.getMap());
}
if (content == null || content.trim().isEmpty()) {
logger.error("向目标邮箱:" + emailMessage.getTomail() + " 发送的标题为:" + emailMessage.getSubject() + " 的邮件内容解析为空,不发送该邮件!");
return;
}
messageHelper.setText(content, true);
// true 表示启动HTML格式的邮件
if (emailMessage.getFile() != null) {
// 添加邮件附件
FileSystemResource rarfile = new FileSystemResource(emailMessage.getFile());
// addAttachment addInline 两种附件添加方式
// 以附件的形式添加到邮件
// 使用MimeUtility.encodeWord 解决附件名中文乱码的问题
messageHelper.addAttachment(MimeUtility.encodeWord(emailMessage.getFilename()), rarfile);
}
this.mailSender.send(mailMsg);// 发送
} catch (MessagingException e) {
//org.springframework.mail.MailSendException
//logger.error(e.getMessage(), e);
// 外层需要用到抛出的异常做相关的业务处理
throw e;
} catch (UnsupportedEncodingException e) {
logger.error(e.getMessage(), e);
}
}
/**
* 获取模板并将内容输出到模板
*
* @param ftlname
* @param map
* @return
*/
private String getMailText(String ftlname, Map<String, Object> map) {
String html = "";
try {
// 装载模板
Template tpl = this.freeMarkerConfigurer.getConfiguration().getTemplate(ftlname);
// 加入map到模板中 输出对应变量
html = FreeMarkerTemplateUtils.processTemplateIntoString(tpl, map);
} catch (IOException e) {
e.printStackTrace();
} catch (TemplateException e) {
e.printStackTrace();
}
return html;
}
// 选择下一个邮箱账号索引
private synchronized int getNextMailSender() {
if (currentIndex >= this.host.size()) {
currentIndex = 0; // 重置计数器
}
this.mailSender.setPort(port.get(currentIndex));
this.mailSender.setUsername(username.get(currentIndex));
this.mailSender.setPassword(password.get(currentIndex));
this.mailSender.setHost(host.get(currentIndex));
currentIndex++;
return currentIndex++;
}
public void setMailSender(JavaMailSenderImpl mailSender) {
this.mailSender = mailSender;
}
public void setMailMessage(SimpleMailMessage mailMessage) {
this.mailMessage = mailMessage;
}
public void setFreeMarkerConfigurer(FreeMarkerConfigurer freeMarkerConfigurer) {
this.freeMarkerConfigurer = freeMarkerConfigurer;
}
public void setHosts(String hosts) {
this.hosts = hosts;
}
public void setPorts(String ports) {
this.ports = ports;
}
public void setUsernames(String usernames) {
this.usernames = usernames;
}
public void setPasswords(String passwords) {
this.passwords = passwords;
}
public void setFroms(String froms) {
this.froms = froms;
}
}

View File

@@ -0,0 +1,8 @@
package email.internal;
public class Test {
public static void main(String[] args) {
System.out.println("hello");
}
}

View File

@@ -0,0 +1,126 @@
package email.sender;
import java.io.File;
import java.io.Serializable;
import java.util.Map;
/**
*
* <p>Description: 邮件消息类 </p>
*/
public class EmailMessage implements Serializable{
private static final long serialVersionUID = 3402051115688556553L;
/**
* 目标邮件地址
*/
private String tomail;
/**
* 邮件标题
*/
private String subject;
/**
* 邮件内容
*/
private String content;
/**
* 模板名称,
* 模板文件需存放到ftl包下
* 如果为空直接发送content内容否则根据map和ftlname构造content邮件内容
*/
private String ftlname;
/**
* 模板参数替换值
*/
private Map<String, Object> map;
/**
* 附件
*/
private File file;
/**
* 附件名称
*/
private String filename;
/**
* 无参构造函数
*/
public EmailMessage() {
}
/**
* 构造函数
*/
public EmailMessage(String tomail, String subject,String content,String ftlname,Map<String, Object> map,File file,String filename) {
this.tomail = tomail;
this.subject = subject;
this.content = content;
this.ftlname = ftlname;
this.map = map;
this.file = file;
this.filename = filename;
}
public String getTomail() {
return tomail;
}
public void setTomail(String tomail) {
this.tomail = tomail;
}
public String getSubject() {
return subject;
}
public void setSubject(String subject) {
this.subject = subject;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String getFtlname() {
return ftlname;
}
public void setFtlname(String ftlname) {
this.ftlname = ftlname;
}
public Map<String, Object> getMap() {
return map;
}
public void setMap(Map<String, Object> map) {
this.map = map;
}
public File getFile() {
return file;
}
public void setFile(File file) {
this.file = file;
}
public String getFilename() {
return filename;
}
public void setFilename(String filename) {
this.filename = filename;
}
}

View File

@@ -0,0 +1,35 @@
package email.sender;
import java.util.concurrent.ConcurrentLinkedQueue;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class EmailMessageQueue {
private static final Log logger = LogFactory.getLog(EmailMessageQueue.class);
private static ConcurrentLinkedQueue<EmailMessage> WORKING_EVENTS = new ConcurrentLinkedQueue<EmailMessage>();
public static void add(EmailMessage item) {
try {
WORKING_EVENTS.add(item);
} catch (Throwable e) {
logger.error("add(SmsMessage item) fail : ", e);
}
}
public static int size() {
return WORKING_EVENTS.size();
}
public static EmailMessage poll() {
EmailMessage item = null;
try {
item = WORKING_EVENTS.poll();
} catch (Throwable e) {
logger.error("SmsMessage poll() fail : ", e);
}
return item;
}
}

View File

@@ -0,0 +1,115 @@
package email.sender;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.task.TaskExecutor;
import email.internal.InternalEmailSenderService;
import kernel.util.ThreadUtils;
import project.mall.task.MallOrdersJob;
import java.util.HashMap;
import java.util.Map;
/**
* 邮件服务类,负责从短信消息队列取出短信消息并发送
*/
public class EmailServer implements InitializingBean, Runnable {
//private static Log logger = LogFactory.getLog(EmailServer.class);
private static org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(EmailServer.class);
private TaskExecutor taskExecutor;
private InternalEmailSenderService internalEmailSenderService;
// 优化
// 一次发送失败的邮箱,在 5 分钟内再次遇到发送邮件时直接忽略
long invalidTimeout = 5L * 60L * 1000L;
// 记录发送失败的邮箱上次真实发送的时间戳
private Map<String, Long> failEmailMap = new HashMap();
/**
* 服务运行:
* 1. 从消息队列获取message
* 2.调用currentProvider发送短信
*/
public void run() {
while (true) {
try {
EmailMessage item = EmailMessageQueue.poll();
if (item != null) {
logger.info("---> EmailServer.run 邮寄地址:{}", item.getTomail());
long now = System.currentTimeMillis();
Long lastSendTime = failEmailMap.get(item.getTomail());
if (lastSendTime != null && lastSendTime > 0) {
if (lastSendTime + invalidTimeout > now) {
// 上次发送失败,并且还没过时限,忽略本次发送
logger.warn("当前待发送消息的目标邮箱:" + item.getTomail() + " 在时刻:" + lastSendTime + " 发送失败,尚未过冷却期,忽略本次消息的发送, 消息内容:" + item.getContent());
continue;
}
}
taskExecutor.execute(new HandleRunner(item));
} else {
/*
* 限速最多1秒20个
*/
ThreadUtils.sleep(50);
}
} catch (Throwable e) {
logger.error("EmailServer taskExecutor.execute() fail", e);
}
}
}
public class HandleRunner implements Runnable {
private EmailMessage item;
public HandleRunner(EmailMessage item) {
this.item = item;
}
public void run() {
long now = System.currentTimeMillis();
try {
internalEmailSenderService.send(item);
logger.info("---> HandleRunner.run 向邮件地址:{} 发送邮件:{} 正常结束", item.getTomail(), item.getContent());
} catch (Throwable t) {
failEmailMap.put(this.item.getTomail(), now);
logger.error("EmailServer taskExecutor.execute() fail, email:" + item.getTomail(), t);
}
}
}
public void afterPropertiesSet() throws Exception {
new Thread(this, "EmailServer").start();
if (logger.isInfoEnabled()) {
logger.info("启动邮件发送服务!");
}
}
public void setTaskExecutor(TaskExecutor taskExecutor) {
this.taskExecutor = taskExecutor;
}
public void setInternalEmailSenderService(InternalEmailSenderService internalEmailSenderService) {
this.internalEmailSenderService = internalEmailSenderService;
}
}

View File

@@ -0,0 +1,16 @@
package email.sender;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadPoolExecutor;
import kernel.util.ThreadUtils;
public class OffLineEventRejectExecutingHandler implements RejectedExecutionHandler {
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
ThreadUtils.sleep(1000 * 10);
executor.execute(r);
}
}

View File

@@ -0,0 +1,97 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:util="http://www.springframework.org/schema/util"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.0.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<bean id="emailSendService" class="email.internal.EmailSendServiceImpl">
</bean>
<context:property-placeholder location="classpath:config.properties" />
<bean id="internalEmailSenderService" class="email.internal.InternalEmailSenderServiceImpl" init-method="init">
<property name="hosts" value="${email.host}"/>
<property name="ports" value="${email.port}"/>
<property name="usernames" value="${email.username}"/>
<property name="froms" value="${email.from}"/>
<property name="passwords" value="${email.password}"/>
<property name="mailSender" ref="mailSender" />
<property name="mailMessage" ref="mailMessage" />
<property name="freeMarkerConfigurer" ref="freeMarkerConfigurer" />
</bean>
<bean id="emailServer" class="email.sender.EmailServer">
<property name="taskExecutor" ref="emailSendThreadPool" />
<property name="internalEmailSenderService" ref="internalEmailSenderService" />
</bean>
<bean id="emailSendThreadPool" class="kernel.concurrent.ThreadPoolTaskExecutor">
<property name="corePoolSize" value="2" />
<property name="keepAliveSeconds" value="60" />
<property name="maxPoolSize" value="4" />
<property name="queueCapacity" value="3000" />
<property name="rejectedExecutionHandler" ref="emailSendThreadRejectExecutingHandler" />
</bean>
<bean id="emailSendThreadRejectExecutingHandler" class="kernel.util.RejectExecutionHandlerDelegator">
<property name="rejectExecutionHandlers">
<list>
<bean class="email.sender.OffLineEventRejectExecutingHandler" />
</list>
</property>
</bean>
<!-- 邮件发送方配置bean -->
<bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
<property name="host" value="${email.host}" />
<!-- <property name="port" value="${email.port}" />-->
<!-- mail account -->
<property name="username" value="${email.username}" />
<property name="password" value="${email.password}" />
<property name="javaMailProperties">
<props>
<!-- gmail
<prop key="mail.smtp.auth">true</prop>
<prop key="mail.smtp.port">465</prop>
<prop key="mail.smtp.ssl.enable">true</prop>
<prop key="mail.debug">true</prop>
<prop key="mail.smtp.host">smtp.gmail.com</prop>
<prop key="mail.smtp.socketFactory.class">javax.net.ssl.SSLSocketFactory</prop>
<prop key="mail.smtp.socketFactory.port">465</prop>-->
<!-- outlook-->
<!-- <prop key="mail.smtp.port">${email.port}</prop>-->
<prop key="mail.smtp.starttls.enable">true</prop>
<prop key="mail.smtp.auth">true</prop>
<!--
<prop key="mail.smtp.port">465</prop>
<prop key="mail.smtp.socketFactory.port">465</prop>
<prop key="mail.smtp.socketFactory.class">javax.net.ssl.SSLSocketFactory</prop> -->
</props>
</property>
</bean>
<!-- 邮件发送模板 -->
<bean id="mailMessage" class="org.springframework.mail.SimpleMailMessage">
<property name="from" value="${email.username}" />
</bean>
<!-- 配置发送模板bean -->
<bean id="freeMarkerConfigurer"
class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
<property name="templateLoaderPaths" value="classpath:email/ftl" /><!--
模板路径位置 -->
<property name="freemarkerSettings">
<props>
<prop key="template_update_delay">1800</prop><!-- 模板更新延时 -->
<prop key="default_encoding">UTF-8</prop>
<prop key="locale">zh_CN</prop>
</props>
</property>
</bean>
</beans>