diff --git a/hippo4j-example/hippo4j-spring-boot-starter-example/src/main/resources/application.properties b/hippo4j-example/hippo4j-spring-boot-starter-example/src/main/resources/application.properties
index 3d283f86..8d3ade56 100644
--- a/hippo4j-example/hippo4j-spring-boot-starter-example/src/main/resources/application.properties
+++ b/hippo4j-example/hippo4j-spring-boot-starter-example/src/main/resources/application.properties
@@ -24,3 +24,20 @@ spring.dynamic.thread-pool.monitor.collect-types=server,micrometer
spring.dynamic.thread-pool.monitor.thread-pool-types=dynamic,web
spring.dynamic.thread-pool.monitor.initial-delay=10000
spring.dynamic.thread-pool.monitor.collect-interval=5000
+
+# for email notify
+## simple example
+spring.mail.host=smtp.qq.com
+spring.mail.username=xxx@qq.com
+spring.mail.password=xxx
+
+## for gmail need ssl
+#spring.mail.host=smtp.gmail.com
+#spring.mail.username=xxx@gmail.com
+#spring.mail.password=xxx
+#spring.mail.protocol=smtp
+#spring.mail.properties.mail.smtp.auth=true
+#spring.mail.properties.mail.smtp.port=465
+#spring.mail.properties.mail.smtp.starttls.enable=true
+#spring.mail.properties.mail.smtp.starttls.required=true
+#spring.mail.properties.mail.smtp.ssl.enable=true
diff --git a/hippo4j-message/pom.xml b/hippo4j-message/pom.xml
index 3ee8b786..f4e52c77 100644
--- a/hippo4j-message/pom.xml
+++ b/hippo4j-message/pom.xml
@@ -37,8 +37,12 @@
test
- com.sun.mail
- javax.mail
+ org.springframework.boot
+ spring-boot-starter-mail
+
+
+ org.freemarker
+ freemarker
@@ -49,6 +53,7 @@
**/*.txt
**/*.json
+ **/*.ftl
diff --git a/hippo4j-message/src/main/java/cn/hippo4j/message/enums/NotifyPlatformEnum.java b/hippo4j-message/src/main/java/cn/hippo4j/message/enums/NotifyPlatformEnum.java
index 6faa4819..0d5aa7c3 100644
--- a/hippo4j-message/src/main/java/cn/hippo4j/message/enums/NotifyPlatformEnum.java
+++ b/hippo4j-message/src/main/java/cn/hippo4j/message/enums/NotifyPlatformEnum.java
@@ -38,7 +38,7 @@ public enum NotifyPlatformEnum {
WECHAT,
/**
- * Email
+ * EMAIL
*/
- Email
+ EMAIL
}
diff --git a/hippo4j-message/src/main/java/cn/hippo4j/message/platform/EmailSendMessageHandler.java b/hippo4j-message/src/main/java/cn/hippo4j/message/platform/EmailSendMessageHandler.java
index a40e83b4..a7d3e003 100644
--- a/hippo4j-message/src/main/java/cn/hippo4j/message/platform/EmailSendMessageHandler.java
+++ b/hippo4j-message/src/main/java/cn/hippo4j/message/platform/EmailSendMessageHandler.java
@@ -17,158 +17,109 @@
package cn.hippo4j.message.platform;
-import cn.hippo4j.common.toolkit.Assert;
import cn.hippo4j.common.toolkit.FileUtil;
-import cn.hippo4j.common.toolkit.JSONUtil;
import cn.hippo4j.common.toolkit.Singleton;
import cn.hippo4j.message.dto.NotifyConfigDTO;
import cn.hippo4j.message.enums.NotifyPlatformEnum;
-import cn.hippo4j.message.platform.base.AbstractRobotSendMessageHandler;
-import cn.hippo4j.message.platform.base.RobotMessageActualContent;
-import cn.hippo4j.message.platform.base.RobotMessageExecuteDTO;
-import lombok.Data;
+import cn.hippo4j.message.platform.constant.EmailAlarmConstants;
+import cn.hippo4j.message.request.AlarmNotifyRequest;
+import cn.hippo4j.message.request.ChangeParameterNotifyRequest;
+import cn.hippo4j.message.service.SendMessageHandler;
+import freemarker.cache.StringTemplateLoader;
+import freemarker.template.Configuration;
+import freemarker.template.Template;
+import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.beanutils.BeanUtils;
+import org.springframework.boot.autoconfigure.mail.MailProperties;
+import org.springframework.mail.javamail.JavaMailSender;
+import org.springframework.mail.javamail.MimeMessageHelper;
-import javax.mail.*;
-import javax.mail.internet.InternetAddress;
-import javax.mail.internet.MimeBodyPart;
+import javax.annotation.Resource;
+import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
-import javax.mail.internet.MimeMultipart;
-import java.nio.charset.Charset;
-import java.util.*;
-
-import static cn.hippo4j.message.platform.constant.EmailAlarmConstants.Email_ALARM_TITLE;
-import static cn.hippo4j.message.platform.constant.EmailAlarmConstants.Email_NOTICE_TITLE;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.Map;
/**
* Send Email notification message.
*/
@Slf4j
-public class EmailSendMessageHandler extends AbstractRobotSendMessageHandler {
+public class EmailSendMessageHandler implements SendMessageHandler {
+
+ @Resource
+ private JavaMailSender emailSender;
+
+ @Resource
+ MailProperties mailProperties;
@Override
public String getType() {
- return NotifyPlatformEnum.Email.name();
+ return NotifyPlatformEnum.EMAIL.name();
}
@Override
- protected RobotMessageActualContent buildMessageActualContent() {
- String emailAlarmTxtKey = "message/robot/dynamic-thread-pool/email-alarm.txt";
- String emailConfigTxtKey = "message/robot/dynamic-thread-pool/email-config.txt";
- return RobotMessageActualContent.builder()
- .receiveSeparator(", @")
- .changeSeparator(" -> ")
- .alarmMessageContent(Singleton.get(emailAlarmTxtKey, () -> FileUtil.readUtf8String(emailAlarmTxtKey)))
- .configMessageContent(Singleton.get(emailConfigTxtKey, () -> FileUtil.readUtf8String(emailConfigTxtKey)))
- .build();
+ public void sendAlarmMessage(NotifyConfigDTO notifyConfig, AlarmNotifyRequest alarmNotifyRequest) {
+ try {
+ String emailAlarmTxtKey = "message/robot/dynamic-thread-pool/email-alarm.ftl";
+ Map dataModel = getDataModel(alarmNotifyRequest);
+ dataModel.put("interval", notifyConfig.getInterval().toString());
+ String emailAlarmTxt = Singleton.get(emailAlarmTxtKey, () -> FileUtil.readUtf8String(emailAlarmTxtKey));
+ String renderedEmailAlarmTxt = render(dataModel, emailAlarmTxt);
+ String[] recipients = notifyConfig.getReceives().split(",");
+ execute(recipients, EmailAlarmConstants.Email_ALARM_TITLE, renderedEmailAlarmTxt);
+ } catch (Exception e) {
+ log.error("Email failed to send message", e);
+ }
}
@Override
- protected void execute(RobotMessageExecuteDTO robotMessageExecuteDTO) {
-
- NotifyConfigDTO notifyConfig = robotMessageExecuteDTO.getNotifyConfig();
- String content = robotMessageExecuteDTO.getText();
- String receives = notifyConfig.getReceives();
- String secretKey = notifyConfig.getSecretKey();
- String[] recipients = receives.split(",");
-
- MailAccount mailAccount = JSONUtil.parseObject(secretKey, MailAccount.class);
- Assert.isTrue(mailAccount != null, "mailAccount is null");
- mailAccount.setUser(mailAccount.getFrom());
- String subject = Objects.equals(notifyConfig.getType(), "CONFIG") ? Email_NOTICE_TITLE : Email_ALARM_TITLE;
+ public void sendChangeMessage(NotifyConfigDTO notifyConfig, ChangeParameterNotifyRequest changeParameterNotifyRequest) {
try {
- MimeMessage mimeMessage = buildMsg(mailAccount, recipients, subject, content);
- Transport.send(mimeMessage);
- } catch (Exception ex) {
- log.error("Email failed to send message", ex);
+ String emailConfigTxtKey = "message/robot/dynamic-thread-pool/email-config.ftl";
+ Map dataModel = getDataModel(changeParameterNotifyRequest);
+ String emailAlarmTxt = Singleton.get(emailConfigTxtKey, () -> FileUtil.readUtf8String(emailConfigTxtKey));
+ String renderedEmailAlarmTxt = render(dataModel, emailAlarmTxt);
+ String[] recipients = notifyConfig.getReceives().split(",");
+ execute(recipients, EmailAlarmConstants.Email_NOTICE_TITLE, renderedEmailAlarmTxt);
+ } catch (Exception e) {
+ log.error("Email failed to send message", e);
}
}
- private MimeMessage buildMsg(MailAccount mailAccount, String[] recipients, String subject, String content) throws MessagingException {
-
- UserPassAuthenticator authenticator = new UserPassAuthenticator(mailAccount.getUser(), mailAccount.getPass());
- Properties properties = new Properties();
- properties.put("mail.transport.protocol", mailAccount.getHost().split("\\.")[0]);
- properties.put("mail.smtp.host", mailAccount.getHost());
- properties.put("mail.smtp.port", mailAccount.getPort());
- properties.put("mail.smtp.auth", "true");
- Session session = Session.getInstance(properties, authenticator);
-
- MimeMessage msg = new MimeMessage(session);
- // 发件人
- String from = mailAccount.getFrom();
- msg.setFrom(from);
- // 标题
- msg.setSubject(subject);
- // 发送时间
- msg.setSentDate(new Date());
- // 内容和附件
- MimeMultipart mimeMultipart = new MimeMultipart();
- MimeBodyPart body = new MimeBodyPart();
- body.setContent(content, "text/html; charset=" + Charset.defaultCharset());
- mimeMultipart.addBodyPart(body);
- msg.setContent(mimeMultipart);
-
- // 收件人
- List addressList = new ArrayList<>(recipients.length);
- for (String recipient : recipients) {
- Address to = new InternetAddress(recipient);
- addressList.add(to);
+ private String render(Map dataModel, String stringTemplate) {
+ Configuration cfg = new Configuration(Configuration.VERSION_2_3_31);
+ StringTemplateLoader stringLoader = new StringTemplateLoader();
+ stringLoader.putTemplate("renderTemplate", stringTemplate);
+ cfg.setTemplateLoader(stringLoader);
+ Writer out = new StringWriter(2048);
+ try {
+ Template tpl = cfg.getTemplate("renderTemplate", "UTF-8");
+ tpl.process(dataModel, out);
+ } catch (Exception e) {
+ log.error("failed to render template,dataModel:{},stringTemplate:{}", dataModel, stringTemplate);
}
- Address[] addresses = addressList.toArray(new Address[0]);
- msg.setRecipients(MimeMessage.RecipientType.TO, addresses);
- return msg;
+ return out.toString();
}
- @Data
- private static class MailAccount {
-
- /**
- * SMTP服务器域名
- */
- private String host;
- /**
- * SMTP服务端口
- */
- private Integer port;
- /**
- * 是否需要用户名密码验证
- */
- private Boolean auth;
- /**
- * 用户名
- */
- private String user;
- /**
- * 密码
- */
- private String pass;
-
- /**
- * 发送方
- */
- private String from;
+ @SneakyThrows
+ private Map getDataModel(Object bean) {
+ Map dataModel = BeanUtils.describe(bean);
+ dataModel.put("from", mailProperties.getUsername());
+ dataModel.put("date", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
+ return dataModel;
}
- private static class UserPassAuthenticator extends Authenticator {
-
- private final String user;
- private final String pass;
-
- /**
- * 构造
- *
- * @param user 用户名
- * @param pass 密码
- */
- public UserPassAuthenticator(String user, String pass) {
- this.user = user;
- this.pass = pass;
- }
-
- @Override
- protected PasswordAuthentication getPasswordAuthentication() {
- return new PasswordAuthentication(this.user, this.pass);
- }
+ private void execute(String[] to, String subject, String htmlBody) throws MessagingException {
+ MimeMessage message = emailSender.createMimeMessage();
+ MimeMessageHelper helper = new MimeMessageHelper(message, "UTF-8");
+ helper.setFrom(mailProperties.getUsername());
+ helper.setTo(to);
+ helper.setSubject(subject);
+ helper.setText(htmlBody, true);
+ emailSender.send(message);
}
}
\ No newline at end of file
diff --git a/hippo4j-message/src/main/resources/message/robot/dynamic-thread-pool/email-alarm.ftl b/hippo4j-message/src/main/resources/message/robot/dynamic-thread-pool/email-alarm.ftl
new file mode 100644
index 00000000..42a0c04d
--- /dev/null
+++ b/hippo4j-message/src/main/resources/message/robot/dynamic-thread-pool/email-alarm.ftl
@@ -0,0 +1,27 @@
+
+[警报] ${active} - 动态线程池运行告警(${notifyTypeEnum})
+
+ - 线程池ID:${threadPoolId}
+ - 应用名称:${appName}
+ - 应用实例:${identify}
+ - 核心线程数:${corePoolSize}
+ - 最大线程数:${maximumPoolSize}
+ - 当前线程数:${poolSize}
+ - 活跃线程数:${activeCount}
+ - 同存最大线程数:${largestPoolSize}
+ - 线程池任务总量:${completedTaskCount}
+ - 队列类型:${queueName}
+ - 队列容量:${capacity}
+ - 队列元素个数:${queueSize}
+ - 队列剩余个数:${remainingCapacity}
+ - 拒绝策略:${rejectedExecutionHandlerName}
+ - 拒绝策略执行次数:${rejectCountNum}
+ - OWNER:${from}
+ - 提示:${interval} 分钟内此线程池不会重复告警(可配置)
+
+
+ 播报时间:${date}
\ No newline at end of file
diff --git a/hippo4j-message/src/main/resources/message/robot/dynamic-thread-pool/email-alarm.txt b/hippo4j-message/src/main/resources/message/robot/dynamic-thread-pool/email-alarm.txt
deleted file mode 100644
index 9e1d4a7b..00000000
--- a/hippo4j-message/src/main/resources/message/robot/dynamic-thread-pool/email-alarm.txt
+++ /dev/null
@@ -1,20 +0,0 @@
-[警报] %s - 动态线程池运行告警(%s)
- 线程池ID:%s
- 应用名称:%s
- 应用实例:%s
- 核心线程数:%s
- 最大线程数:%s
- 当前线程数:%s
- 活跃线程数:%s
- 同存最大线程数:%s
- 线程池任务总量:%s
- 队列类型:%s
- 队列容量:%s
- 队列元素个数:%s
- 队列剩余个数:%s
- 拒绝策略:%s
- 拒绝策略执行次数:%s ${timout-content}
- OWNER:<@%s>
- 提示:%d 分钟内此线程池不会重复告警(可配置)
-
- 播报时间:%s
\ No newline at end of file
diff --git a/hippo4j-message/src/main/resources/message/robot/dynamic-thread-pool/email-config.ftl b/hippo4j-message/src/main/resources/message/robot/dynamic-thread-pool/email-config.ftl
new file mode 100644
index 00000000..3f6ad711
--- /dev/null
+++ b/hippo4j-message/src/main/resources/message/robot/dynamic-thread-pool/email-config.ftl
@@ -0,0 +1,21 @@
+
+[通知] ${active} - 动态线程池参数变更
+
+ - 线程池ID:${threadPoolId}
+ - 应用名称:${appName}
+ - 应用实例:${identify}
+ - 核心线程数:${beforeCorePoolSize} -> ${nowCorePoolSize}
+ - 核心线程超时:${beforeMaximumPoolSize} -> ${nowMaximumPoolSize}
+ - 线程存活时间:${beforeAllowsCoreThreadTimeOut} -> ${nowAllowsCoreThreadTimeOut}
+ - 执行超时时间:${beforeKeepAliveTime} -> ${nowKeepAliveTime}
+ - 队列类型:${blockingQueueName}
+ - 队列容量:${beforeQueueCapacity} -> ${nowQueueCapacity}
+ - AGO 拒绝策略:${beforeRejectedName}
+ - NOW 拒绝策略:${nowRejectedName}
+ - OWNER: ${from}
+ - 提示:动态线程池配置变更实时通知(无限制)
+
+
+ 播报时间:${date}
diff --git a/hippo4j-message/src/main/resources/message/robot/dynamic-thread-pool/email-config.txt b/hippo4j-message/src/main/resources/message/robot/dynamic-thread-pool/email-config.txt
deleted file mode 100644
index 492a76e6..00000000
--- a/hippo4j-message/src/main/resources/message/robot/dynamic-thread-pool/email-config.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-[通知] %s - 动态线程池参数变更
- 线程池ID:%s
- 应用名称:%s
- 应用实例:%s
- 核心线程数:%s
- 最大线程数:%s
- 核心线程超时:%s
- 线程存活时间:%s
- 执行超时时间:%s
- 队列类型:%s
- 队列容量:%s
- AGO 拒绝策略:%s
- NOW 拒绝策略:%s
- OWNER:<@%s>
- 提示:动态线程池配置变更实时通知(无限制)
-
- 播报时间:%s
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index cb9fff67..7b1bca48 100644
--- a/pom.xml
+++ b/pom.xml
@@ -95,7 +95,7 @@
3.0
2.22.1
3.1.0
- 1.6.2
+ 2.3.31
@@ -128,9 +128,9 @@
${netty.version}
- com.sun.mail
- javax.mail
- ${javax.mail.version}
+ org.freemarker
+ freemarker
+ ${freemarker.version}