SpringBoot2.0實戰 | 第十六章:整合Mail實現郵件發送

目標

整合 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());
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章