一. 发送邮件原理
发件人【设置授权码】 - SMTP协议【Simple Mail TransferProtocol - 是一种提供可靠且有效的电子邮件传输的协议】 - 收件人
二. 获取授权码
开通POP3/SMTP,获取授权码
授权码是QQ邮箱推出的,用于登录第三方客户端的专用密码。适用于登录以下服务:POP3/IMAP/SMTP/Exchange/CardDAV/CalDAV服务。
温馨提醒:为了你的帐户安全,更改QQ密码以及独立密码会触发授权码过期,需要重新获取新的授权码登录
第一步:进入邮箱设置 -> 账户 -> 生成授权码 :【注意】POP3/SMTP ,IMAP/SMTP服务都需要开启
三. SpringBoot发送邮件步骤
1、导入依赖
<!--对邮件的支持jar-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
2、配置邮箱
spring:
servlet:
multipart:
#设置单个文件大小
max-file-size: 10MB
#设置单次请求文件的总大小
max-request-size: 50MB
mail:
host: smtp.qq.com # 设置邮箱主机(服务商),这里使用QQ邮件服务器
username: # 设置用户名 - 发送方
password: # 设置密码,该处的密码是QQ邮箱开启SMTP的授权码而非QQ密码
properties:
mail:
smtp:
auth: true # 必须进行授权认证,它的目的就是阻止他人任意乱发邮件
starttls: #SMTP加密方式:连接到一个TLS保护连接
enable: true
required: true
3、发送邮件的时候可以自定义发送的内容,创建工具类
@Component
@Slf4j
public class MailUtil {
/**
* 1. 来源人名
* 2. 来源内容
*/
public static final String originalText = "<hr style=\"border: 1px dashed #ef859d2e;margin: 20px 0\">\n" +
" <div>\n" +
" <div style=\"font-size: 18px;font-weight: bold;color: #C5343E\">\n" +
" %s\n" +
" </div>\n" +
" <div style=\"margin-top: 6px;font-size: 16px;color: #000000\">\n" +
" <p>\n" +
" %s\n" +
" </p>\n" +
" </div>\n" +
" </div>";
/**
* 发件人
*/
public static final String replyMail = "你之前的评论收到来自 %s 的回复";
public static final String commentMail = "你的文章 %s 收到来自 %s 的评论";
public static final String messageMail = "你收到来自 %s 的留言";
public static final String loveMail = "你收到来自 %s 的祝福";
public static final String imMail = "你收到来自 %s 的消息";
public static final String notificationMail = "你收到来自 %s 的订阅";
@Autowired
private JavaMailSender mailSender;
@Value("${spring.mail.username}")
private String sendMailer;
/**
* 1. 网站名称
* 2. 邮件类型
* 3. 发件人
* 4. 发件内容
* 5. originalText
* 6. 网站名称
*/
private String mailText;
@PostConstruct
public void init() {
this.mailText = "<div style=\"font-family: serif;line-height: 22px;padding: 30px\">\n" +
" <div style=\"display: flex;justify-content: center;width: 100%%;max-width: 900px;background-size: cover;border-radius: 10px\"></div>\n" +
" <div style=\"margin-top: 20px;display: flex;flex-direction: column;align-items: center\">\n" +
" <div style=\"margin: 10px auto 20px;text-align: center\">\n" +
" <div style=\"line-height: 32px;font-size: 26px;font-weight: bold;color: #000000\">\n" +
" 嘿!你在 %s 中收到一条新消息。\n" +
" </div>\n" +
" <div style=\"font-size: 16px;font-weight: bold;color: rgba(0, 0, 0, 0.19);margin-top: 21px\">\n" +
" %s\n" +
" </div>\n" +
" </div>\n" +
" <div style=\"min-width: 250px;max-width: 800px;min-height: 128px;background: #F7F7F7;border-radius: 10px;padding: 32px\">\n" +
" <div>\n" +
" <div style=\"font-size: 18px;font-weight: bold;color: #C5343E\">\n" +
" %s\n" +
" </div>\n" +
" <div style=\"margin-top: 6px;font-size: 16px;color: #000000\">\n" +
" <p>\n" +
" %s\n" +
" </p>\n" +
" </div>\n" +
" </div>\n" +
" %s\n" +
" <a style=\"width: 150px;height: 38px;background: #ef859d38;border-radius: 32px;display: flex;align-items: center;justify-content: center;text-decoration: none;margin: 40px auto 0\"\n" +
" href=\"https://poetize.cn\" target=\"_blank\">\n" +
" <span style=\"color: #DB214B\">有朋自远方来</span>\n" +
" </a>\n" +
" </div>\n" +
" <div style=\"margin-top: 20px;font-size: 12px;color: #00000045\">\n" +
" 此邮件由 %s 自动发出,直接回复无效(一天最多发送 " + CommonConst.COMMENT_IM_MAIL_COUNT + " 条通知邮件和 " + CommonConst.CODE_MAIL_COUNT + " 条验证码邮件),退订请联系站长。\n" +
" </div>\n" +
" </div>\n" +
"</div>";
}
public String getMailText() {
return mailText;
}
}
4、实现类。一般来说验证码可以应用在注册、登录、找回密码等功能上。前端需要传递flag标志,后端进行判断发送哪种邮件
public Result getCodeForForgetPassword(String place, Integer flag) {
int i = new Random().nextInt(900000) + 100000;
if (flag == 1) {
// 任务需求
} else if (flag == 2) {
log.info(place + "---" + "邮箱验证码---" + i);
List<String> mail = new ArrayList<>();
mail.add(place);
String text = getCodeMail(i);
WebInfo webInfo = (WebInfo) UtopianCache.get(CommonConst.WEB_INFO);
AtomicInteger count = (AtomicInteger) UtopianCache.get(CommonConst.CODE_MAIL + mail.get(0));
if (count == null || count.get() < CommonConst.CODE_MAIL_COUNT) {
mailUtil.sendMailMessage(mail, "您有一封来自" + (webInfo == null ? "Utopian" : webInfo.getWebName()) + "的回信!", text);
if (count == null) {
UtopianCache.put(CommonConst.CODE_MAIL + mail.get(0), new AtomicInteger(1), CommonConst.CODE_EXPIRE);
} else {
count.incrementAndGet();
}
} else {
return Result.fail("验证码发送次数过多,请明天再试!");
}
}
UtopianCache.put(CommonConst.FORGET_PASSWORD + place + "_" + flag, Integer.valueOf(i), 300);
return Result.success();
}
首先根据标志为flag参数,这里2
为注册时候使用的格式。调用getCodeMail
方法获取模板内容
private String getCodeMail(int i) {
WebInfo webInfo = (WebInfo) UtopianCache.get(CommonConst.WEB_INFO);
String webName = (webInfo == null ? "Utopian" : webInfo.getWebName());
return String.format(mailUtil.getMailText(),
webName,
String.format(MailUtil.imMail, PoetryUtil.getAdminUser().getUsername()),
UtopianUtil.getAdminUser().getUsername(),
String.format(codeFormat, i),
"",
webName);
}
模板内容为:【utopian.cn】%s为本次验证的验证码,请在5分钟内完成验证。为保证账号安全,请勿泄漏此验证码。
对用户点击发送的验证码的次数也需要进行统计,不超过三次,否则进行提示
4、发送邮件
这里采用异步的方式,分别填充邮件主题,邮件内容,发送时间等信息
@Async
public void sendMailMessage(List<String> to, String subject, String text) {
log.info("发送邮件===================");
log.info("to:{}", JSON.toJSONString(to));
log.info("subject:{}", subject);
log.info("text:{}", text);
try {
//true代表支持复杂的类型
MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(mailSender.createMimeMessage(), true);
//邮件发信人
mimeMessageHelper.setFrom(sendMailer);
//邮件收信人1或多个
mimeMessageHelper.setTo(to.toArray(new String[0]));
//邮件主题
mimeMessageHelper.setSubject(subject);
//邮件内容
mimeMessageHelper.setText(text, true);
//邮件发送时间
mimeMessageHelper.setSentDate(new Date());
//发送邮件
mailSender.send(mimeMessageHelper.getMimeMessage());
log.info("发送成功==================");
} catch (MessagingException e) {
log.info("发送失败==================");
log.error(e.getMessage());
}
}