在小明經歷的多個項目開發中,總會遇到消息通知的場景,比如某個廣告主提交一個表單,我們要通知提醒運營人員及時查看。
消息通知的形式也有很多,比如:短信、郵件、app推送等,本文主要給大家描述一下郵件通知的形式,因為郵件相比較其他通知渠道更方便實用(免費),除了簡單文本郵件(已經滿足大多數情形),本文還會重點說一下集成Thymeleaf模版引擎,使用HTML的形式發送郵件,盡管HTML內容不是標准化的消息格式,但是許多郵件客戶端至少支持標記語言的子集,這種方式相比較純文本展現形式更加友好。
准備
一個普通再也普通不了的SpringBoot項目
簡單文本發送
還是那句老話,在SpringBoot看來一切都是這么便捷。它已經集成郵件發送所必需的庫模塊,我們只需將以下依賴添加到pom.xml
即可。
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-mail -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
郵箱服務結構
Spring框架中用於Java郵件支持的接口和類組織如下:
-
MailSender interface:發送簡單基礎電子郵件的頂級接口;
-
JavaMailSender interface:是
MailSender
的子接口。它支持MIME消息,並且主要與MimeMessageHelper
類一起用於創建MimeMessage
。建議在此接口實現類JavaMailSenderImpl
中使用MimeMessagePreparator
機制; -
JavaMailSenderImpl class:實現了
JavaMailSender
的接口,它支持MimeMessage
和SimpleMailMessage
; -
SimpleMailMessage class:用於創建簡單的郵件消息,包括from,to,cc,subject和text字段;
-
MimeMessagePreparator interface:提供一個回調接口,用於編寫MIME消息;
-
MimeMessageHelper class:用於創建MIME消息的幫助類。它為HTML布局中的圖像,典型郵件附件和文本內容提供支持。
在以下部分中,我將向大家展示如何使用這些接口和類:
配置文件
下面舉例163郵箱(最常用的):
spring:
mail:
host: smtp.163.com # 發件服務器
username: coderxm@163.com # 賬號
password: xxxx # 密碼(163需要授權第三方登錄密碼,請查看設置-客戶端授權碼密碼開通)
port: 465
protocol: smtp
default-encoding: utf-8
# 下面這些配置大家不用深究,主要用於配置ssl
properties:
mail:
imap:
ssl:
socketFactory:
fallback: false
smtp:
auth: true
ssl:
enable: true
socketFactory:
class: com.fintech.modules.base.util.mail.MailSSLSocketFactory
starttls:
enable: true
required: true
test-connection: false
代碼
service層
按照常見的代碼結構,我們先定義一個發送郵件的接口,負責創建和發送新的郵件消息。
public interface EmailService {
/**
* 發送簡單文本內容
* @param to 發件人
* @param subject 主題
* @param text 內容
*/
void sendSimpleMessage(String to,
String subject,
String text);
}
我們可以將一些常用的配置添加到yml配置文件當中
# 郵件配置
xiaoming:
email:
subject: "程序員小明"
from: "coderxm@163.com"
to: "xiaohong@163.com"
# 抄送人:類型定義為數組,可以配置多個
cc:
- "xiaogang@163.com"
然后再通過注解注入到一個實體類中,這樣很優雅,隨用隨取:
@Configuration
@ConfigurationProperties(prefix = "xiaoming.email")
@Data
public class EmailConfig {
private String subject;
private String from;
private String to;
private String[] cc;
}
我們再定義一個類去實現這個接口:
@Slf4j
@Service
public class EmailServiceImpl implements EmailService {
@Autowired
public JavaMailSender emailSender;
@Autowired
private EmailConfig emailConfig;
@Override
public void sendSimpleMessage(String to, String subject, String text) {
try {
SimpleMailMessage message = new SimpleMailMessage();
message.setTo(to);
message.setFrom("coderxm@163.com");
message.setSubject(subject);
message.setText(text);
emailSender.send(message);
} catch (MailException exception) {
log.error(ExceptionUtil.stacktraceToString(exception));
}
}
}
測試
我們做一個簡單的測試:簡單的郵件是否能夠發送成功。
@RunWith(SpringRunner.class)
@SpringBootTest
public class EmailTest {
@Autowired
private EmailService emailService;
@Test
public void testSimple(){
emailService.sendSimpleMessage("ligang@163.com","XX籃球","你好,我想讓周琦代言!");
}
}
使用html作為模版發送郵件
正在洋洋得意(准備划水)的時候,我們的產品突然對我說,“用簡單的文本發送郵件也太簡陋了吧,顯示不出來我們的產品檔次”,然后給我了一個樣式,讓我以這種形式發送,好啊,什么都難不倒小明。我連忙找到我們的前端,(假裝低三下四地)讓她幫忙排一個頁面給我(這個工作我實在不想做,一是懶,二是人家前端肯定比我專業啊),為了保密,我簡化一下,大概是這樣的:
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
<head></head>
<body>
姓 名:<span th:text="${userName}"></span>
性 別:<span th:text="${gender}"></span>
</body>
</html>
其實樣式很好看的,但是這都不是重點,我們就以此作為模版舉個例子,語法使用的都是thymeleaf,在此處就不再贅述,如果有想了解的可以去官網找。
增加Thymeleaf dependency
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
service層
創建另一個服務類,它主要通過讀取html模版封裝數據准備郵件內容,在我們之前的示例中,這是一個簡單的文本消息。
@Service
public class MailContentBuilder {
@Autowired
private TemplateEngine templateEngine;
@Autowired
public MailContentBuilder(TemplateEngine templateEngine) {
this.templateEngine = templateEngine;
}
public String build(Map<String, Object> message) {
Context context = new Context();
context.setVariables(message);
return templateEngine.process("email", context);
}
}
在EmailService
增加接口:
public interface EmailService {
/**
* 發送簡單文本內容
* @param to 發件人
* @param subject 主題
* @param text 內容
*/
void sendSimpleMessage(String to,
String subject,
String text);
/**
* 傳遞多個變量,用於動態更換頁面模版內容
* @param emailInfoMap
*/
void prepareAndSend(Map<String,Object> emailInfoMap);
}
在EmailServiceImpl
增加發送html形式郵件的實現方法:
@Override
public void prepareAndSend(Map<String,Object> emailInfoMap) {
MimeMessagePreparator messagePreparator = mimeMessage -> {
MimeMessageHelper messageHelper = new MimeMessageHelper(mimeMessage);
messageHelper.setFrom(emailConfig.getFrom());
messageHelper.setTo(emailConfig.getTo());
messageHelper.setCc(emailConfig.getCc());
messageHelper.setSubject(emailConfig.getSubject());
// messageHelper.setText(message);
String content = mailContentBuilder.build(info);
messageHelper.setText(content,true);
};
try {
emailSender.send(messagePreparator);
} catch (MailException e) {
// runtime exception; compiler will not force you to handle it
}
}
測試
@RunWith(SpringRunner.class)
@SpringBootTest
public class EmailTest {
@Autowired
private EmailService emailService;
@Test
public void testHtml(){
HashMap<String, Object> map = new HashMap<>();
map.put("userName","程序員小明");
map.put("gender","男");
emailService.prepareAndSend(map);
}
}
整個Springboot發送郵件的場景已經復盤結束,大家如果有用到的速速體驗吧!
歡迎關注微信公眾號”程序員小明”,獲取更多資源。