Email 开发
1. 核心依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
hutool工具包:
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.11</version>
</dependency>
2. 邮件实体类
- 这个类更贴近我们的常见信息,用这个去构造邮箱框架的指定邮件类的构造。
@Data
public class EmailMessage implements Serializable {
private String sender;
String[] recipient;
String[] carbonCopy;
private String title;
private String content;
private Date createTime;
private static final long serialVersionUID = 1L;
public void setRecipient(String... recipient) {
this.recipient = recipient;
}
public void setCarbonCopy(String... cc) {
this.carbonCopy = cc;
}
public void setRecipient(@NonNull String recipient) {
this.recipient = new String[]{recipient};
}
public void setCarbonCopy(@NonNull String cc) {
this.carbonCopy = new String[]{cc};
}
public String[] getRecipient() {
return recipient;
}
public String[] getCarbonCopy() {
return carbonCopy;
}
public String getRecipient(int i) {
return recipient != null ? recipient[i] : null;
}
public String getCarbonCopy(int i) {
return carbonCopy != null ? carbonCopy[i] : null;
}
}
邮箱格式检查:
public class EmailValidator {
public static final String EMAIL_PATTERN = "^[A-Za-z0-9+_.-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}$";
public static boolean isEmailAccessible(String email) {
return email.matches(EMAIL_PATTERN);
}
}
3. 配置
spring:
mail:
host: # 邮箱服务器地址(不填会无法启动成功)
port: # 邮箱服务器端口
username: # 发起者的邮箱地址
password: # 密码(是调用邮箱接口的授权密码,不是邮箱账户密码)
default-encoding: utf-8
properties:
mail:
smtp:
socketFactory:
class: javax.net.ssl.SSLSocketFactory
以 yeah.net 邮箱为例(其他的邮箱也会有,举一反三)
根据指导即可,获得授权密码!
以smtp为例:
- 这个就是host,可以查一下,port是465(其他的服务器 port是啥,一查便知)
4. 发送邮件(都是可群发的)
@Component
@Slf4j
@RequiredArgsConstructor
public class EmailSender {
private final JavaMailSender javaMailSender;
private final TemplateEngine templateEngine;
public SimpleMailMessage emailToSimpleMailMessage(EmailMessage emailMessage) {
SimpleMailMessage simpleMailMessage = new SimpleMailMessage();
simpleMailMessage.setFrom(emailMessage.getSender());
simpleMailMessage.setTo(emailMessage.getRecipient());
simpleMailMessage.setCc(emailMessage.getCarbonCopy());
simpleMailMessage.setSubject(emailMessage.getTitle());
simpleMailMessage.setText(emailMessage.getContent());
return simpleMailMessage;
}
public MimeMessageHelper emailIntoMimeMessageByHelper(MimeMessage mimeMessage, EmailMessage emailMessage) {
try {
MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(mimeMessage, true);
mimeMessageHelper.setFrom(emailMessage.getSender());
mimeMessageHelper.setCc(emailMessage.getCarbonCopy());
mimeMessageHelper.setSubject(emailMessage.getTitle());
mimeMessageHelper.setTo(emailMessage.getRecipient());
return mimeMessageHelper;
} catch (MessagingException e) {
throw new RuntimeException(e);
}
}
}
4.1 发送普通邮件(纯文本)
public void sendSimpleMailMessage(EmailMessage emailMessage) {
if (Objects.isNull(emailMessage)) {
throw new RuntimeException("email不能为null!");
}
// 封装simpleMailMessage对象
SimpleMailMessage simpleMailMessage = emailToSimpleMailMessage(emailMessage);
// 发送
javaMailSender.send(simpleMailMessage);
}
4.2 发送邮件待附件
public void sendMailWithFile(EmailMessage emailMessage, File... files) {
if (Objects.isNull(emailMessage)) {
throw new RuntimeException("email不能为null!");
}
// 封装对象
try {
MimeMessage mimeMessage = javaMailSender.createMimeMessage();
MimeMessageHelper mimeMessageHelper = emailIntoMimeMessageByHelper(mimeMessage, emailMessage);
// 添加附件
for (File file : files) {
if (Objects.nonNull(file)) {
mimeMessageHelper.addAttachment(file.getName(), file);
}
}
mimeMessageHelper.setText(emailMessage.getContent(), false);
javaMailSender.send(mimeMessage);
} catch (MessagingException e) {
throw new RuntimeException(e);
}
}
4.3 发送模板邮件
public void sendModelMail(EmailMessage emailMessage, String template, Object modelMessage) {
if (Objects.isNull(emailMessage)) {
throw new RuntimeException("email不能为null!");
}
// 封装对象
try {
MimeMessage mimeMessage = javaMailSender.createMimeMessage();
MimeMessageHelper mimeMessageHelper = emailIntoMimeMessageByHelper(mimeMessage, emailMessage);
// 构造模板消息
Context context = new Context();
context.setVariables(BeanUtil.beanToMap(modelMessage));
//合并模板与数据
String content = templateEngine.process(template, context);
mimeMessageHelper.setText(content, true);
javaMailSender.send(mimeMessage);
} catch (MessagingException e) {
throw new RuntimeException(e);
}
}
其中,template是模板html的路径,以类路径(resources)下的templates包为根目录!
邮件显示的一些对html语法的兼容问题,可以参考文章:HTML邮件 兼容问题_foxmail对html样式支持不好-CSDN博客
一个模板html例子:
- 经典的邮箱验证登录
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>邮箱验证</title>
</head>
<body>
<span>
下面是您的身份验证码:
</span>
<br />
<font style="font-size: 50pt">
<span th:text="${code}"></span>
</font>
<br />
<span> 请在 </span>
<font style="font-size: 20pt; color: brown">
<span th:text="${minutes}"></span>
</font>
<span> 分钟内完成验证,如非本人操作,请忽略!</span>
</body>
</html>
原理:将传入的Map的键值对,替换到html里
4.4 发送模板邮件带附件
public void sendModelMailWithFile(EmailMessage emailMessage, String template, Object modelMessage, File... files) {
if (Objects.isNull(emailMessage)) {
throw new RuntimeException("email不能为null!");
}
// 封装对象
try {
MimeMessage mimeMessage = javaMailSender.createMimeMessage();
MimeMessageHelper mimeMessageHelper = emailIntoMimeMessageByHelper(mimeMessage, emailMessage);
// 构造模板消息
Context context = new Context();
context.setVariables(BeanUtil.beanToMap(modelMessage));
//合并模板与数据
String content = templateEngine.process(template, context);
mimeMessageHelper.setText(content, true);
// 添加附件
for (File file : files) {
if (Objects.nonNull(file)) {
mimeMessageHelper.addAttachment(file.getName(), file);
}
}
javaMailSender.send(mimeMessage);
} catch (MessagingException e) {
throw new RuntimeException(e);
}
}
4.5 根据收件人自定义发送模板邮件并且带附件
public <T, R> void customizedSendEmail(EmailMessage emailMessage, String template, Function<T, R> function, File... files) {
if (Objects.isNull(emailMessage)) {
throw new RuntimeException("email不能为null!");
}
String sender = emailMessage.getSender();
String[] carbonCopy = emailMessage.getCarbonCopy();
String title = emailMessage.getTitle();
Arrays.stream(emailMessage.getRecipient())
.parallel()
.distinct()
.forEach(s -> {
try {
// 封装对象
MimeMessage mimeMessage = javaMailSender.createMimeMessage();
MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(mimeMessage, true);
mimeMessageHelper.setTo(s);
mimeMessageHelper.setFrom(sender);
mimeMessageHelper.setCc(carbonCopy);
mimeMessageHelper.setSubject(title);
// 添加附件
for (File file : files) {
if (Objects.nonNull(file)) {
mimeMessageHelper.addAttachment(file.getName(), file);
}
}
// 构造模板消息
Context context = new Context();
Object modelMessage = function.apply((T) s);
context.setVariables(BeanUtil.beanToMap(modelMessage));
//合并模板与数据
String content = templateEngine.process(template, context);
// 通过mimeMessageHelper设置到mimeMessage里
mimeMessageHelper.setText(content, true);
//发送
javaMailSender.send(mimeMessage);
} catch (MessagingException e) {
throw new RuntimeException(e);
}
});
}