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-8properties: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);}});
}