refactor: 调整邮件服务配置

This commit is contained in:
2024-05-31 00:22:01 +08:00
parent 774db91d19
commit ee30e861ff
5 changed files with 203 additions and 211 deletions

View File

@@ -0,0 +1,44 @@
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* 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 top.continew.starter.core.util;
import java.util.Map;
import java.util.Properties;
/**
* Map 工具类
*
* @author Charles7c
* @since 2.1.0
*/
public class MapUtils {
private MapUtils() {
}
/**
* 转换为 Properties 对象
*
* @param source 数据源
* @return Properties 对象
*/
public static Properties toProperties(Map<String, String> source) {
Properties properties = new Properties();
properties.putAll(source);
return properties;
}
}

View File

@@ -1,109 +0,0 @@
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* 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 top.continew.starter.messaging.mail.core;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.extra.spring.SpringUtil;
import jakarta.mail.Authenticator;
import jakarta.mail.PasswordAuthentication;
import jakarta.mail.Session;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import java.util.Properties;
/**
* 邮件发送器
*
* @author KAI
* @since 1.0.0
*/
public class DynamicMailSenderAutoConfiguration extends JavaMailSenderImpl {
private static final Logger log = LoggerFactory.getLogger(DynamicMailSenderAutoConfiguration.class);
// 邮件会话属性
private final Properties javaMailProperties;
/**
* 构造函数,使用给定的邮件会话属性初始化邮件发送器。
*
* @param javaMailProperties 邮件会话属性
*/
public DynamicMailSenderAutoConfiguration(Properties javaMailProperties) {
super(); // 调用父类的构造函数
this.javaMailProperties = javaMailProperties;
// 设置用户名和密码
setUsername(javaMailProperties.getProperty("mail.smtp.username"));
setPassword(javaMailProperties.getProperty("mail.smtp.password"));
// 设置默认编码
String defaultEncoding = javaMailProperties.getProperty("mail.default-encoding", "utf-8");
setDefaultEncoding(defaultEncoding);
}
/**
* 获取邮件会话。
*
* @return 邮件会话
*/
@Override
public Session getSession() {
if (ObjectUtil.isNotEmpty(javaMailProperties)) {
// 使用提供的身份验证器创建邮件会话
log.info("[ContiNew Starter] DynamicMailSenderAutoConfiguration creating session with properties: {}", javaMailProperties);
return Session.getInstance(javaMailProperties, new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
// 返回用户名和密码认证信息
return new PasswordAuthentication(javaMailProperties
.getProperty("mail.username"), javaMailProperties.getProperty("mail.password"));
}
});
}
// 如果没有提供属性,使用父类的会话
return super.getSession();
}
/**
* 创建默认的邮件发送器。
*
* @return 默认的邮件发送器
*/
public static JavaMailSender createDefault() {
return SpringUtil.getBean(JavaMailSender.class);
}
/**
* 根据邮件配置构建邮件发送器。
*
* @param mailConfig 邮件配置对象
* @return 构建的邮件发送器
*/
public static JavaMailSender build(MailConfig mailConfig) {
if (mailConfig != null) {
Properties properties = mailConfig.toJavaMailProperties();
log.info("[ContiNew Starter] DynamicMailSenderAutoConfiguration build with mailConfig");
return new DynamicMailSenderAutoConfiguration(properties);
} else {
log.error("[ContiNew Starter] Mail configuration is null, using default mail configuration.");
return createDefault();
}
}
}

View File

@@ -16,47 +16,51 @@
package top.continew.starter.messaging.mail.core; package top.continew.starter.messaging.mail.core;
import cn.hutool.core.map.MapUtil;
import top.continew.starter.core.util.validate.ValidationUtils; import top.continew.starter.core.util.validate.ValidationUtils;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.Map;
import java.util.Properties; import java.util.Properties;
/** /**
* 邮件配置 * 邮件配置
* *
* @author KAI * @author KAI
* @since 1.0.0 * @author Charles7c
* @since 2.1.0
*/ */
public class MailConfig { public class MailConfig {
/** private static final Charset DEFAULT_CHARSET;
* 邮件发送协议 (例如: smtp, smtps)
*/ public static final String DEFAULT_PROTOCOL = "smtp";
private String mailProtocol = "smtp";
/** /**
* SMTP 服务器地址 * 协议
*/ */
private String mailHost; private String protocol = DEFAULT_PROTOCOL;
/** /**
* SMTP 服务器端口 * 服务器地址
*/ */
private int mailPort; private String host;
/** /**
* SMTP 用户名 * 服务器端口
*/ */
private String mailUsername; private Integer port;
/** /**
* SMTP 授权码 * 用户名
*/ */
private String mailPassword; private String username;
/** /**
* 发件人邮箱地址 * 密码(授权码)
*/ */
private String mailFrom; private String password;
/** /**
* 是否启用 SSL 连接 * 是否启用 SSL 连接
@@ -66,54 +70,55 @@ public class MailConfig {
/** /**
* SSL 端口 * SSL 端口
*/ */
private int sslPort; private Integer sslPort;
public String getMailProtocol() { private Charset defaultEncoding;
return mailProtocol;
private final Map<String, String> properties;
public MailConfig() {
this.defaultEncoding = DEFAULT_CHARSET;
this.properties = MapUtil.newHashMap();
} }
public void setMailProtocol(String mailProtocol) { public String getProtocol() {
this.mailProtocol = mailProtocol; return protocol;
} }
public String getMailHost() { public void setProtocol(String protocol) {
return mailHost; this.protocol = protocol;
} }
public void setMailHost(String mailHost) { public String getHost() {
this.mailHost = mailHost; return host;
} }
public int getMailPort() { public void setHost(String host) {
return mailPort; this.host = host;
} }
public void setMailPort(int mailPort) { public Integer getPort() {
this.mailPort = mailPort; return port;
} }
public String getMailUsername() { public void setPort(Integer port) {
return mailUsername; this.port = port;
} }
public void setMailUsername(String mailUsername) { public String getUsername() {
this.mailUsername = mailUsername; return username;
} }
public String getMailPassword() { public void setUsername(String username) {
return mailPassword; this.username = username;
} }
public void setMailPassword(String mailPassword) { public String getPassword() {
this.mailPassword = mailPassword; return password;
} }
public String getMailFrom() { public void setPassword(String password) {
return mailFrom; this.password = password;
}
public void setMailFrom(String mailFrom) {
this.mailFrom = mailFrom;
} }
public boolean isSslEnabled() { public boolean isSslEnabled() {
@@ -124,62 +129,45 @@ public class MailConfig {
this.sslEnabled = sslEnabled; this.sslEnabled = sslEnabled;
} }
public int getSslPort() { public Integer getSslPort() {
return sslPort; return sslPort;
} }
public void setSslPort(int sslPort) { public void setSslPort(Integer sslPort) {
this.sslPort = sslPort; this.sslPort = sslPort;
} }
public Charset getDefaultEncoding() {
return defaultEncoding;
}
public void setDefaultEncoding(Charset defaultEncoding) {
this.defaultEncoding = defaultEncoding;
}
public Map<String, String> getProperties() {
return properties;
}
/** /**
* 将当前配置转换为 JavaMail 的 Properties 对象 * 将当前配置转换为 JavaMail 的 Properties 对象
* *
* @return 配置好的 Properties 对象 * @return Properties 对象
*/ */
public Properties toJavaMailProperties() { public Properties toJavaMailProperties() {
Properties javaMailProperties = new Properties(); Properties javaMailProperties = new Properties();
javaMailProperties.putAll(this.getProperties());
ValidationUtils.throwIf(!this.mailProtocol.equals("smtp"), "不支持的邮件发送协议: " + this.mailProtocol); javaMailProperties.put("mail.smtp.auth", true);
// 设置邮件发送协议 javaMailProperties.put("mail.smtp.ssl.enable", this.isSslEnabled());
javaMailProperties.put("mail.transport.protocol", this.mailProtocol.toLowerCase()); if (this.isSslEnabled()) {
ValidationUtils.throwIfNull(this.getSslPort(), "邮件配置错误SSL端口不能为空");
// 设置 SMTP 服务器地址
ValidationUtils.throwIfBlank(this.mailHost, "SMTP服务器地址不能为空");
javaMailProperties.put("mail.smtp.host", this.mailHost);
// 设置 SMTP 服务器端口
ValidationUtils.throwIfNull(this.mailPort, "SMTP服务端口不能为空");
javaMailProperties.put("mail.smtp.port", this.mailPort);
// 设置 SMTP 用户名
ValidationUtils.throwIfBlank(this.mailUsername, "SMTP用户名不能为空");
javaMailProperties.put("mail.smtp.user", this.mailUsername);
// 设置 SMTP 授权码
ValidationUtils.throwIfBlank(this.mailPassword, "SMTP授权码不能为空");
javaMailProperties.put("mail.smtp.password", this.mailPassword);
// 启用 SMTP 认证
javaMailProperties.put("mail.smtp.auth", "true");
// 设置 SSL 连接
javaMailProperties.put("mail.smtp.ssl.enable", this.sslEnabled);
// 设置默认发件人地址
ValidationUtils.throwIfBlank(this.mailFrom, "默认发件人地址不能为空");
javaMailProperties.put("mail.from", this.mailFrom);
// 设置默认编码为 UTF-8
javaMailProperties.put("mail.defaultEncoding", "utf-8");
// 如果启用 SSL设置 SSL Socket 工厂和端口
if (sslEnabled) {
ValidationUtils.throwIfNull(this.sslPort, "SSL端口不能为空");
javaMailProperties.put("mail.smtp.socketFactory.port", this.sslPort); javaMailProperties.put("mail.smtp.socketFactory.port", this.sslPort);
javaMailProperties.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory"); javaMailProperties.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
} }
return javaMailProperties; return javaMailProperties;
} }
static {
DEFAULT_CHARSET = StandardCharsets.UTF_8;
}
} }

View File

@@ -0,0 +1,69 @@
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* 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 top.continew.starter.messaging.mail.core;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import top.continew.starter.core.util.validate.ValidationUtils;
/**
* 邮件配置服务
*
* @author Charles7c
* @since 2.1.0
*/
public interface MailConfigService {
/**
* 获取邮件配置
*
* @return 邮件配置
*/
MailConfig getMailConfig();
/**
* 应用配置
*
* @param mailConfig 邮件配置
* @param sender 邮件 Sender
*/
default void apply(MailConfig mailConfig, JavaMailSenderImpl sender) {
String protocolLowerCase = mailConfig.getProtocol().toLowerCase();
ValidationUtils.throwIfNotEqual(MailConfig.DEFAULT_PROTOCOL, protocolLowerCase, "邮件配置错误:不支持的邮件发送协议: %s"
.formatted(mailConfig.getProtocol()));
sender.setProtocol(mailConfig.getProtocol());
ValidationUtils.throwIfBlank(mailConfig.getHost(), "邮件配置错误:服务器地址不能为空");
sender.setHost(mailConfig.getHost());
ValidationUtils.throwIfNull(mailConfig.getPort(), "邮件配置错误:服务器端口不能为空");
sender.setPort(mailConfig.getPort());
ValidationUtils.throwIfBlank(mailConfig.getUsername(), "邮件配置错误:用户名不能为空");
sender.setUsername(mailConfig.getUsername());
ValidationUtils.throwIfBlank(mailConfig.getPassword(), "邮件配置错误:密码不能为空");
sender.setPassword(mailConfig.getPassword());
if (mailConfig.getDefaultEncoding() != null) {
sender.setDefaultEncoding(mailConfig.getDefaultEncoding().name());
}
if (!mailConfig.getProperties().isEmpty()) {
sender.setJavaMailProperties(mailConfig.toJavaMailProperties());
}
}
}

View File

@@ -24,11 +24,11 @@ import cn.hutool.extra.spring.SpringUtil;
import jakarta.mail.MessagingException; import jakarta.mail.MessagingException;
import jakarta.mail.internet.MimeMessage; import jakarta.mail.internet.MimeMessage;
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.util.StringUtils;
import top.continew.starter.core.constant.StringConstants; import top.continew.starter.core.constant.StringConstants;
import top.continew.starter.messaging.mail.core.MailConfig; import top.continew.starter.core.util.ExceptionUtils;
import top.continew.starter.messaging.mail.core.DynamicMailSenderAutoConfiguration; import top.continew.starter.messaging.mail.core.MailConfigService;
import java.io.File; import java.io.File;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
@@ -45,12 +45,6 @@ import java.util.List;
public class MailUtils { public class MailUtils {
private static MailConfig mailConfig; // 邮件配置
public static void setMailConfig(MailConfig mailConfig) {
MailUtils.mailConfig = mailConfig;
}
private MailUtils() { private MailUtils() {
} }
@@ -165,20 +159,12 @@ public class MailUtils {
boolean isHtml, boolean isHtml,
File... files) throws MessagingException { File... files) throws MessagingException {
Assert.isFalse(CollUtil.isEmpty(tos), "请至少指定一名收件人"); Assert.isFalse(CollUtil.isEmpty(tos), "请至少指定一名收件人");
JavaMailSender mailSender = DynamicMailSenderAutoConfiguration.build(mailConfig); JavaMailSender mailSender = getMailSender();
String form;
if (mailConfig != null && StringUtils.hasText(mailConfig.getMailFrom())) {
form = mailConfig.getMailFrom();
} else {
form = SpringUtil.getProperty("spring.mail.username");
}
MimeMessage mimeMessage = mailSender.createMimeMessage(); MimeMessage mimeMessage = mailSender.createMimeMessage();
// 创建邮件发送器 // 创建邮件发送器
MimeMessageHelper messageHelper = new MimeMessageHelper(mimeMessage, true, StandardCharsets.UTF_8 MimeMessageHelper messageHelper = new MimeMessageHelper(mimeMessage, true, StandardCharsets.UTF_8
.displayName()); .displayName());
// 设置基本信息 // 设置基本信息
messageHelper.setFrom(form);
messageHelper.setSubject(subject); messageHelper.setSubject(subject);
messageHelper.setText(content, isHtml); messageHelper.setText(content, isHtml);
// 设置收信人 // 设置收信人
@@ -223,4 +209,18 @@ public class MailUtils {
return result; return result;
} }
/**
* 获取邮件 Sender
*
* @return 邮件 Sender
*/
public static JavaMailSender getMailSender() {
JavaMailSenderImpl mailSender = SpringUtil.getBean(JavaMailSenderImpl.class);
MailConfigService mailConfigService = ExceptionUtils.exToNull(() -> SpringUtil
.getBean(MailConfigService.class));
if (mailConfigService != null && mailConfigService.getMailConfig() != null) {
mailConfigService.apply(mailConfigService.getMailConfig(), mailSender);
}
return mailSender;
}
} }