Sending Email

在项目的维护过程中,我们通常会在应用中加入短信或者邮件预警功能,比如当应用出现异常宕机时应该及时地将预警信息发送给运维或者开发人员,本文将介绍如何在Spring Boot中发送邮件。在Spring Boot中发送邮件使用的是Spring提供的org.springframework.mail.javamail.JavaMailSender,其提供了许多简单易用的方法,可发送简单的邮件、HTML格式的邮件、带附件的邮件,并且可以创建邮件模板。

引入依赖

在Spring Boot中发送邮件,需要用到spring-boot-starter-mail,引入spring-boot-starter-mail

  1. <dependency>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-starter-mail</artifactId>
  4. </dependency>

邮件配置

到邮箱设置中开启SMTP服务:
Screen Shot 2021-10-13 at 9.56.14 PM.png
再在application.yml中进行简单的配置(以163邮件为例):

  1. server:
  2. port: 80
  3. mail:
  4. jndi-name: "mail/Session"
  5. host: smtp.163.com
  6. username: 账户@163.com
  7. password: 密码 #注意这里不是邮箱登录密码!是开启SMTP发送信息获取授权码就是代码里面用的密码
  8. properties:
  9. mail:
  10. smtp:
  11. connectiontimeout: 5000
  12. timeout: 3000
  13. writetimeout: 5000
  14. auth: true
  15. starttls:
  16. enable: true
  17. required: true

spring.mail.usernamespring.mail.password填写自己的邮箱账号密码即可。

发送简单的邮件

编写EmailController,注入JavaMailSender:

  1. import org.springframework.beans.factory.annotation.Autowired;
  2. import org.springframework.beans.factory.annotation.Value;
  3. import org.springframework.mail.SimpleMailMessage;
  4. import org.springframework.mail.javamail.JavaMailSender;
  5. import org.springframework.web.bind.annotation.RequestMapping;
  6. import org.springframework.web.bind.annotation.RestController;
  7. @RestController
  8. @RequestMapping("/email")
  9. public class EmailController {
  10. @Autowired
  11. private JavaMailSender jms;
  12. @Value("${spring.mail.username}")
  13. private String from;
  14. @RequestMapping("sendSimpleEmail")
  15. public String sendSimpleEmail() {
  16. try {
  17. SimpleMailMessage message = new SimpleMailMessage();
  18. message.setFrom(from);
  19. message.setTo("888888@qq.com"); // 接收地址
  20. message.setSubject("一封简单的邮件"); // 标题
  21. message.setText("使用Spring Boot发送简单邮件。"); // 内容
  22. jms.send(message);
  23. return "发送成功";
  24. } catch (Exception e) {
  25. e.printStackTrace();
  26. return e.getMessage();
  27. }
  28. }
  29. }

启动项目访问http://localhost/email/sendSimpleEmail,提示发送成功:
Screen Shot 2021-10-13 at 10.49.45 PM.png

使用Spring Boot发送邮件 - 图3

发送HTML格式的邮件

改造EmailControllerSimpleMailMessage替换为MimeMessage

  1. import javax.mail.internet.MimeMessage;
  2. import org.springframework.beans.factory.annotation.Autowired;
  3. import org.springframework.beans.factory.annotation.Value;
  4. import org.springframework.mail.SimpleMailMessage;
  5. import org.springframework.mail.javamail.JavaMailSender;
  6. import org.springframework.mail.javamail.MimeMessageHelper;
  7. import org.springframework.web.bind.annotation.RequestMapping;
  8. import org.springframework.web.bind.annotation.RestController;
  9. @RestController
  10. @RequestMapping("/email")
  11. public class EmailController {
  12. @Autowired
  13. private JavaMailSender jms;
  14. @Value("${spring.mail.username}")
  15. private String from;
  16. @RequestMapping("sendHtmlEmail")
  17. public String sendHtmlEmail() {
  18. MimeMessage message = null;
  19. try {
  20. message = jms.createMimeMessage();
  21. MimeMessageHelper helper = new MimeMessageHelper(message, true);
  22. helper.setFrom(from);
  23. helper.setTo("888888@qq.com"); // 接收地址
  24. helper.setSubject("一封HTML格式的邮件"); // 标题
  25. // 带HTML格式的内容
  26. StringBuffer sb = new StringBuffer("<p style='color:#6db33f'>使用Spring Boot发送HTML格式邮件。</p>");
  27. helper.setText(sb.toString(), true);
  28. jms.send(message);
  29. return "发送成功";
  30. } catch (Exception e) {
  31. e.printStackTrace();
  32. return e.getMessage();
  33. }
  34. }
  35. }

helper.setText(sb.toString(), true);中的true表示发送HTML格式邮件。启动项目,访问http://localhost/email/sendHtmlEmail,提示发送成功,可看到文本已经加上了颜色#6db33f

使用Spring Boot发送邮件 - 图4

发送带附件的邮件

发送带附件的邮件和普通邮件相比,其实就只是多了个传入附件的过程。不过使用的仍是MimeMessage

  1. package com.springboot.demo.controller;
  2. import java.io.File;
  3. import javax.mail.internet.MimeMessage;
  4. import org.springframework.beans.factory.annotation.Autowired;
  5. import org.springframework.beans.factory.annotation.Value;
  6. import org.springframework.core.io.FileSystemResource;
  7. import org.springframework.mail.SimpleMailMessage;
  8. import org.springframework.mail.javamail.JavaMailSender;
  9. import org.springframework.mail.javamail.MimeMessageHelper;
  10. import org.springframework.web.bind.annotation.RequestMapping;
  11. import org.springframework.web.bind.annotation.RestController;
  12. @RestController
  13. @RequestMapping("/email")
  14. public class EmailController {
  15. @Autowired
  16. private JavaMailSender jms;
  17. @Value("${spring.mail.username}")
  18. private String from;
  19. @RequestMapping("sendAttachmentsMail")
  20. public String sendAttachmentsMail() {
  21. MimeMessage message = null;
  22. try {
  23. message = jms.createMimeMessage();
  24. MimeMessageHelper helper = new MimeMessageHelper(message, true);
  25. helper.setFrom(from);
  26. helper.setTo("888888@qq.com"); // 接收地址
  27. helper.setSubject("一封带附件的邮件"); // 标题
  28. helper.setText("详情参见附件内容!"); // 内容
  29. // 传入附件
  30. FileSystemResource file = new FileSystemResource(new File("src/main/resources/static/file/项目文档.docx"));
  31. helper.addAttachment("项目文档.docx", file);
  32. jms.send(message);
  33. return "发送成功";
  34. } catch (Exception e) {
  35. e.printStackTrace();
  36. return e.getMessage();
  37. }
  38. }
  39. }

启动项目访问http://localhost/email/sendAttachmentsMail,提示发送成功:

使用Spring Boot发送邮件 - 图5

发送带静态资源的邮件

发送带静态资源的邮件其实就是在发送HTML邮件的基础上嵌入静态资源(比如图片),嵌入静态资源的过程和传入附件类似,唯一的区别在于需要标识资源的cid:

  1. package com.springboot.demo.controller;
  2. import java.io.File;
  3. import javax.mail.internet.MimeMessage;
  4. import org.springframework.beans.factory.annotation.Autowired;
  5. import org.springframework.beans.factory.annotation.Value;
  6. import org.springframework.core.io.FileSystemResource;
  7. import org.springframework.mail.SimpleMailMessage;
  8. import org.springframework.mail.javamail.JavaMailSender;
  9. import org.springframework.mail.javamail.MimeMessageHelper;
  10. import org.springframework.web.bind.annotation.RequestMapping;
  11. import org.springframework.web.bind.annotation.RestController;
  12. @RestController
  13. @RequestMapping("/email")
  14. public class EmailController {
  15. @Autowired
  16. private JavaMailSender jms;
  17. @Value("${spring.mail.username}")
  18. private String from;
  19. @RequestMapping("sendInlineMail")
  20. public String sendInlineMail() {
  21. MimeMessage message = null;
  22. try {
  23. message = jms.createMimeMessage();
  24. MimeMessageHelper helper = new MimeMessageHelper(message, true);
  25. helper.setFrom(from);
  26. helper.setTo("888888@qq.com"); // 接收地址
  27. helper.setSubject("一封带静态资源的邮件"); // 标题
  28. helper.setText("<html><body>博客图:<img src='cid:img'/></body></html>", true); // 内容
  29. // 传入附件
  30. FileSystemResource file = new FileSystemResource(new File("src/main/resources/static/img/sunshine.png"));
  31. helper.addInline("img", file);
  32. jms.send(message);
  33. return "发送成功";
  34. } catch (Exception e) {
  35. e.printStackTrace();
  36. return e.getMessage();
  37. }
  38. }
  39. }

helper.addInline("img", file);中的img和图片标签里cid后的名称相对应。启动项目访问http://localhost/email/sendInlineMail,提示发送成功:

使用Spring Boot发送邮件 - 图6

使用模板发送邮件

在发送验证码等情况下可以创建一个邮件的模板,唯一的变量为验证码。这个例子中使用的模板解析引擎为Thymeleaf,所以首先引入Thymeleaf依赖:

  1. <dependency>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-starter-thymeleaf</artifactId>
  4. </dependency>

在template目录下创建一个emailTemplate.html模板:

  1. <!DOCTYPE html>
  2. <html lang="zh" xmlns:th="http://www.thymeleaf.org">
  3. <head>
  4. <meta charset="UTF-8" />
  5. <title>模板</title>
  6. </head>
  7. <body>
  8. 您好,您的验证码为<p th:text="${code}" style="display: inline">{code}</p>,请在两分钟内使用完成操作。
  9. </body>
  10. </html>

发送模板邮件,本质上还是发送HTML邮件,只不过多了绑定变量的过程,详细如下所示:

  1. package com.springboot.demo.controller;
  2. import java.io.File;
  3. import javax.mail.internet.MimeMessage;
  4. import org.springframework.beans.factory.annotation.Autowired;
  5. import org.springframework.beans.factory.annotation.Value;
  6. import org.springframework.core.io.FileSystemResource;
  7. import org.springframework.mail.SimpleMailMessage;
  8. import org.springframework.mail.javamail.JavaMailSender;
  9. import org.springframework.mail.javamail.MimeMessageHelper;
  10. import org.springframework.web.bind.annotation.RequestMapping;
  11. import org.springframework.web.bind.annotation.RestController;
  12. import org.thymeleaf.TemplateEngine;
  13. import org.thymeleaf.context.Context;
  14. @RestController
  15. @RequestMapping("/email")
  16. public class EmailController {
  17. @Autowired
  18. private JavaMailSender jms;
  19. @Value("${spring.mail.username}")
  20. private String from;
  21. @Autowired
  22. private TemplateEngine templateEngine;
  23. @RequestMapping("sendTemplateEmail")
  24. public String sendTemplateEmail(String code) {
  25. MimeMessage message = null;
  26. try {
  27. message = jms.createMimeMessage();
  28. MimeMessageHelper helper = new MimeMessageHelper(message, true);
  29. helper.setFrom(from);
  30. helper.setTo("888888@qq.com"); // 接收地址
  31. helper.setSubject("邮件摸板测试"); // 标题
  32. // 处理邮件模板
  33. Context context = new Context();
  34. context.setVariable("code", code);
  35. String template = templateEngine.process("emailTemplate", context);
  36. helper.setText(template, true);
  37. jms.send(message);
  38. return "发送成功";
  39. } catch (Exception e) {
  40. e.printStackTrace();
  41. return e.getMessage();
  42. }
  43. }
  44. }

其中code对应模板里的${code}变量。启动项目,访问http://localhost/email/sendTemplateEmail?code=EOS9,页面提示发送成功:

使用Spring Boot发送邮件 - 图7