完成基础发送定义

This commit is contained in:
wind 2023-06-08 23:52:05 +08:00
parent 1cff9a1b73
commit a45df3ea28
13 changed files with 510 additions and 37 deletions

View File

@ -63,6 +63,7 @@
<activation.version>1.1.1</activation.version> <activation.version>1.1.1</activation.version>
<mail.version>1.6.2</mail.version> <mail.version>1.6.2</mail.version>
<sunactivation.version>1.2.0</sunactivation.version> <sunactivation.version>1.2.0</sunactivation.version>
<jakarta.activation.version>1.2.2</jakarta.activation.version>
</properties> </properties>
<dependencyManagement> <dependencyManagement>
@ -180,6 +181,12 @@
<version>${sunactivation.version}</version> <version>${sunactivation.version}</version>
</dependency> </dependency>
<dependency>
<groupId>jakarta.activation</groupId>
<artifactId>jakarta.activation-api</artifactId>
<version>${jakarta.activation.version}</version>
</dependency>
</dependencies> </dependencies>
</dependencyManagement> </dependencyManagement>

View File

@ -56,6 +56,17 @@
<artifactId>javax.activation</artifactId> <artifactId>javax.activation</artifactId>
<version>${sunactivation.version}</version> <version>${sunactivation.version}</version>
</dependency> </dependency>
<dependency>
<groupId>jakarta.activation</groupId>
<artifactId>jakarta.activation-api</artifactId>
<version>${jakarta.activation.version}</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-cron</artifactId>
<version>${hutool.version}</version>
</dependency>
</dependencies> </dependencies>
</dependencyManagement> </dependencyManagement>

View File

@ -0,0 +1,14 @@
package org.dromara.email.api;
import java.util.List;
/**
* Blacklist
* <p> 黑名单实现 实现此接口发送邮件时将自动排除调黑名单中的收件人
* @author :Wind
* 2023/6/8 23:05
**/
public interface Blacklist {
List<String> getBlacklist();
}

View File

@ -1,8 +1,162 @@
package org.dromara.email.api; package org.dromara.email.api;
import java.lang.String;
import java.util.List;
import java.util.Map;
public interface MailClient { public interface MailClient {
void sendMail(String mailAddress, String Title ,String body); /**
* sendMail
* <p> 发送纯文本邮件
* @param mailAddress 收件人地址
* @param title 邮件标题
* @param body 邮件正文
* @author :Wind
*/
void sendMail(String mailAddress, String title ,String body);
/**
* sendMail
* <p> 群体发送纯文本邮件
* @param mailAddress 收件人地址,添加多个
* @param title 邮件标题
* @param body 邮件正文
* @author :Wind
*/
void sendMail(List<String> mailAddress ,String title ,String body);
/**
* sendEmail
* <p>发送带有附件的文本邮件
* @param mailAddress 收件人地址
* @param title 邮件标题
* @param body 邮件正文
* @param files 附件可添加多个
* @author :Wind
*/
void sendEmail(String mailAddress, String title, String body, String... files);
/**
* sendEmail
* <p>群体发送带有附件的文本邮件
* @param mailAddress 收件人地址添加多个
* @param title 邮件标题
* @param body 邮件正文
* @param files 附件可添加多个
* @author :Wind
*/
void sendEmail(List<String> mailAddress, String title, String body, String... files);
/**
* sendHtml
* <p> 读取模板发送html邮件无正文
* <p> 将默认读取resources/template下的html文件第三个参数为html的名称需携带尾缀
* @param mailAddress 收件人地址添加多个
* @param title 邮件标题
* @param htmlName 邮件正文
* @param parameter key为模板的变量名称 无需携带大括号 value为模板变量所对应的值
* @author :Wind
*/
void sendHtml(String mailAddress, String title , String htmlName, Map<String,Object> parameter);
/**
* sendHtml
* <p> 读取模板发送html邮件,无正文
* <p> 将默认读取resources/template下的html文件第三个参数为html的名称需携带尾缀
* <p> 用户可以自己编写一个实体类并实现Parameter接口编写get和set方法这样一来字段的名称则为模板变量名称对象的值则为模板变量的值
* @param mailAddress 收件人地址添加多个
* @param title 邮件标题
* @param htmlName 邮件模板名称
* @param parameter 实体
* @author :Wind
*/
void sendHtml(String mailAddress, String title , String htmlName, Parameter parameter);
/**
* sendHtml
* <p> 读取模板发送html邮件,无正文带附件
* <p> 将默认读取resources/template下的html文件第三个参数为html的名称需携带尾缀
* @param mailAddress 收件人地址添加多个
* @param title 邮件标题
* @param htmlName 邮件模板名称
* @param parameter 实体
* @param files 附件可添加多个
* @author :Wind
*/
void sendHtml(String mailAddress, String title , String htmlName,Map<String,Object> parameter,String...files);
/**
* sendHtml
* <p> 读取模板发送html邮件,无正文带附件
* <p> 将默认读取resources/template下的html文件第三个参数为html的名称需携带尾缀
* <p> 用户可以自己编写一个实体类并实现Parameter接口编写get和set方法这样一来字段的名称则为模板变量名称对象的值则为模板变量的值
* @param mailAddress 收件人地址添加多个
* @param title 邮件标题
* @param htmlName 邮件模板名称
* @param parameter 实体
* @param files 附件可添加多个
* @author :Wind
*/
void sendHtml(String mailAddress, String title , String htmlName,Parameter parameter,String...files);
/**
* sendHtml
* <p> 读取模板发送html邮件,并携带正文
* <p> 将默认读取resources/template下的html文件第四个参数为html的名称需携带尾缀
* @param mailAddress 收件人地址添加多个
* @param title 邮件标题
* @param body 邮件文本正文
* @param htmlName 邮件正文
* @param parameter key为模板的变量名称 无需携带大括号 value为模板变量所对应的值
* @author :Wind
*/
void sendHtml(String mailAddress, String title ,String body, String htmlName, Map<String,Object> parameter);
/**
* sendHtml
* <p> 读取模板发送html邮件,并携带正文
* <p> 将默认读取resources/template下的html文件第四个参数为html的名称需携带尾缀
* <p> 用户可以自己编写一个实体类并实现Parameter接口编写get和set方法这样一来字段的名称则为模板变量名称对象的值则为模板变量的值
* @param mailAddress 收件人地址添加多个
* @param title 邮件标题
* @param body 邮件文本正文
* @param htmlName 邮件正文
* @param parameter 实体
* @author :Wind
*/
void sendHtml(String mailAddress, String title ,String body, String htmlName, Parameter parameter);
/**
* sendHtml
* <p> 读取模板发送html邮件,并携带正文和附件
* <p> 将默认读取resources/template下的html文件第四个参数为html的名称需携带尾缀
* @param mailAddress 收件人地址添加多个
* @param title 邮件标题
* @param body 邮件文本正文
* @param htmlName 邮件正文
* @param parameter key为模板的变量名称 无需携带大括号 value为模板变量所对应的值
* @param files 附件可添加多个
* @author :Wind
*/
void sendHtml(String mailAddress, String title ,String body, String htmlName, Map<String,Object> parameter,String...files);
/**
* sendHtml
* <p> 读取模板发送html邮件,并携带正文和附件
* <p> 将默认读取resources/template下的html文件第四个参数为html的名称需携带尾缀
* <p> 用户可以自己编写一个实体类并实现Parameter接口编写get和set方法这样一来字段的名称则为模板变量名称对象的值则为模板变量的值
* @param mailAddress 收件人地址添加多个
* @param title 邮件标题
* @param body 邮件文本正文
* @param htmlName 邮件正文
* @param parameter key为模板的变量名称 无需携带大括号 value为模板变量所对应的值
* @param files 附件可添加多个
* @author :Wind
*/
void sendHtml(String mailAddress, String title ,String body, String htmlName, Parameter parameter,String...files);
void sendHtml(String mailAddress, String Title ,String body);
} }

View File

@ -0,0 +1,11 @@
package org.dromara.email.api;
/**
* Parameter
* <p> 空接口用于标定用户自己的实体类型
* 用于发送html模板邮件时候 用户传递自己的实体序列化进行的类型标定
* @author :Wind
* 2023/6/8 19:36
**/
public interface Parameter {
}

View File

@ -18,7 +18,10 @@
</properties> </properties>
<dependencies> <dependencies>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-cron</artifactId>
</dependency>
</dependencies> </dependencies>
</project> </project>

View File

@ -1,6 +1,9 @@
package org.dromara.email.comm.config; package org.dromara.email.comm.config;
import lombok.Data; import lombok.Builder;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.ToString;
/** /**
* MailSmtpConfig * MailSmtpConfig
@ -8,12 +11,20 @@ import lombok.Data;
* @author :Wind * @author :Wind
* 2023/6/7 21:19 * 2023/6/7 21:19
**/ **/
@Data @Builder
@ToString
@Getter
@EqualsAndHashCode
public class MailSmtpConfig { public class MailSmtpConfig {
/** /**
* 端口号 * 端口号
* */ * */
private String host; private String port;
/**
* 发件人地址
* */
private String fromAddress;
/** /**
* 服务器地址 * 服务器地址
@ -29,4 +40,16 @@ public class MailSmtpConfig {
* 密码 * 密码
* */ * */
private String password; private String password;
/**
* 是否开启ssl 默认开启
* */
@Builder.Default
private String isSSL = "true";
/**
* 是否开启验证 默认开启
* */
@Builder.Default
private String isAuth = "true";
} }

View File

@ -0,0 +1,11 @@
package org.dromara.email.comm.utils;
import java.io.File;
public class BaseUtil {
public static String getPathName(String path) {
String[] split = path.split(File.separator);
return split[split.length-1];
}
}

View File

@ -0,0 +1,36 @@
package org.dromara.email.comm.utils;
import org.dromara.email.comm.errors.MailException;
import java.lang.reflect.Field;
import java.lang.reflect.Parameter;
import java.util.HashMap;
import java.util.Map;
public class ReflectUtil {
/**
* 反射获取接口对象的原类名
*/
public static String getObjectName(Parameter parameter) {
return parameter.getClass().getTypeName();
}
/**
* 将对象的属性和属性值变为map
* */
public static Map<String, Object> getValues(Parameter parameter) {
try {
Map<String ,Object> map = new HashMap<>();
Class<?> clazz = Class.forName(getObjectName(parameter));
Field[] declaredFields = clazz.getDeclaredFields();
for (Field declaredField : declaredFields) {
declaredField.setAccessible(true);
map.put(declaredField.getName(),declaredField.get(parameter));
}
return map;
} catch (Exception e) {
throw new MailException(e);
}
}
}

View File

@ -34,6 +34,11 @@
<artifactId>javax.activation</artifactId> <artifactId>javax.activation</artifactId>
</dependency> </dependency>
<dependency>
<groupId>jakarta.activation</groupId>
<artifactId>jakarta.activation-api</artifactId>
</dependency>
</dependencies> </dependencies>

View File

@ -0,0 +1,62 @@
package org.dromara.email.core.factory;
import org.dromara.email.api.Blacklist;
import org.dromara.email.api.MailClient;
import org.dromara.email.comm.config.MailSmtpConfig;
import org.dromara.email.comm.errors.MailException;
import org.dromara.email.core.service.MailBuild;
import javax.mail.MessagingException;
import java.util.HashMap;
import java.util.Map;
/**
* ConfigFactory
* <p> 配置工厂
* @author :Wind
* 2023/6/8 22:35
**/
public class ConfigFactory{
private static final Map<Object,MailSmtpConfig> configs = new HashMap<>();
/**
* createMailClient
* <p>从工厂获取一个邮件发送实例
* @param key 配置的标识key
* @author :Wind
*/
public static MailClient createMailClient(Object key){
try {
return MailBuild.build(configs.get(key));
} catch (MessagingException e) {
throw new MailException(e);
}
}
/**
* createMailClient
* <p>从工厂获取一个邮件发送实例,该实例发送短信将依照黑名单中的数据进行过滤
* @param key 配置的标识key
* @param blacklist 黑名单接口实例将从这里获取黑名单数据
* @author :Wind
*/
public static MailClient createMailClient(Object key, Blacklist blacklist){
try {
return MailBuild.build(configs.get(key));
} catch (MessagingException e) {
throw new MailException(e);
}
}
/**
* set
* <p>将一个配置对象交给工厂
* @param key 标识
* @param config 配置对象
* @author :Wind
*/
public static void set(Object key, MailSmtpConfig config){
configs.put(key,config);
}
}

View File

@ -0,0 +1,74 @@
package org.dromara.email.core.service;
import cn.hutool.core.collection.CollUtil;
import lombok.Data;
import org.dromara.email.api.Blacklist;
import org.dromara.email.api.MailClient;
import org.dromara.email.comm.config.MailSmtpConfig;
import org.dromara.email.comm.errors.MailException;
import javax.mail.*;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Properties;
@Data
public class MailBuild {
private Message message;
private Session session;
private MailSmtpConfig config;
private Blacklist blacklist;
private MailBuild(MailSmtpConfig config) throws MessagingException {
Properties props = new Properties();
props.put("mail.smtp.host", config.getSmtpServer());
props.put("mail.smtp.auth", config.getIsAuth());
props.put("mail.smtp.port", config.getPort());
props.put("mail.smtp.ssl.enable", config.getIsSSL());
// props.put("mail.smtp.ssl.socketFactory", new MailSSLSocketFactory());
this.session = Session.getInstance(props, new Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(config.getUsername(), config.getPassword());
}
});
this.message = new MimeMessage(session);
this.message.setFrom(new InternetAddress(config.getFromAddress()));
this.config = config;
}
public static MailClient build(MailSmtpConfig config) throws MessagingException {
return MailService.NewMailService(new MailBuild(config));
}
/**
* eliminate
* <p>过滤黑名单内容
*
* @param
* @author :Wind
*/
public InternetAddress[] eliminate(List<String> source) {
List<String> list = new ArrayList<>();
try {
if (Objects.isNull(blacklist)) {
return InternetAddress.parse(Objects.requireNonNull(CollUtil.join(source, ",")));
}
for (String s : blacklist.getBlacklist()) {
if (!source.contains(s)) {
list.add(s);
}
}
return InternetAddress.parse(CollUtil.join(list, ","));
} catch (AddressException e) {
throw new MailException(e);
}
}
}

View File

@ -1,60 +1,114 @@
package org.dromara.email.core.service; package org.dromara.email.core.service;
import lombok.extern.slf4j.Slf4j;
import org.dromara.email.api.Blacklist;
import org.dromara.email.api.MailClient; import org.dromara.email.api.MailClient;
import org.dromara.email.api.Parameter;
import org.dromara.email.comm.errors.MailException;
import org.dromara.email.comm.utils.BaseUtil;
import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.activation.FileDataSource;
import javax.mail.*; import javax.mail.*;
import javax.mail.internet.InternetAddress; import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart; import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage; import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart; import javax.mail.internet.MimeMultipart;
import java.util.Properties; import java.util.*;
@Slf4j
public class MailService implements MailClient { public class MailService implements MailClient {
private MailService() { private MailBuild mailBuild;
private MailService(MailBuild mailBuild) {
this.mailBuild = mailBuild;
} }
public static MailClient NewMailService() { public static MailClient NewMailService(MailBuild mailBuild) {
return new MailService(); return new MailService(mailBuild);
} }
@Override @Override
public void sendMail(String mailAddress, String Title, String body) { public void sendMail(String mailAddress, String title, String body) {
String smtpServer = "smtp.qq.com"; sendEmail(mailAddress,title,body);
String username = "wzsf1810@qq.com"; }
String password = "xophzbzswkzkiacb";
String fromAddress = "wzsf1810@qq.com";
String toAddress = "291203727@qq.com";
int port = 465; // SMTP服务器的端口号
Properties props = new Properties(); @Override
props.put("mail.smtp.host", smtpServer); public void sendMail(List<String> mailAddress, String title, String body) {
props.put("mail.smtp.auth", "true"); sendEmail(mailAddress,title,body);
props.put("mail.smtp.port", port); }
props.put("mail.smtp.ssl.enable", "true");
// props.put("mail.smtp.ssl.socketFactory", new MailSSLSocketFactory());
Session session = Session.getInstance(props, new Authenticator() { @Override
protected PasswordAuthentication getPasswordAuthentication() { public void sendEmail(String mailAddress, String title, String body, String... files) {
return new PasswordAuthentication(username, password); sendEmail(Collections.singletonList(mailAddress),title,body,files);
} }
});
@Override
public void sendEmail(List<String> mailAddress, String title, String body, String... files) {
try { try {
Message message = new MimeMessage(session); Message message = mailBuild.getMessage();
message.setFrom(new InternetAddress(fromAddress)); message.setRecipients(Message.RecipientType.TO, mailBuild.eliminate(mailAddress));
message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(toAddress)); message.setSubject(title);
message.setSubject(Title);
message.setText(body); message.setText(body);
Multipart multipart = new MimeMultipart();
for (String file : files) {
// 设置附件消息部分
MimeBodyPart messageBodyPart = new MimeBodyPart();
DataSource source = new FileDataSource(file);
messageBodyPart.setDataHandler(new DataHandler(source));
messageBodyPart.setFileName(BaseUtil.getPathName(file));
multipart.addBodyPart(messageBodyPart);
}
message.setContent(multipart);
Transport.send(message); Transport.send(message);
System.out.println("Email sent successfully.");
} catch (MessagingException e) { } catch (MessagingException e) {
System.out.println("Failed to send email: " + e.getMessage()); throw new MailException(e);
} }
} }
@Override
public void sendHtml(String mailAddress, String title, String htmlName, Map<String, Object> parameter) {
}
@Override
public void sendHtml(String mailAddress, String title, String htmlName, Parameter parameter) {
}
@Override
public void sendHtml(String mailAddress, String title, String htmlName, Map<String, Object> parameter, String... files) {
}
@Override
public void sendHtml(String mailAddress, String title, String htmlName, Parameter parameter, String... files) {
}
@Override
public void sendHtml(String mailAddress, String title, String body, String htmlName, Map<String, Object> parameter) {
}
@Override
public void sendHtml(String mailAddress, String title, String body, String htmlName, Parameter parameter) {
}
@Override
public void sendHtml(String mailAddress, String title, String body, String htmlName, Map<String, Object> parameter, String... files) {
}
@Override
public void sendHtml(String mailAddress, String title, String body, String htmlName, Parameter parameter, String... files) {
}
@Override @Override
public void sendHtml(String mailAddress, String Title, String body) { public void sendHtml(String mailAddress, String Title, String body) {
String smtpServer = "smtp.qq.com"; String smtpServer = "smtp.qq.com";
@ -89,11 +143,19 @@ public class MailService implements MailClient {
htmlPart.setContent(body, "text/html;charset=UTF-8"); htmlPart.setContent(body, "text/html;charset=UTF-8");
message.setContent(multipart); message.setContent(multipart);
multipart.addBodyPart(htmlPart); multipart.addBodyPart(htmlPart);
Transport.send(message);
MimeBodyPart messageBodyPart = new MimeBodyPart();
String filename = "file.txt";
DataSource source = new FileDataSource(filename);
messageBodyPart.setDataHandler(new DataHandler(source));
messageBodyPart.setFileName(filename);
multipart.addBodyPart(messageBodyPart);
Transport.send(message);
System.out.println("Email sent successfully."); System.out.println("Email sent successfully.");
} catch (MessagingException e) { } catch (MessagingException e) {
System.out.println("Failed to send email: " + e.getMessage()); throw new MailException(e);
} }
} }
} }