记录一下,Spring Boot如何发送邮件。分为以下五种
- 发送文本邮件
- 发送html邮件
- 发送附件邮件
- 发送图片邮件
- 发送模板邮件
配置环境
引入maven坐标。spring-boot-starter-mail
、spring-boot-starter-thymeleaf
。
1 2 3 4 5 6 7 8 9 10
| <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-mail</artifactId> </dependency>
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency>
|
配置配置文件
1 2 3 4 5 6
| spring: mail: host: smtp.qq.com username: 928301810@qq.com password: ···· default-encoding: UTF-8
|
这里的password,并不是你邮箱的登录密码,而是POP3授权码。
配置邮箱(以qq邮箱为例)
点击邮箱的设置,然后点击账户

将获取的POP3授权码,设置到配置文件中。
发送邮件
注入JavaMailSender
对象,这是一个接口。然后获取配置文件中username
配置信息。作为发送方
1 2 3 4 5
| @Value("${spring.mail.username}") private String from;
@Autowired private JavaMailSender sender;
|
发送文本文件
Service层
这里先用SimpleMailMessage
对象,封装消息,包括:发送方,接收方、邮件主题、邮件内容。
然后使用JavaMailSender
对象,发送消息。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| @Service public class MailServiceImpl implements MailService {
@Value("${spring.mail.username}") private String from;
@Autowired private JavaMailSender sender; @Override public void sendmail(String to, String subject, String content) { SimpleMailMessage message = new SimpleMailMessage(); message.setTo(to); message.setSubject(subject); message.setText(content); message.setFrom(from);
sender.send(message);
} }
|
测试
1 2 3 4 5
| @Test void contextLoads() { service.sendmail("928301810@qq.com","HELLO","这是我用SrongBoot发送的第一封邮件");
}
|
- to:收件方
- subject:邮件主题
- content:邮件内容
发送html文件
Service层
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| @Service public class MailServiceImpl implements MailService {
@Value("${spring.mail.username}") private String from;
@Autowired private JavaMailSender sender;
@Override public void sendhtml(String to, String subject, String content) throws MessagingException { MimeMessage message = sender.createMimeMessage(); MimeMessageHelper helper = new MimeMessageHelper(message,true); helper.setFrom(from); helper.setTo(to); helper.setSubject(subject); helper.setText(content,true); sender.send(message); } }
|
这是使用JavaMailSender
的createMimeMessage
方法,来获取MimeMessage
对象。
MimeMessageHelper
的构造方法的两个参数,一个是message
,另一个是true
。
true表示发送的邮件是multipart邮件
。简单来说,multpart
是一种可以内嵌html,包含附件的邮件类型。
然后测试代码如下:
1 2 3 4 5 6 7 8 9 10 11
| @Test void TestSendHTML() throws MessagingException { String content = "<html>\n"+ "<body>\n"+ "<h3>这是我用SrongBoot发送的第二封邮件</h3>\n"+ "</body>\n"+ "</html>";
service.sendhtml("928301810@qq.com","HELLO",content);
}
|
发送带附件的邮件
Service层
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| @Service public class MailServiceImpl implements MailService {
@Value("${spring.mail.username}") private String from;
@Autowired private JavaMailSender sender;
@Override public void sendhtmlwithFile(String to, String subject, String content, String[] filepaths) throws MessagingException, FileNotFoundException { MimeMessage message = sender.createMimeMessage(); MimeMessageHelper helper = new MimeMessageHelper(message,true); helper.setFrom(from); helper.setTo(to); helper.setSubject(subject); helper.setText(content,true);
for (String filepath : filepaths) { FileSystemResource file = new FileSystemResource(new File(filepath)); String filename = file.getFilename(); assert filename != null; helper.addAttachment(filename,file); }
sender.send(message); } }
|
从参数String[] filepaths
,可以看出,它是可以携带多个附件的。与发送html不同的是,多了如下代码
1 2 3 4 5 6
| for (String filepath : filepaths) { FileSystemResource file = new FileSystemResource(new File(filepath)); String filename = file.getFilename(); assert filename != null; helper.addAttachment(filename,file); }
|
测试代码如下:
1 2 3 4 5 6 7 8 9 10
| @Test void TestSendwithFile() throws MessagingException, FileNotFoundException { String content = "<html>\n"+ "<body>\n"+ "<h3>这是我用SrongBoot发送的第三封带附件的邮件</h3>\n"+ "</body>\n"+ "</html>"; String[] filepaths = {"C:\\Users\\TJS\\Desktop\\力扣算法题链接.md", "C:\\Users\\TJS\\Desktop\\nginx-1.16.1.tar.gz"}; service.sendhtmlwithFile("928301810@qq.com","HELLO",content, filepaths); }
|
发送带有图片的邮件
Service层
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| @Service public class MailServiceImpl implements MailService {
@Value("${spring.mail.username}") private String from;
@Autowired private JavaMailSender sender;
@Override public void sendImage(String to, String subject, String content,String[][] images) throws MessagingException { MimeMessage message = sender.createMimeMessage(); MimeMessageHelper helper = new MimeMessageHelper(message,true); helper.setFrom(from); helper.setTo(to); helper.setSubject(subject); helper.setText(content,true);
for (String[] image : images) { String path = image[0]; String rscId = image[1]; FileSystemResource resource = new FileSystemResource(new File(path)); helper.addInline(rscId,resource); } sender.send(message); } }
|
可以内嵌多张图片,传入images字符串数组。
images[i][0]
:图片的路径,可以是绝对路径,也可以是相对路径。
images[i][1]
:图片的id。因为它内嵌到邮件中,实际就是以html的方式内嵌到邮件中,因此需要使用<img>
标签
测试代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| @Test void TestSendImage() throws MessagingException { String[][] images = new String[][]{ {"src/main/resources/static/2.JPG","002"}, {"src/main/resources/static/3.JPG","003"}, }; StringBuilder content = new StringBuilder("<html>\n" + "<body>\n" + "<h3>这是我用SrongBoot发送的第四封带图片的邮件</h3>\n"); for (String[] image : images) { content.append("<img src='cid:").append(image[1]).append("'></img>"); } content.append("</body>\n"+ "</html>");
service.sendImage("928301810@qq.com","HELLO", content.toString(),images); }
|
发送模板邮件
生活中有很多场景特别适用模板邮件,比如:
这些邮件都有一个特点:邮件的主体内容不会变化,变化的是用户的信息。在这个使用的模板引擎是:thymeleaf
。
maven坐标已经再前面引入。service层使用发送html的就可以。
然后再resouce的templates文件夹中,创建html模板。
html代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13
| <html lang="en" xmlns:th="http://www.thymeleaf.org">
<head> <meta charset="UTF-8"/>
<title>邮件模板</title> </head> <body> 您好,感谢您的注册,这是一封验证邮件,请点击下面的链接完成注册,感谢您的支持! <a href="#" th:href="@{http://www.ityouknow.com/register/{id}(id=${id})}">激活账号</a> </body> </html>
|
我们可以看到只有id
是变化的。{id}(id=${id})
测试代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| @SpringBootTest class SpringbootMailApplicationTests {
@Autowired private MailService service;
@Autowired private TemplateEngine templateEngine;
@Test public void TestTemplete() throws MessagingException { Context context = new Context(); context.setVariable("id","006");
String emailTemplate = templateEngine.process("EmailTemplate", context); service.sendhtml("928301810@qq.com","HELLO",emailTemplate); } }
|
我们需要注入TemplateEngine
来解析html模板。
创建Context对象,来封装变量。然后使用TemplateEngine
来解析模板,因此需要传入Context
对象。
关于异常的处理
我们看到,在发送邮件过程中,会产生例如MessagingException
异常。我们处理的方法是不断的向外抛。
但在项目中的操作通常是一个异步的操作,因此它不必要去影响主业务。因此这个异常需要我们自己来处理,而不是统统抛出去。这种情况下,我们需要使用Log,以日志的形式记录下来。
以发送HTML邮件的代码为例,原代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| @Service public class MailServiceImpl implements MailService { @Value("${spring.mail.username}") private String from;
@Autowired private JavaMailSender sender;
@Override public void sendhtml(String to, String subject, String content) throws MessagingException { MimeMessage message = sender.createMimeMessage(); MimeMessageHelper helper = new MimeMessageHelper(message,true); helper.setFrom(from); helper.setTo(to); helper.setSubject(subject); helper.setText(content,true); sender.send(message); } }
|
使用try···catch
来捕获异常,并记录日志
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| @Service public class MailServiceImpl implements MailService {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
@Value("${spring.mail.username}") private String from;
@Autowired private JavaMailSender sender;
@Override public void sendhtml(String to, String subject, String content) { logger.info("发送静态邮件开始,接收方{},{}",to,subject); MimeMessage message = sender.createMimeMessage(); MimeMessageHelper helper = null; try { helper = new MimeMessageHelper(message,true); helper.setFrom(from); helper.setTo(to); helper.setSubject(subject); helper.setText(content,true); sender.send(message); logger.info("发送成功!"); } catch (MessagingException e) { logger.error("发送失败,{}",e.toString()); } } }
|
常见错误
- 421 HL:ICC该IP同时并发连接数过大
- 451 Requested mail action not taken: too much fail …登录失败次数过多,被临时禁止登录。
- 553 authentication is required 认证失败【账号密码有可能不对,或者协议配置不对,等等】
参考地址:http://help.163.com/09/1224/17/5RAJ4LMHO0753VB8.html【它会对每一个错误进行解释】
__END__