作为即时通信的重要方式,邮件在互联网互动中起到举足轻重的作用,而搭建邮件推送服务不仅可以做到实时的消息交流,更能拉近网站与用户的距离,增加用户粘性,本文将介绍获取域名邮箱,启用 smtp,集成后端,实现推送的全过程,带你让网站“活起来”。
搭建域名邮箱服务
感谢 @miaoer 和 @Innei 大佬提供的快捷解决方案,节省折腾 Postfix 和 Dovecot 的精力,不过后续也会更新服务器手动搭建邮件首发服务的详细步骤(等期末之后有精力写详细文档,步骤还是挺复杂的)
这里我们选择 Lark(飞书国际版,国内版的操作类似,只是多了实名步骤)提供的邮箱服务
获取邮箱
我们可以使用邮箱或者 Google 帐号注册并创建企业(个人就是 1-50 人企业选项),注册完成后,我们需要为当前登录帐号分配邮箱:
进入 企业管理页面 ,点击上方产品设置,找到邮箱,在域名管理中即可为自己的邮箱指定域。
按照要求填写并前往对应的 DNS 提供商管理面板添加解析记录,我们便成功获取到了域名邮箱。
随后我们返回企业管理——组织架构——成员与部门,为自己的登录账户添加企业邮箱,由此便可以通过网页直接收发邮件
设置 smtp
依然是管理面板——产品设置——邮箱,这次我们找到左面的地址管理——公共邮箱,我们便可以创建支持 smtp 的公共推送地址
整合至后端程序
条件具备,回到主线。
整合依赖
我们这里使用的是 Spring 提供的 spring-boot-starter-mail ,在 pom.xml 中添加以下依赖:
<!--邮箱服务-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
<version>3.4.1</version>
</dependency>
随后在 application.xml 中添加好对应的配置:
spring:
mail:
host: smtp.larksuite.com
port: 587
username: [email protected]
password: your_password
properties:
mail.smtp.auth: true
mail.smtp.starttls.enable: true
mail.smtp.starttls.required: true
default-encoding: UTF-8
创建服务
我们先以最小可行性思想来完成这个实验,先创建基础的 EmailService.java
package com.grtsinry43.grtblog.service;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.stereotype.Service;
/**
* @author grtsinry43
* @date 2025/1/1 23:04
* @description 热爱可抵岁月漫长
*/
@Service
public class EmailService {
private final JavaMailSender mailSender;
public EmailService(JavaMailSender mailSender) {
this.mailSender = mailSender;
}
public void sendEmail(String to, String subject, String content) {
SimpleMailMessage message = new SimpleMailMessage();
message.setFrom("[email protected]");
message.setTo(to);
message.setSubject(subject);
message.setText(content);
mailSender.send(message);
}
}
额,就这么简单,是不是很 ruozhi
邮件模板
当然,我们给用户展示的不可能是简单的一点点文字而已吧,所以我们需要自定义邮件的样式,由于其支持使用 html,那我们便可以利用模板引擎 thymeleaf 来快速创建模板,添加如下依赖:
<!--模板支持-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
我们在 src/main/resources/templates 中新建 emailTemplate.html,这样我们便可以使用模板语法将内容填充进我们的邮件啦,利用 org.thymeleaf.context.Context;,也就是创建上下文,由模板引擎提供,在 html 生成时消费,语法大概是 th:text="${type} 这种,你也可以参考下我的:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Comment Reply Notification</title>
<style>
/*太多了,这里省略了*/
</style>
</head>
<body>
<div class="bg-container">
<div class="main-container">
<div class="header">
<img src="https://dogeoss.grtsinry43.com/img/author.jpeg" alt="Logo">
<h1>Grtsinry43's Blog | 邮件通知 </h1>
</div>
<div class="content">
<h2 style="font-size: medium"> 亲爱的朋友 <span th:text="${name}"></span>, 您在
<span th:text="${type}"></span>「
<span th:text="${title}"></span>」的评论收到了新的回复哇 </h2>
<div class="user-info">
<img class="user-avatar" th:src="${avatarUrl}" alt="Logo">
<div style="margin-left: 10px"><span th:text="${replyName}"></span> 在 <span
th:text="${replyTime}"></span> 回复了您的评论
</div>
</div>
<div style="margin-top: 10px">
<span th:utext="${replyContent}"></span>
</div>
<div>
<span> 您的原评论内容:</span>
<div style="margin-top: 10px">
<span th:utext="${commentContent}"></span>
</div>
</div>
<div class="action-container">
<a class="more-button" th:href="${url}">
点击查看详情
</a>
</div>
</div>
<div class="footer">
<p>Powered by Grtblog. 此邮件由系统自动发出,请勿回复。</p>
<p>Copyright © 2022-2025 Grtsinry43's Blog. All rights reserved.</p>
<p><a href="https://blog.grtsinry43.com"> 前往主站 </a></p>
</div>
</div>
</div>
</body>
</html>
这里我选择在发送邮件的方法中添加一个HashMap作为参数,传递所需的上下文,也就是这样:
package com.grtsinry43.grtblog.service;
import jakarta.mail.MessagingException;
import jakarta.mail.internet.MimeMessage;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context;
import java.util.HashMap;
/**
* @author grtsinry43
* @date 2025/1/1 23:04
* @description 热爱可抵岁月漫长
*/
@Service
public class EmailService {
private final JavaMailSender mailSender;
private final TemplateEngine templateEngine;
public EmailService(JavaMailSender mailSender, TemplateEngine templateEngine) {
this.mailSender = mailSender;
this.templateEngine = templateEngine;
}
@Async
public void sendEmail(String to, String subject, HashMap<String,String> info) throws MessagingException {
MimeMessage message = mailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message, true, "UTF-8");
Context context = new Context();
context.setVariable("name", info.getOrDefault("name", " "));
context.setVariable("type", info.getOrDefault("type", " "));
// ... 这里都是设置上下文咯
String html = templateEngine.process("emailTemplate", context);
helper.setFrom("[email protected]");
helper.setTo(to);
helper.setSubject(subject);
helper.setText(html, true);
mailSender.send(message);
System.out.println("邮件发送成功" + to);
}
}
Tip!这里还有一个小问题,邮件发送是花费时间很长的时间,如果同步进行会严重阻塞业务,这里采用异步模式,你也可以配合日志记录来追溯所有的邮件发送记录
结果
最后的效果大约是这样的,你可以在任意需要的场景触发,或是自定义邮件的内容,任你喜欢!