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}