From 65ee256a1b9081e410a27258fca8e75667d99255 Mon Sep 17 00:00:00 2001 From: baymax55 Date: Thu, 3 Nov 2022 16:00:57 +0800 Subject: [PATCH] feat: add email support for send msg when TP' CONFIG or ALARM are triggered --- hippo4j-message/pom.xml | 4 + .../message/config/MessageConfiguration.java | 6 + .../message/enums/NotifyPlatformEnum.java | 7 +- .../platform/EmailSendMessageHandler.java | 174 ++++++++++++++++++ .../constant/EmailAlarmConstants.java | 34 ++++ .../robot/dynamic-thread-pool/email-alarm.txt | 20 ++ .../dynamic-thread-pool/email-config.txt | 17 ++ pom.xml | 6 + 8 files changed, 267 insertions(+), 1 deletion(-) create mode 100644 hippo4j-message/src/main/java/cn/hippo4j/message/platform/EmailSendMessageHandler.java create mode 100644 hippo4j-message/src/main/java/cn/hippo4j/message/platform/constant/EmailAlarmConstants.java create mode 100644 hippo4j-message/src/main/resources/message/robot/dynamic-thread-pool/email-alarm.txt create mode 100644 hippo4j-message/src/main/resources/message/robot/dynamic-thread-pool/email-config.txt diff --git a/hippo4j-message/pom.xml b/hippo4j-message/pom.xml index b32e2992..0a666cac 100644 --- a/hippo4j-message/pom.xml +++ b/hippo4j-message/pom.xml @@ -40,6 +40,10 @@ spring-boot-starter-test test + + com.sun.mail + javax.mail + diff --git a/hippo4j-message/src/main/java/cn/hippo4j/message/config/MessageConfiguration.java b/hippo4j-message/src/main/java/cn/hippo4j/message/config/MessageConfiguration.java index e495cfe4..63899819 100644 --- a/hippo4j-message/src/main/java/cn/hippo4j/message/config/MessageConfiguration.java +++ b/hippo4j-message/src/main/java/cn/hippo4j/message/config/MessageConfiguration.java @@ -19,6 +19,7 @@ package cn.hippo4j.message.config; import cn.hippo4j.message.api.NotifyConfigBuilder; import cn.hippo4j.message.platform.DingSendMessageHandler; +import cn.hippo4j.message.platform.EmailSendMessageHandler; import cn.hippo4j.message.platform.LarkSendMessageHandler; import cn.hippo4j.message.platform.WeChatSendMessageHandler; import cn.hippo4j.message.service.AlarmControlHandler; @@ -57,4 +58,9 @@ public class MessageConfiguration { public SendMessageHandler weChatSendMessageHandler() { return new WeChatSendMessageHandler(); } + + @Bean + public EmailSendMessageHandler emailSendMessageHandler() { + return new EmailSendMessageHandler(); + } } 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 5ffbad3b..6faa4819 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 @@ -35,5 +35,10 @@ public enum NotifyPlatformEnum { /** * WECHAT */ - WECHAT + WECHAT, + + /** + * 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 new file mode 100644 index 00000000..89ea0861 --- /dev/null +++ b/hippo4j-message/src/main/java/cn/hippo4j/message/platform/EmailSendMessageHandler.java @@ -0,0 +1,174 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +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 lombok.extern.slf4j.Slf4j; + +import javax.mail.*; +import javax.mail.internet.InternetAddress; +import javax.mail.internet.MimeBodyPart; +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; + +/** + * Send Email notification message. + */ +@Slf4j +public class EmailSendMessageHandler extends AbstractRobotSendMessageHandler { + + @Override + public String getType() { + 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(); + } + + @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; + try { + MimeMessage mimeMessage = buildMsg(mailAccount, recipients, subject, content); + Transport.send(mimeMessage); + } catch (Exception ex) { + log.error("Email failed to send message", ex); + } + } + + 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", "smtp"); + 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); + } + Address[] addresses = addressList.toArray(new Address[0]); + msg.setRecipients(MimeMessage.RecipientType.TO, addresses); + return msg; + } + + @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; + } + + 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); + } + } +} \ No newline at end of file diff --git a/hippo4j-message/src/main/java/cn/hippo4j/message/platform/constant/EmailAlarmConstants.java b/hippo4j-message/src/main/java/cn/hippo4j/message/platform/constant/EmailAlarmConstants.java new file mode 100644 index 00000000..3daa24ac --- /dev/null +++ b/hippo4j-message/src/main/java/cn/hippo4j/message/platform/constant/EmailAlarmConstants.java @@ -0,0 +1,34 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.hippo4j.message.platform.constant; + +/** + * Email alarm constants. + */ +public class EmailAlarmConstants { + + /** + * Thread Pool Alert Notification Title + */ + public static final String Email_ALARM_TITLE = "动态线程池告警"; + + /** + * Thread pool parameter change notification title + */ + public static final String Email_NOTICE_TITLE = "动态线程池通知"; +} \ 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 new file mode 100644 index 00000000..9e1d4a7b --- /dev/null +++ b/hippo4j-message/src/main/resources/message/robot/dynamic-thread-pool/email-alarm.txt @@ -0,0 +1,20 @@ +[警报] %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.txt b/hippo4j-message/src/main/resources/message/robot/dynamic-thread-pool/email-config.txt new file mode 100644 index 00000000..492a76e6 --- /dev/null +++ b/hippo4j-message/src/main/resources/message/robot/dynamic-thread-pool/email-config.txt @@ -0,0 +1,17 @@ +[通知] %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 2973722a..24051620 100644 --- a/pom.xml +++ b/pom.xml @@ -97,6 +97,7 @@ 3.0 2.22.1 3.1.0 + 1.6.2 @@ -179,6 +180,11 @@ netty-all ${netty.version} + + com.sun.mail + javax.mail + ${javax.mail.version} +