fix:use spring-boot-starter-mail to send msg

pull/923/head
baymax55 3 years ago
parent 0ecf204b9d
commit 3ef45f2b51

@ -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.thread-pool-types=dynamic,web
spring.dynamic.thread-pool.monitor.initial-delay=10000 spring.dynamic.thread-pool.monitor.initial-delay=10000
spring.dynamic.thread-pool.monitor.collect-interval=5000 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

@ -37,8 +37,12 @@
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.sun.mail</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>javax.mail</artifactId> <artifactId>spring-boot-starter-mail</artifactId>
</dependency>
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
</dependency> </dependency>
</dependencies> </dependencies>
@ -49,6 +53,7 @@
<includes> <includes>
<include>**/*.txt</include> <include>**/*.txt</include>
<include>**/*.json</include> <include>**/*.json</include>
<include>**/*.ftl</include>
</includes> </includes>
</resource> </resource>
</resources> </resources>

@ -38,7 +38,7 @@ public enum NotifyPlatformEnum {
WECHAT, WECHAT,
/** /**
* Email * EMAIL
*/ */
Email EMAIL
} }

@ -17,158 +17,109 @@
package cn.hippo4j.message.platform; package cn.hippo4j.message.platform;
import cn.hippo4j.common.toolkit.Assert;
import cn.hippo4j.common.toolkit.FileUtil; import cn.hippo4j.common.toolkit.FileUtil;
import cn.hippo4j.common.toolkit.JSONUtil;
import cn.hippo4j.common.toolkit.Singleton; import cn.hippo4j.common.toolkit.Singleton;
import cn.hippo4j.message.dto.NotifyConfigDTO; import cn.hippo4j.message.dto.NotifyConfigDTO;
import cn.hippo4j.message.enums.NotifyPlatformEnum; import cn.hippo4j.message.enums.NotifyPlatformEnum;
import cn.hippo4j.message.platform.base.AbstractRobotSendMessageHandler; import cn.hippo4j.message.platform.constant.EmailAlarmConstants;
import cn.hippo4j.message.platform.base.RobotMessageActualContent; import cn.hippo4j.message.request.AlarmNotifyRequest;
import cn.hippo4j.message.platform.base.RobotMessageExecuteDTO; import cn.hippo4j.message.request.ChangeParameterNotifyRequest;
import lombok.Data; 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 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.annotation.Resource;
import javax.mail.internet.InternetAddress; import javax.mail.MessagingException;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage; import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart; import java.io.StringWriter;
import java.nio.charset.Charset; import java.io.Writer;
import java.util.*; import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import static cn.hippo4j.message.platform.constant.EmailAlarmConstants.Email_ALARM_TITLE; import java.util.Map;
import static cn.hippo4j.message.platform.constant.EmailAlarmConstants.Email_NOTICE_TITLE;
/** /**
* Send Email notification message. * Send Email notification message.
*/ */
@Slf4j @Slf4j
public class EmailSendMessageHandler extends AbstractRobotSendMessageHandler { public class EmailSendMessageHandler implements SendMessageHandler<AlarmNotifyRequest, ChangeParameterNotifyRequest> {
@Resource
private JavaMailSender emailSender;
@Resource
MailProperties mailProperties;
@Override @Override
public String getType() { public String getType() {
return NotifyPlatformEnum.Email.name(); return NotifyPlatformEnum.EMAIL.name();
} }
@Override @Override
protected RobotMessageActualContent buildMessageActualContent() { public void sendAlarmMessage(NotifyConfigDTO notifyConfig, AlarmNotifyRequest alarmNotifyRequest) {
String emailAlarmTxtKey = "message/robot/dynamic-thread-pool/email-alarm.txt"; try {
String emailConfigTxtKey = "message/robot/dynamic-thread-pool/email-config.txt"; String emailAlarmTxtKey = "message/robot/dynamic-thread-pool/email-alarm.ftl";
return RobotMessageActualContent.builder() Map<String, String> dataModel = getDataModel(alarmNotifyRequest);
.receiveSeparator(", @") dataModel.put("interval", notifyConfig.getInterval().toString());
.changeSeparator(" -> ") String emailAlarmTxt = Singleton.get(emailAlarmTxtKey, () -> FileUtil.readUtf8String(emailAlarmTxtKey));
.alarmMessageContent(Singleton.get(emailAlarmTxtKey, () -> FileUtil.readUtf8String(emailAlarmTxtKey))) String renderedEmailAlarmTxt = render(dataModel, emailAlarmTxt);
.configMessageContent(Singleton.get(emailConfigTxtKey, () -> FileUtil.readUtf8String(emailConfigTxtKey))) String[] recipients = notifyConfig.getReceives().split(",");
.build(); execute(recipients, EmailAlarmConstants.Email_ALARM_TITLE, renderedEmailAlarmTxt);
} catch (Exception e) {
log.error("Email failed to send message", e);
}
} }
@Override @Override
protected void execute(RobotMessageExecuteDTO robotMessageExecuteDTO) { public void sendChangeMessage(NotifyConfigDTO notifyConfig, ChangeParameterNotifyRequest changeParameterNotifyRequest) {
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 { try {
MimeMessage mimeMessage = buildMsg(mailAccount, recipients, subject, content); String emailConfigTxtKey = "message/robot/dynamic-thread-pool/email-config.ftl";
Transport.send(mimeMessage); Map<String, String> dataModel = getDataModel(changeParameterNotifyRequest);
} catch (Exception ex) { String emailAlarmTxt = Singleton.get(emailConfigTxtKey, () -> FileUtil.readUtf8String(emailConfigTxtKey));
log.error("Email failed to send message", ex); 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 { private String render(Map<String, String> dataModel, String stringTemplate) {
Configuration cfg = new Configuration(Configuration.VERSION_2_3_31);
UserPassAuthenticator authenticator = new UserPassAuthenticator(mailAccount.getUser(), mailAccount.getPass()); StringTemplateLoader stringLoader = new StringTemplateLoader();
Properties properties = new Properties(); stringLoader.putTemplate("renderTemplate", stringTemplate);
properties.put("mail.transport.protocol", mailAccount.getHost().split("\\.")[0]); cfg.setTemplateLoader(stringLoader);
properties.put("mail.smtp.host", mailAccount.getHost()); Writer out = new StringWriter(2048);
properties.put("mail.smtp.port", mailAccount.getPort()); try {
properties.put("mail.smtp.auth", "true"); Template tpl = cfg.getTemplate("renderTemplate", "UTF-8");
Session session = Session.getInstance(properties, authenticator); tpl.process(dataModel, out);
} catch (Exception e) {
MimeMessage msg = new MimeMessage(session); log.error("failed to render template,dataModel:{},stringTemplate:{}", dataModel, stringTemplate);
// 发件人
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<Address> addressList = new ArrayList<>(recipients.length);
for (String recipient : recipients) {
Address to = new InternetAddress(recipient);
addressList.add(to);
} }
Address[] addresses = addressList.toArray(new Address[0]); return out.toString();
msg.setRecipients(MimeMessage.RecipientType.TO, addresses);
return msg;
} }
@Data @SneakyThrows
private static class MailAccount { private Map<String, String> getDataModel(Object bean) {
Map<String, String> dataModel = BeanUtils.describe(bean);
/** dataModel.put("from", mailProperties.getUsername());
* SMTP dataModel.put("date", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
*/ return dataModel;
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 void execute(String[] to, String subject, String htmlBody) throws MessagingException {
MimeMessage message = emailSender.createMimeMessage();
private final String user; MimeMessageHelper helper = new MimeMessageHelper(message, "UTF-8");
private final String pass; helper.setFrom(mailProperties.getUsername());
helper.setTo(to);
/** helper.setSubject(subject);
* helper.setText(htmlBody, true);
* emailSender.send(message);
* @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);
}
} }
} }

@ -0,0 +1,27 @@
<style>
li {
list-style-type: none;
}
</style>
<span style="color: rgb(255, 0, 0);">[警报] </span>${active} - 动态线程池运行告警(${notifyTypeEnum}
<ul>
<li>线程池ID<span style="color: rgb(160, 0, 0);">${threadPoolId}</span></li>
<li>应用名称:<span style="color: rgb(160, 0, 0);">${appName}</span></li>
<li>应用实例:${identify}</li>
<li>核心线程数:${corePoolSize}</li>
<li>最大线程数:${maximumPoolSize}</li>
<li>当前线程数:${poolSize}</li>
<li>活跃线程数:${activeCount}</li>
<li>同存最大线程数:${largestPoolSize}</li>
<li>线程池任务总量:${completedTaskCount}</li>
<li>队列类型:${queueName}</li>
<li>队列容量:${capacity}</li>
<li>队列元素个数:${queueSize}</li>
<li>队列剩余个数:${remainingCapacity}</li>
<li>拒绝策略:${rejectedExecutionHandlerName}</li>
<li>拒绝策略执行次数:<span style="color: #FF0000; ">${rejectCountNum}</li>
<li>OWNER${from}</li>
<li>提示:${interval} 分钟内此线程池不会重复告警(可配置)</li>
</ul>
<b> 播报时间:${date} </b>

@ -1,20 +0,0 @@
<font color='#FF0000'>[警报] </font>%s - 动态线程池运行告警(%s <br/>
线程池ID<font color='warning'>%s</font> <br/>
应用名称:<font color='warning'>%s</font> <br/>
应用实例:%s <br/>
核心线程数:%s <br/>
最大线程数:%s <br/>
当前线程数:%s <br/>
活跃线程数:%s <br/>
同存最大线程数:%s <br/>
线程池任务总量:%s <br/>
队列类型:%s <br/>
队列容量:%s <br/>
队列元素个数:%s <br/>
队列剩余个数:%s <br/>
拒绝策略:%s <br/>
拒绝策略执行次数:<font color='#FF0000'>%s</font> ${timout-content} <br/>
OWNER<@%s> <br/>
提示:%d 分钟内此线程池不会重复告警(可配置)<br/>
<b> 播报时间:%s </b>

@ -0,0 +1,21 @@
<style>
li{list-style-type:none;}
</style>
<span style="color: rgb(0, 240, 0); ">[通知] </span>${active} - 动态线程池参数变更
<ul>
<li>线程池ID<span style="color: rgb(160, 0, 0);">${threadPoolId}</span></li>
<li>应用名称:<span style="color: rgb(160, 0, 0);">${appName}</span></li>
<li>应用实例:${identify}</li>
<li>核心线程数:${beforeCorePoolSize} -> ${nowCorePoolSize}</li>
<li>核心线程超时:${beforeMaximumPoolSize} -> ${nowMaximumPoolSize}</li>
<li>线程存活时间:${beforeAllowsCoreThreadTimeOut} -> ${nowAllowsCoreThreadTimeOut}</li>
<li>执行超时时间:${beforeKeepAliveTime} -> ${nowKeepAliveTime}</li>
<li>队列类型:${blockingQueueName}</li>
<li>队列容量:${beforeQueueCapacity} -> ${nowQueueCapacity}</li>
<li>AGO 拒绝策略:${beforeRejectedName}</li>
<li>NOW 拒绝策略:${nowRejectedName}</li>
<li>OWNER ${from}</li>
<li>提示:动态线程池配置变更实时通知(无限制)</li>
</ul>
<b> 播报时间:${date} </b>

@ -1,17 +0,0 @@
<font color='info'>[通知] </font>%s - 动态线程池参数变更 <br/>
线程池ID<font color='warning'>%s</font> <br/>
应用名称:<font color='warning'>%s</font> <br/>
应用实例:%s <br/>
核心线程数:%s <br/>
最大线程数:%s <br/>
核心线程超时:%s <br/>
线程存活时间:%s <br/>
执行超时时间:%s <br/>
队列类型:%s <br/>
队列容量:%s <br/>
AGO 拒绝策略:%s <br/>
NOW 拒绝策略:%s <br/>
OWNER<@%s> <br/>
提示:动态线程池配置变更实时通知(无限制) <br/>
<b> 播报时间:%s </b>

@ -95,7 +95,7 @@
<license-maven-plugin.version>3.0</license-maven-plugin.version> <license-maven-plugin.version>3.0</license-maven-plugin.version>
<spotless-maven-plugin.version>2.22.1</spotless-maven-plugin.version> <spotless-maven-plugin.version>2.22.1</spotless-maven-plugin.version>
<maven-checkstyle-plugin.version>3.1.0</maven-checkstyle-plugin.version> <maven-checkstyle-plugin.version>3.1.0</maven-checkstyle-plugin.version>
<javax.mail.version>1.6.2</javax.mail.version> <freemarker.version>2.3.31</freemarker.version>
</properties> </properties>
<dependencyManagement> <dependencyManagement>
@ -128,9 +128,9 @@
<version>${netty.version}</version> <version>${netty.version}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.sun.mail</groupId> <groupId>org.freemarker</groupId>
<artifactId>javax.mail</artifactId> <artifactId>freemarker</artifactId>
<version>${javax.mail.version}</version> <version>${freemarker.version}</version>
</dependency> </dependency>
</dependencies> </dependencies>
</dependencyManagement> </dependencyManagement>

Loading…
Cancel
Save