Compare commits

...

2 Commits

Author SHA1 Message Date
hanxuanyu ca65b5e8fc 修复notify中mail模块的bug 2022-01-24 20:57:21 +08:00
hanxuanyu baccb20c3c 修复notify中mail模块的bug 2022-01-24 20:43:33 +08:00
8 changed files with 223 additions and 301 deletions

View File

@ -0,0 +1,108 @@
package com.hxuanyu.notify.config;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* @author hxuanyu
*/
@ConfigurationProperties(prefix = "notify.mail")
@ConditionalOnProperty(prefix = "notify.mail", havingValue = "true")
public class MailProperties {
private static final Charset DEFAULT_CHARSET;
private String host;
private Integer port;
private String username;
private String password;
private String protocol = "smtp";
private Charset defaultEncoding;
private Map<String, String> properties;
private String jndiName;
private Integer interval = 10000;
public MailProperties() {
this.defaultEncoding = DEFAULT_CHARSET;
this.properties = new HashMap();
}
public void setProperties(Map<String, String> properties) {
this.properties = properties;
}
public Integer getInterval() {
return interval;
}
public void setInterval(Integer interval) {
this.interval = interval;
}
public String getHost() {
return this.host;
}
public void setHost(String host) {
this.host = host;
}
public Integer getPort() {
return this.port;
}
public void setPort(Integer port) {
this.port = port;
}
public String getUsername() {
return this.username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return this.password;
}
public void setPassword(String password) {
this.password = password;
}
public String getProtocol() {
return this.protocol;
}
public void setProtocol(String protocol) {
this.protocol = protocol;
}
public Charset getDefaultEncoding() {
return this.defaultEncoding;
}
public void setDefaultEncoding(Charset defaultEncoding) {
this.defaultEncoding = defaultEncoding;
}
public Map<String, String> getProperties() {
return this.properties;
}
public void setJndiName(String jndiName) {
this.jndiName = jndiName;
}
public String getJndiName() {
return this.jndiName;
}
static {
DEFAULT_CHARSET = StandardCharsets.UTF_8;
}
}

View File

@ -1,19 +1,57 @@
package com.hxuanyu.notify.config; package com.hxuanyu.notify.config;
import com.google.common.util.concurrent.ThreadFactoryBuilder; import com.google.common.util.concurrent.ThreadFactoryBuilder;
import org.springframework.context.annotation.Bean; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.ComponentScan; import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.*;
import org.springframework.context.annotation.ImportResource; import org.springframework.mail.javamail.JavaMailSenderImpl;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.*; import java.util.concurrent.*;
/** /**
* @author hxuanyu * @author hxuanyu
*/ */
@Configuration @Configuration
@ComponentScan("com.hxuanyu.notify.service") @ComponentScan("com.hxuanyu.notify")
@EnableConfigurationProperties(MailProperties.class)
public class NotifyConfiguration { public class NotifyConfiguration {
@Autowired
MailProperties mailProperties;
@Bean
JavaMailSenderImpl mailSender(MailProperties properties) {
JavaMailSenderImpl sender = new JavaMailSenderImpl();
this.applyProperties(properties, sender);
return sender;
}
private void applyProperties(MailProperties properties, JavaMailSenderImpl sender) {
sender.setHost(properties.getHost());
if (properties.getPort() != null) {
sender.setPort(properties.getPort());
}
sender.setUsername(properties.getUsername());
sender.setPassword(properties.getPassword());
sender.setProtocol(properties.getProtocol());
if (properties.getDefaultEncoding() != null) {
sender.setDefaultEncoding(properties.getDefaultEncoding().name());
}
if (!properties.getProperties().isEmpty()) {
sender.setJavaMailProperties(this.asProperties(properties.getProperties()));
}
}
private Properties asProperties(Map<String, String> source) {
Properties properties = new Properties();
properties.putAll(source);
return properties;
}
@Bean(name = "mailExecutorService") @Bean(name = "mailExecutorService")
public ExecutorService mailExecutorService() { public ExecutorService mailExecutorService() {
// 使用 ThreadFactoryBuilder 创建自定义线程名称的 ThreadFactory // 使用 ThreadFactoryBuilder 创建自定义线程名称的 ThreadFactory

View File

@ -2,18 +2,19 @@ package com.hxuanyu.notify.service.impl;
import com.hxuanyu.notify.common.MailQueue; import com.hxuanyu.notify.common.MailQueue;
import com.hxuanyu.notify.config.MailProperties;
import com.hxuanyu.notify.model.Mail; import com.hxuanyu.notify.model.Mail;
import com.hxuanyu.notify.service.MailService; import com.hxuanyu.notify.service.MailService;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.mail.javamail.JavaMailSender; import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.mail.javamail.MimeMessageHelper; import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context;
import javax.annotation.PostConstruct; import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy; import javax.annotation.PreDestroy;
@ -27,15 +28,14 @@ import java.util.concurrent.ExecutorService;
*/ */
@Service @Service
public class MailServiceImpl implements MailService { public class MailServiceImpl implements MailService {
@Resource
MailProperties mailProperties;
private static final Logger logger = LoggerFactory.getLogger(MailServiceImpl.class); private static final Logger logger = LoggerFactory.getLogger(MailServiceImpl.class);
private static boolean isRunning = true; private static boolean isRunning = true;
ExecutorService executor; ExecutorService executor;
@Resource
private JavaMailSender javaMailSender;
private static JavaMailSender javaMailSender;
private static TemplateEngine templateEngine;
private static String defaultFrom;
@ -45,7 +45,7 @@ public class MailServiceImpl implements MailService {
executor.submit(new PollMail()); executor.submit(new PollMail());
} }
static class PollMail implements Runnable { class PollMail implements Runnable {
@Override @Override
public void run() { public void run() {
while (isRunning) { while (isRunning) {
@ -55,7 +55,7 @@ public class MailServiceImpl implements MailService {
if (mail != null) { if (mail != null) {
//可以设置延时 以及重复校验等等操作 //可以设置延时 以及重复校验等等操作
sendMailSync(mail); sendMailSync(mail);
Thread.sleep(10000); Thread.sleep(mailProperties.getInterval());
} }
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
@ -71,10 +71,14 @@ public class MailServiceImpl implements MailService {
} }
private static void sendMailSync(Mail mail) { private void sendMailSync(Mail mail) {
if (mailProperties == null){
logger.error("未配置邮件信息,请在配置文件中添加配置信息后再发送邮件");
return;
}
String from = mail.getFrom(); String from = mail.getFrom();
if (from == null) { if (from == null) {
from = defaultFrom; from = mailProperties.getUsername();
logger.info("未传入发件人,从配置中读取:{}", from); logger.info("未传入发件人,从配置中读取:{}", from);
} }
MimeMessage mimeMessage; MimeMessage mimeMessage;
@ -87,12 +91,7 @@ public class MailServiceImpl implements MailService {
mimeMessageHelper.setFrom(from); mimeMessageHelper.setFrom(from);
mimeMessageHelper.setTo(mail.getTo()); mimeMessageHelper.setTo(mail.getTo());
mimeMessageHelper.setSubject(mail.getSubject()); mimeMessageHelper.setSubject(mail.getSubject());
// 利用 Thymeleaf 引擎渲染 HTML String content = mail.getContent();
Context context = new Context();
// 设置注入的变量
context.setVariable("templates/mail", mail);
// 模板设置为 "mail"
String content = templateEngine.process("templates/mail/mail", context);
// 设置邮件内容 // 设置邮件内容
// true 表示开启 html // true 表示开启 html
mimeMessageHelper.setText(content, true); mimeMessageHelper.setText(content, true);
@ -112,24 +111,9 @@ public class MailServiceImpl implements MailService {
} }
@Resource
public void setJavaMailSender(JavaMailSender javaMailSender) {
MailServiceImpl.javaMailSender = javaMailSender;
}
@Autowired @Autowired
public void setExecutor(@Qualifier("mailExecutorService") ExecutorService executor) { public void setExecutor(@Qualifier("mailExecutorService") ExecutorService executor) {
this.executor = executor; this.executor = executor;
} }
@Autowired
public void setTemplateEngine(TemplateEngine templateEngine) {
MailServiceImpl.templateEngine = templateEngine;
}
@Value("${spring.mail.username}")
public void setDefaultFrom(String defaultFrom) {
MailServiceImpl.defaultFrom = defaultFrom;
}
} }

View File

@ -6,6 +6,7 @@ import com.hxuanyu.notify.service.MailService;
import com.hxuanyu.notify.service.NotifyService; import com.hxuanyu.notify.service.NotifyService;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import javax.annotation.Resource; import javax.annotation.Resource;

View File

@ -0,0 +1,48 @@
{
"properties": [
{
"name": "notify.mail.host",
"type": "java.lang.String",
"description": "Description for notify.mail.host."
},
{
"name": "notify.mail.protocol",
"type": "java.lang.String",
"description": "Description for notify.mail.protocol."
},
{
"name": "notify.mail.default-encoding",
"type": "java.lang.String",
"description": "Description for notify.mail.default-encoding."
},
{
"name": "notify.mail.password",
"type": "java.lang.String",
"description": "Description for notify.mail.password."
},
{
"name": "notify.mail.username",
"type": "java.lang.String",
"description": "Description for notify.mail.username."
},
{
"name": "notify.mail.port",
"type": "java.lang.String",
"description": "Description for notify.mail.port."
},
{
"name": "notify.mail.properties.mail.debug",
"type": "java.lang.String",
"description": "Description for notify.mail.properties.mail.debug."
},
{
"name": "notify.mail.properties.mail.interval",
"type": "java.lang.String",
"description": "Description for notify.mail.properties.mail.debug."
},
{
"name": "notify.mail.properties.stmp.socketFactory.class",
"type": "java.lang.String",
"description": "Description for notify.mail.properties.stmp.socketFactory.class."
}
] }

View File

@ -1,129 +0,0 @@
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org">
<!--${government}-->
<!--${title}-->
<!--${suggestion}-->
<!--${deadline}-->
<!--${secret}-->
<!--${url}-->
<!--${officeName}-->
<!--${createTime}-->
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
<title>${title}</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.3.1/css/bootstrap.min.css">
<style>
.contact-clean {
background: #f1f7fc;
padding: 80px 0;
}
a {
text-decoration: none;
}
@media (max-width: 767px) {
.contact-clean {
padding: 20px 0;
}
}
.contact-clean form {
max-width: 480px;
width: 90%;
margin: 0 auto;
background-color: #ffffff;
padding: 40px;
border-radius: 4px;
color: #505e6c;
box-shadow: 1px 1px 5px rgba(0, 0, 0, 0.1);
}
@media (max-width: 767px) {
.contact-clean form {
padding: 30px;
}
}
.contact-clean h2 {
margin-top: 5px;
font-weight: bold;
font-size: 28px;
margin-bottom: 36px;
color: inherit;
}
.contact-clean .form-group:last-child {
margin-bottom: 5px;
}
.contact-clean form .form-control {
background: #fff;
border-radius: 2px;
box-shadow: 1px 1px 1px rgba(0, 0, 0, 0.05);
outline: none;
color: inherit;
padding-left: 12px;
height: 42px;
}
.contact-clean form .form-control:focus {
border: 1px solid #b2b2b2;
}
.contact-clean form textarea.form-control {
min-height: 100px;
max-height: 260px;
padding-top: 10px;
resize: vertical;
}
.contact-clean form .btn {
padding: 16px 32px;
border: none;
background: none;
box-shadow: none;
text-shadow: none;
opacity: 0.9;
text-transform: uppercase;
font-weight: bold;
font-size: 13px;
letter-spacing: 0.4px;
line-height: 1;
outline: none !important;
}
.contact-clean form .btn:hover {
opacity: 1;
}
.contact-clean form .btn:active {
transform: translateY(1px);
}
.contact-clean form .btn-primary {
background-color: #055ada !important;
margin-top: 15px;
color: #fff;
}
</style>
</head>
<body>
<div class="contact-clean">
<form method="post">
<h2 class="text-center" th:text="${mail.getSubject()}"></h2>
<p th:utext="${mail.getContent()}"></p>
<div class="alert alert-danger" role="alert">
<span>
<strong>注意</strong>本邮件由系统自动发送,请勿回复本邮件,如果邮件内容您并不知情,请忽略本邮件
</span>
</div>
</form>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.3.1/js/bootstrap.bundle.min.js"></script>
</body>
</html>

View File

@ -1,14 +1,15 @@
spring: notify:
mail: mail:
host: smtp.domain host: smtp.qq.com
protocol: smtp protocol: smtp
default-encoding: UTF-8 default-encoding: UTF-8
password: your_password password: your pwd
username: your_username username: your account
port: 587 port: 587
properties: properties:
mail: mail:
debug: false debug: false
stmp: stmp:
socketFactory: socketFactory:
class: javax.net.ssl.SSLSocketFactory class: javax.net.ssl.SSLSocketFactory
interval: 5000

View File

@ -1,129 +0,0 @@
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org">
<!--${government}-->
<!--${title}-->
<!--${suggestion}-->
<!--${deadline}-->
<!--${secret}-->
<!--${url}-->
<!--${officeName}-->
<!--${createTime}-->
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
<title>${title}</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.3.1/css/bootstrap.min.css">
<style>
.contact-clean {
background: #f1f7fc;
padding: 80px 0;
}
a {
text-decoration: none;
}
@media (max-width: 767px) {
.contact-clean {
padding: 20px 0;
}
}
.contact-clean form {
max-width: 480px;
width: 90%;
margin: 0 auto;
background-color: #ffffff;
padding: 40px;
border-radius: 4px;
color: #505e6c;
box-shadow: 1px 1px 5px rgba(0, 0, 0, 0.1);
}
@media (max-width: 767px) {
.contact-clean form {
padding: 30px;
}
}
.contact-clean h2 {
margin-top: 5px;
font-weight: bold;
font-size: 28px;
margin-bottom: 36px;
color: inherit;
}
.contact-clean .form-group:last-child {
margin-bottom: 5px;
}
.contact-clean form .form-control {
background: #fff;
border-radius: 2px;
box-shadow: 1px 1px 1px rgba(0, 0, 0, 0.05);
outline: none;
color: inherit;
padding-left: 12px;
height: 42px;
}
.contact-clean form .form-control:focus {
border: 1px solid #b2b2b2;
}
.contact-clean form textarea.form-control {
min-height: 100px;
max-height: 260px;
padding-top: 10px;
resize: vertical;
}
.contact-clean form .btn {
padding: 16px 32px;
border: none;
background: none;
box-shadow: none;
text-shadow: none;
opacity: 0.9;
text-transform: uppercase;
font-weight: bold;
font-size: 13px;
letter-spacing: 0.4px;
line-height: 1;
outline: none !important;
}
.contact-clean form .btn:hover {
opacity: 1;
}
.contact-clean form .btn:active {
transform: translateY(1px);
}
.contact-clean form .btn-primary {
background-color: #055ada !important;
margin-top: 15px;
color: #fff;
}
</style>
</head>
<body>
<div class="contact-clean">
<form method="post">
<h2 class="text-center" th:text="${mail.getSubject()}"></h2>
<p th:utext="${mail.getContent()}"></p>
<div class="alert alert-danger" role="alert">
<span>
<strong>注意</strong>本邮件由系统自动发送,请勿回复本邮件,如果邮件内容您并不知情,请忽略本邮件
</span>
</div>
</form>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.3.1/js/bootstrap.bundle.min.js"></script>
</body>
</html>