🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
[TOC] # spring-boot-starter-mail ## 配置 ~~~ <!-- 邮件服务 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-mail</artifactId> </dependency> <!-- Thymeleaf 模版,用于发送模版邮件 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> ~~~ 使用邮件服务需要配置自己可以使用的邮箱信息,一般需要配置发送协议 SMTP、邮箱帐号 ~~~ #使用163.com的邮件服务器 spring.mail.host=smtp.163.com spring.mail.port=25 #在163.com注册的用户名,注意这里不需要@163.com后缀 spring.mail.username=****** #在163.com注册的密码 spring.mail.password=****** spring.mail.default-encoding=UTF-8 ~~~ ## 文本邮件 ~~~ @Service @Slf4j public class MailService { @Value("${spring.mail.username}") private String from; @Autowired private JavaMailSender mailSender; /** * 发送简单文本邮件 * * @param to * @param subject * @param content */ public void sendSimpleTextMail(String to, String subject, String content) { SimpleMailMessage message = new SimpleMailMessage(); message.setTo(to); message.setSubject(subject); message.setText(content); message.setFrom(from); mailSender.send(message); log.info("【文本邮件】成功发送!to={}", to); } } ~~~ 创建 Springboot 的单元测试类测试文本邮件,实验中的收信人为了方便,都设置成了自己的邮箱。 ~~~ @RunWith(SpringRunner.class) @SpringBootTest public class MailServiceTest { @Autowired private MailService mailService; @Autowired private TemplateEngine templateEngine; @Test public void sendSimpleTextMailTest() { String to = "niumoo@126.com"; String subject = "Springboot 发送简单文本邮件"; String content = "<p>第一封 Springboot 简单文本邮件</p>"; mailService.sendSimpleTextMail(to, subject, content); } } ~~~ 运行单元测试,测试文本邮件的发送。 **PS:如果运行报出异常`AuthenticationFailedException: 535 Error`. 一般都是用户名和密码有误。** ~~~ Caused by: javax.mail.AuthenticationFailedException: 535 Error: authentication failed at com.sun.mail.smtp.SMTPTransport$Authenticator.authenticate(SMTPTransport.java:965) at com.sun.mail.smtp.SMTPTransport.authenticate(SMTPTransport.java:876) at com.sun.mail.smtp.SMTPTransport.protocolConnect(SMTPTransport.java:780) at javax.mail.Service.connect(Service.java:366) at org.springframework.mail.javamail.JavaMailSenderImpl.connectTransport(JavaMailSenderImpl.java:517) at org.springframework.mail.javamail.JavaMailSenderImpl.doSend(JavaMailSenderImpl.java:436) ... 34 more ~~~ 正常运行输出成功发送的日志。 ~~~ 2019-03-11 23:35:14.743 INFO 13608 --- [ main] n.codingme.boot.service.MailServiceTest : Started MailServiceTest in 3.964 seconds (JVM running for 5.749) 2019-03-11 23:35:24.718 INFO 13608 --- [ main] net.codingme.boot.service.MailService : 【文本邮件】成功发送!to=niumoo@126.com ~~~ 文本邮件正常收到,同时可见文本邮件中的 HTML 标签也不会被解析。 ## HTML邮件 在上面的`MailService`类里新加一个方法`sendHtmlMail`,用于测试 HTML 邮件。 ~~~ /** * 发送 HTML 邮件 * * @param to * @param subject * @param content * @throws MessagingException */ public void sendHtmlMail(String to, String subject, String content) throws MessagingException { MimeMessage message = mailSender.createMimeMessage(); MimeMessageHelper messageHelper = new MimeMessageHelper(message, true); messageHelper.setFrom(from); messageHelper.setTo(to); messageHelper.setSubject(subject); // true 为 HTML 邮件 messageHelper.setText(content, true); mailSender.send(message); log.info("【HTML 邮件】成功发送!to={}", to); } ~~~ 在测试方法中增加 HTML 邮件测试方法。 ~~~ @Test public void sendHtmlMailTest() throws MessagingException { String to = "niumoo@126.com"; String subject = "Springboot 发送 HTML 邮件"; String content = "<h2>Hi~</h2><p>第一封 Springboot HTML 邮件</p>"; mailService.sendHtmlMail(to, subject, content); } ~~~ 运行单元测试,查看收信情况。 HTML 邮件正常收到,HTML 标签也被解析成对应的样式。 ## 附件邮件 在上面的`MailService`类里新加一个方法`sendAttachmentMail`,用于测试 附件邮件。 ~~~ /** * 发送带附件的邮件 * * @param to * @param subject * @param content * @param fileArr */ public void sendAttachmentMail(String to, String subject, String content, String... fileArr) throws MessagingException { MimeMessage mimeMessage = mailSender.createMimeMessage(); MimeMessageHelper messageHelper = new MimeMessageHelper(mimeMessage, true); messageHelper.setFrom(from); messageHelper.setTo(to); messageHelper.setSubject(subject); messageHelper.setText(content, true); // 添加附件 for (String filePath : fileArr) { FileSystemResource fileResource = new FileSystemResource(new File(filePath)); if (fileResource.exists()) { String filename = fileResource.getFilename(); messageHelper.addAttachment(filename, fileResource); } } mailSender.send(mimeMessage); log.info("【附件邮件】成功发送!to={}", to); } ~~~ 在测试方法中增加附件邮件测试方法。 ~~~ @Test public void sendAttachmentTest() throws MessagingException { String to = "niumoo@126.com"; String subject = "Springboot 发送 HTML 附件邮件"; String content = "<h2>Hi~</h2><p>第一封 Springboot HTML 附件邮件</p>"; String filePath = "pom.xml"; mailService.sendAttachmentMail(to, subject, content, filePath, filePath); } ~~~ 带附件的邮件正常收到,多个附件的实现方式同理。 ## 图片邮件 图片邮件和其他的邮件方式略有不同,图片邮件需要先在内容中定义好图片的位置并出给一个记录 ID ,然后在把图片加到邮件中的对于的 ID 位置。 在上面的`MailService`类里新加一个方法`sendImgMail`,用于测试 附件邮件。 ~~~ /** * 发送带图片的邮件 * * @param to * @param subject * @param content * @param imgMap */ public void sendImgMail(String to, String subject, String content, Map<String, String> imgMap) throws MessagingException { MimeMessage mimeMessage = mailSender.createMimeMessage(); MimeMessageHelper messageHelper = new MimeMessageHelper(mimeMessage, true); messageHelper.setFrom(from); messageHelper.setTo(to); messageHelper.setSubject(subject); messageHelper.setText(content, true); // 添加图片 for (Map.Entry<String, String> entry : imgMap.entrySet()) { FileSystemResource fileResource = new FileSystemResource(new File(entry.getValue())); if (fileResource.exists()) { String filename = fileResource.getFilename(); messageHelper.addInline(entry.getKey(), fileResource); } } mailSender.send(mimeMessage); log.info("【图片邮件】成功发送!to={}", to); } ~~~ 在测试方法中增加图片邮件测试方法,测试方法中使用的 apple.png 是项目里的一个图片。 ~~~ @Test public void sendImgTest() throws MessagingException { String to = "niumoo@126.com"; String subject = "Springboot 发送 HTML 图片邮件"; String content = "<h2>Hi~</h2><p>第一封 Springboot HTML 图片邮件</p><br/><img src=\"cid:img01\" /><img src=\"cid:img02\" />"; String imgPath = "apple.png"; Map<String, String> imgMap = new HashMap<>(); imgMap.put("img01", imgPath); imgMap.put("img02", imgPath); mailService.sendImgMail(to, subject, content, imgMap); } ~~~ 两个图片正常显示在邮件里。 ## 模版邮件 模版邮件的用处很广泛,像经常收到的注册成功邮件或者是操作通知邮件等都是模版邮件,模版邮件往往只需要更改其中的几个变量。Springboot 中的模版邮件首选需要选择一款模版引擎,在引入依赖的时候已经增加了模版引擎 `Thymeleaf`. 模版邮件首先需要一个邮件模版,我们在 `Templates` 下新建一个 `HTML` 文件 `RegisterSuccess.html`. 其中的 username 是给我们自定义的。 ~~~ <!DOCTYPE html> <html lang="zh-CN" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>注册成功通知</title> </head> <body> <p>[[${username}]],您好! </p> <p> 新的公钥已添加到你的账户:<br/> 标题: HP-WIN10 <br/> 如果公钥无法使用,你可以在这里重新添加: SSH Keys </p> </body> </html> ~~~ 在邮件服务`MailService`中注入模版引擎,然后编写邮件模版发送代码。 ~~~ @Autowired private TemplateEngine templateEngine; /** * 发送模版邮件 * * @param to * @param subject * @param paramMap * @param template * @throws MessagingException */ public void sendTemplateMail(String to, String subject, Map<String, Object> paramMap, String template) throws MessagingException { Context context = new Context(); // 设置变量的值 context.setVariables(paramMap); String emailContent = templateEngine.process(template, context); sendHtmlMail(to, subject, emailContent); log.info("【模版邮件】成功发送!paramsMap={},template={}", paramMap, template); } ~~~ 在单元单元测试中增加模版邮件测试方法,然后发送邮件测试。 ~~~ @Test public void sendTemplateMailTest() throws MessagingException { String to = "niumoo@126.com"; String subject = "Springboot 发送 模版邮件"; Map<String, Object> paramMap = new HashMap(); paramMap.put("username", "Darcy"); mailService.sendTemplateMail(to, subject, paramMap, "RegisterSuccess"); } ~~~ ## 补充 上面的例子中,是 Springboot 邮件服务的基本用法,代码也有很多重复,和实际的使用情况相比还有很多不足,比如缺少`异常处理机制`,在发送失败时的`重试机制`也没有,实际情况中邮件服务往往对实时性不高,多说情况下会用于`异步请求`