目標
整合 Spring boot 提供的 spring-boot-starter-mail
,實現本地發送郵件
準備工作
獲取郵箱的SMTP服務器
以網易郵箱爲例,通過以下步驟,可以查看到郵箱的SMTP服務器地址
登陸郵箱 -> 設置 -> 選擇 POP3/SMTP/IMAP
操作步驟
添加依賴
引入 Spring Boot Starter 父工程
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.5.RELEASE</version>
</parent>
添加 spring-boot-starter-mail
的依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
添加後的整體依賴如下
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
配置
- host:即準備中提到的SMTP服務器,配置到這裏
- username:用於發送郵件的郵箱
- password:用於發送郵件的郵箱的密碼
- smtp.auth:設置發送郵件需要進行權限校驗
spring:
mail:
host: smtp.126.com
username: [email protected]
password: xxxx
properties:
mail:
smtp:
auth: true
編碼
實體類
@Data
public class Mail {
// 接收方郵件
private String email;
// 主題
private String subject;
// 郵件內容
private String content;
// 模板
private String template;
// 入參
private Map<String, String> arguments;
}
Service 層代碼
JavaMailSender 是郵件發送封裝類,提供了文本類型的 SimpleMailMessage 以及 HTML格式的 MimeMessage
@AllArgsConstructor
@Service
public class MailService {
private MailProperties properties;
private JavaMailSender mailSender;
// 發送普通文本
public void send(Mail mail) throws Exception {
SimpleMailMessage message = new SimpleMailMessage();
message.setFrom(properties.getUsername());
message.setTo(mail.getEmail());
message.setSubject(mail.getSubject());
message.setText(mail.getContent());
mailSender.send(message);
}
// 發送HTML格式郵件,可以附加圖片及附件
public void sendHtml(Mail mail) throws Exception {
MimeMessage message = mailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message, true);
helper.setFrom(properties.getUsername());
helper.setTo(mail.getEmail());
helper.setSubject(mail.getSubject());
helper.setText(
"<html><body><img src=\"cid:test\" ></body></html>",
true);
// 發送圖片
File file = ResourceUtils.getFile("classpath:static/image/test.png");
helper.addInline("test", file);
// 發送附件
file = ResourceUtils.getFile("classpath:static/image/spring.vsdx");
helper.addAttachment("測試", file);
mailSender.send(message);
}
}
Controller 層代碼
@AllArgsConstructor
@RestController
public class MailController {
private MailService mailService;
@PostMapping("/sendText")
public String sendText(@RequestBody Mail mail) {
try {
mailService.send(mail);
} catch (Exception e) {
e.printStackTrace();
}
return "OK";
}
@PostMapping("/sendHtml")
public String sendHtml(@RequestBody Mail mail) {
try {
mailService.sendHtml(mail);
} catch (Exception e) {
e.printStackTrace();
}
return "OK";
}
}
啓動類
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
驗證結果
編寫測試用例
@RunWith(SpringRunner.class)
@WebAppConfiguration
@SpringBootTest(classes = Application.class)
public class UserTest {
private MockMvc mvc;
@Autowired
private WebApplicationContext webApplicationContext;
@Before
public void setUp() {
mvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
}
@Test
public void testSendText() throws Exception {
MvcResult mvcResult = mvc.perform(
MockMvcRequestBuilders
.post("/sendText")
.contentType(MediaType.APPLICATION_JSON_UTF8)
.content(
"{\"email\":\"[email protected]\"," +
"\"subject\":\"測試發郵件\"," +
"\"content\":\"隨便的內容\"}")
)
.andDo(MockMvcResultHandlers.print())
.andReturn();
Assert.assertEquals(200, mvcResult.getResponse().getStatus());
}
@Test
public void testSendHtml() throws Exception {
MvcResult mvcResult = mvc.perform(
MockMvcRequestBuilders
.post("/sendHtml")
.contentType(MediaType.APPLICATION_JSON_UTF8)
.content(
"{\"email\":\"[email protected]\"," +
"\"subject\":\"測試發郵件\"}")
)
.andDo(MockMvcResultHandlers.print())
.andReturn();
Assert.assertEquals(200, mvcResult.getResponse().getStatus());
}
}
執行後去郵箱查看是否收到發送的測試郵件
源碼地址
本章源碼 : https://gitee.com/gongm_24/spring-boot-tutorial.git
參考
結束語
發送郵件是生產中必須的功能,此處只是簡單地進行郵件發送。
郵件發送因爲需要跟郵件服務器進行交互,是一件比較耗時的操作,一般會使用隊列進行異步發送,還可以與定時器結合實現定時發送功能。
在擴展中,還將介紹使用模板進行郵件內容的組織。
擴展
使用 Freemarker 模板
添加依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
配置
在 application.yml 中進行配置,配置了 freemarker 模板文件的位置
spring
freemarker:
template-loader-path: classpath:/templates/
Service 發送方法代碼
public void sendFreemarker(Mail mail) throws Exception {
MimeMessage message = mailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message, true);
helper.setFrom(properties.getUsername());
helper.setTo(mail.getEmail());
helper.setSubject(mail.getSubject());
Template template = configuration.getTemplate(mail.getTemplate());
String text = FreeMarkerTemplateUtils.processTemplateIntoString(
template, mail.getArguments());
helper.setText(text, true);
mailSender.send(message);
}
Controller 方法代碼
@PostMapping("/sendFreemarkerTpl")
public String sendFreemarkerTpl(@RequestBody Mail mail) {
try {
mailService.sendFreemarker(mail);
} catch (Exception e) {
e.printStackTrace();
}
return "OK";
}
測試用例
@Test
public void testSendFreemarker() throws Exception {
MvcResult mvcResult = mvc.perform(
MockMvcRequestBuilders
.post("/sendFreemarkerTpl")
.contentType(MediaType.APPLICATION_JSON_UTF8)
.content("{\"email\":\"[email protected]\"," +
"\"subject\":\"測試發送Freemarker模塊郵件\"," +
"\"template\":\"welcome.ftl\"," +
"\"arguments\":{\"username\":\"哈哈哈哈\"}}")
)
.andDo(MockMvcResultHandlers.print())
.andReturn();
Assert.assertEquals(200, mvcResult.getResponse().getStatus());
}
使用 thymeleaf 模板
添加依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
配置
在 application.yml 中進行配置,配置了 thymeleaf 模板文件的位置,注意最後的反斜槓,一定不能少
spring
thymeleaf:
prefix: classpath:/templates/
Service 發送方法代碼
public void sendThymeleaf(Mail mail) throws Exception {
MimeMessage message = mailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message, true);
helper.setFrom(properties.getUsername());
helper.setTo(mail.getEmail());
helper.setSubject(mail.getSubject());
Context context = new Context();
for (Map.Entry<String, String> entry : mail.getArguments().entrySet()) {
context.setVariable(entry.getKey(), entry.getValue());
}
String text = templateEngine.process(mail.getTemplate(), context);
helper.setText(text, true);
mailSender.send(message);
}
Controller 方法代碼
@PostMapping("/sendThymeleaf")
public String sendThymeleaf(@RequestBody Mail mail) {
try {
mailService.sendThymeleaf(mail);
} catch (Exception e) {
e.printStackTrace();
}
return "OK";
}
測試用例
@Test
public void testSendThymeleaf() throws Exception {
MvcResult mvcResult = mvc.perform(
MockMvcRequestBuilders
.post("/sendThymeleaf")
.contentType(MediaType.APPLICATION_JSON_UTF8)
.content("{\"email\":\"[email protected]\"," +
"\"subject\":\"測試發送Freemarker模塊郵件\"," +
"\"template\":\"thymeleaf\"," +
"\"arguments\":{\"username\":\"哈哈哈哈\"}}")
)
.andDo(MockMvcResultHandlers.print())
.andReturn();
Assert.assertEquals(200, mvcResult.getResponse().getStatus());
}