邮件发送实际上是一个很是常见的需求,用户注册,找回密码等地方,都会用到,使用 JavaSE 代码发送邮件,步骤仍是挺繁琐的,Spring Boot 中对于邮件发送,提供了相关的自动化配置类,使得邮件发送变得很是容易,本文咱们就来一探究竟!看看使用 Spring Boot 发送邮件的 5 中姿式。html
咱们常常会听到各类各样的邮件协议,好比 SMTP、POP三、IMAP ,那么这些协议有什么做用,有什么区别?咱们先来讨论一下这个问题。java
SMTP 是一个基于 TCP/IP 的应用层协议,江湖地位有点相似于 HTTP,SMTP 服务器默认监听的端口号为 25 。看到这里,小伙伴们可能会想到既然 SMTP 协议是基于 TCP/IP 的应用层协议,那么我是否是也能够经过 Socket 发送一封邮件呢?回答是确定的。git
生活中咱们投递一封邮件要通过以下几个步骤:github
这是一个缩减版的生活中邮件发送过程。这三个步骤能够分别对应咱们的邮件发送过程,假设从 aaa@qq.com 发送邮件到 111@163.com :web
邮件投递大体就是这个过程,这个过程就涉及到了多个协议,咱们来分别看一下。spring
SMTP 协议全称为 Simple Mail Transfer Protocol,译做简单邮件传输协议,它定义了邮件客户端软件与 SMTP 服务器之间,以及 SMTP 服务器与 SMTP 服务器之间的通讯规则。后端
也就是说 aaa@qq.com 用户先将邮件投递到腾讯的 SMTP 服务器这个过程就使用了 SMTP 协议,而后腾讯的 SMTP 服务器将邮件投递到网易的 SMTP 服务器这个过程也依然使用了 SMTP 协议,SMTP 服务器就是用来收邮件。服务器
而 POP3 协议全称为 Post Office Protocol ,译做邮局协议,它定义了邮件客户端与 POP3 服务器之间的通讯规则,那么该协议在什么场景下会用到呢?当邮件到达网易的 SMTP 服务器以后, 111@163.com 用户须要登陆服务器查看邮件,这个时候就该协议就用上了:邮件服务商都会为每个用户提供专门的邮件存储空间,SMTP 服务器收到邮件以后,就将邮件保存到相应用户的邮件存储空间中,若是用户要读取邮件,就须要经过邮件服务商的 POP3 邮件服务器来完成。app
最后,可能也有小伙伴们据说过 IMAP 协议,这个协议是对 POP3 协议的扩展,功能更强,做用相似,这里再也不赘述。前后端分离
目前国内大部分的邮件服务商都不容许直接使用用户名/密码的方式来在代码中发送邮件,都是要先申请受权码,这里以 QQ 邮箱为例,向你们演示受权码的申请流程:首先咱们须要先登陆 QQ 邮箱网页版,点击上方的设置按钮:
而后点击帐户选项卡:
在帐户选项卡中找到开启POP3/SMTP选项,以下:
点击开启,开启相关功能,开启过程须要手机号码验证,按照步骤操做便可,不赘述。开启成功以后,便可获取一个受权码,将该号码保存好,一会使用。
接下来,咱们就能够建立项目了,Spring Boot 中,对于邮件发送提供了自动配置类,开发者只须要加入相关依赖,而后配置一下邮箱的基本信息,就能够发送邮件了。
建立完成后,项目依赖以下:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-mail</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
项目建立成功后,接下来在 application.properties 中配置邮箱的基本信息:
spring.mail.host=smtp.qq.com spring.mail.port=587 spring.mail.username=1510161612@qq.com spring.mail.password=ubknfzhjkhrbbabe spring.mail.default-encoding=UTF-8 spring.mail.properties.mail.smtp.socketFactoryClass=javax.net.ssl.SSLSocketFactory spring.mail.properties.mail.debug=true
配置含义分别以下:
若是不知道 smtp 服务器的端口或者地址的的话,能够参考 腾讯的邮箱文档
作完这些以后,Spring Boot 就会自动帮咱们配置好邮件发送类,相关的配置在 org.springframework.boot.autoconfigure.mail.MailSenderAutoConfiguration
类中,部分源码以下:
@Configuration @ConditionalOnClass({ MimeMessage.class, MimeType.class, MailSender.class }) @ConditionalOnMissingBean(MailSender.class) @Conditional(MailSenderCondition.class) @EnableConfigurationProperties(MailProperties.class) @Import({ MailSenderJndiConfiguration.class, MailSenderPropertiesConfiguration.class }) public class MailSenderAutoConfiguration { }
从这段代码中,能够看到,导入了另一个配置 MailSenderPropertiesConfiguration
类,这个类中,提供了邮件发送相关的工具类:
@Configuration @ConditionalOnProperty(prefix = "spring.mail", name = "host") class MailSenderPropertiesConfiguration { private final MailProperties properties; MailSenderPropertiesConfiguration(MailProperties properties) { this.properties = properties; } @Bean @ConditionalOnMissingBean public JavaMailSenderImpl mailSender() { JavaMailSenderImpl sender = new JavaMailSenderImpl(); applyProperties(sender); return sender; } }
能够看到,这里建立了一个 JavaMailSenderImpl
的实例, JavaMailSenderImpl
是 JavaMailSender
的一个实现,咱们将使用 JavaMailSenderImpl
来完成邮件的发送工做。
作完如上两步,邮件发送的准备工做就算是完成了,接下来就能够直接发送邮件了。
具体的发送,有 5 种不一样的方式,咱们一个一个来看。
简单邮件就是指邮件内容是一个普通的文本文档:
@Autowired JavaMailSender javaMailSender; @Test public void sendSimpleMail() { SimpleMailMessage message = new SimpleMailMessage(); message.setSubject("这是一封测试邮件"); message.setFrom("1510161612@qq.com"); message.setTo("25xxxxx755@qq.com"); message.setCc("37xxxxx37@qq.com"); message.setBcc("14xxxxx098@qq.com"); message.setSentDate(new Date()); message.setText("这是测试邮件的正文"); javaMailSender.send(message); }
从上往下,代码含义分别以下:
最后执行该方法,就能够实现邮件的发送,发送效果图以下:
邮件的附件能够是图片,也能够是普通文件,都是支持的。
@Test public void sendAttachFileMail() throws MessagingException { MimeMessage mimeMessage = javaMailSender.createMimeMessage(); MimeMessageHelper helper = new MimeMessageHelper(mimeMessage,true); helper.setSubject("这是一封测试邮件"); helper.setFrom("1510161612@qq.com"); helper.setTo("25xxxxx755@qq.com"); helper.setCc("37xxxxx37@qq.com"); helper.setBcc("14xxxxx098@qq.com"); helper.setSentDate(new Date()); helper.setText("这是测试邮件的正文"); helper.addAttachment("javaboy.jpg",new File("C:\\Users\\sang\\Downloads\\javaboy.png")); javaMailSender.send(mimeMessage); }
注意这里在构建邮件对象上和前文有所差别,这里是经过 javaMailSender 来获取一个复杂邮件对象,而后再利用 MimeMessageHelper 对邮件进行配置,MimeMessageHelper 是一个邮件配置的辅助工具类,建立时候的 true 表示构建一个 multipart message 类型的邮件,有了 MimeMessageHelper 以后,咱们针对邮件的配置都是由 MimeMessageHelper 来代劳。
最后经过 addAttachment 方法来添加一个附件。
执行该方法,邮件发送效果图以下:
图片资源和附件有什么区别呢?图片资源是放在邮件正文中的,即一打开邮件,就能看到图片。可是通常来讲,不建议使用这种方式,一些公司会对邮件内容的大小有限制(由于这种方式是将图片一块儿发送的)。
@Test public void sendImgResMail() throws MessagingException { MimeMessage mimeMessage = javaMailSender.createMimeMessage(); MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true); helper.setSubject("这是一封测试邮件"); helper.setFrom("1510161612@qq.com"); helper.setTo("25xxxxx755@qq.com"); helper.setCc("37xxxxx37@qq.com"); helper.setBcc("14xxxxx098@qq.com"); helper.setSentDate(new Date()); helper.setText("<p>hello 你们好,这是一封测试邮件,这封邮件包含两种图片,分别以下</p><p>第一张图片:</p><img src='cid:p01'/><p>第二张图片:</p><img src='cid:p02'/>",true); helper.addInline("p01",new FileSystemResource(new File("C:\\Users\\sang\\Downloads\\javaboy.png"))); helper.addInline("p02",new FileSystemResource(new File("C:\\Users\\sang\\Downloads\\javaboy2.png"))); javaMailSender.send(mimeMessage); }
这里的邮件 text 是一个 HTML 文本,里边涉及到的图片资源先用一个占位符占着,setText 方法的第二个参数 true 表示第一个参数是一个 HTML 文本。
setText 以后,再经过 addInline 方法来添加图片资源。
最后执行该方法,发送邮件,效果以下:
在公司实际开发中,第一种和第三种都不是使用最多的邮件发送方案。由于正常来讲,邮件的内容都是比较的丰富的,因此大部分邮件都是经过 HTML 来呈现的,若是直接拼接 HTML 字符串,这样之后很差维护,为了解决这个问题,通常邮件发送,都会有相应的邮件模板。最具表明性的两个模板就是 Freemarker
模板和 Thyemeleaf
模板了。
首先须要引入 Freemarker 依赖:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-freemarker</artifactId> </dependency>
而后在 resources/templates
目录下建立一个 mail.ftl
做为邮件发送模板:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <p>hello 欢迎加入 xxx 你们庭,您的入职信息以下:</p> <table border="1"> <tr> <td>姓名</td> <td>${username}</td> </tr> <tr> <td>工号</td> <td>${num}</td> </tr> <tr> <td>薪水</td> <td>${salary}</td> </tr> </table> <div style="color: #ff1a0e">一块儿努力创造辉煌</div> </body> </html>
接下来,将邮件模板渲染成 HTML ,而后发送便可。
@Test public void sendFreemarkerMail() throws MessagingException, IOException, TemplateException { MimeMessage mimeMessage = javaMailSender.createMimeMessage(); MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true); helper.setSubject("这是一封测试邮件"); helper.setFrom("1510161612@qq.com"); helper.setTo("25xxxxx755@qq.com"); helper.setCc("37xxxxx37@qq.com"); helper.setBcc("14xxxxx098@qq.com"); helper.setSentDate(new Date()); //构建 Freemarker 的基本配置 Configuration configuration = new Configuration(Configuration.VERSION_2_3_0); // 配置模板位置 ClassLoader loader = MailApplication.class.getClassLoader(); configuration.setClassLoaderForTemplateLoading(loader, "templates"); //加载模板 Template template = configuration.getTemplate("mail.ftl"); User user = new User(); user.setUsername("javaboy"); user.setNum(1); user.setSalary((double) 99999); StringWriter out = new StringWriter(); //模板渲染,渲染的结果将被保存到 out 中 ,将out 中的 html 字符串发送便可 template.process(user, out); helper.setText(out.toString(),true); javaMailSender.send(mimeMessage); }
须要注意的是,虽然引入了 Freemarker
的自动化配置,可是咱们在这里是直接 new Configuration
来从新配置 Freemarker
的,因此 Freemarker 默认的配置这里不生效,所以,在填写模板位置时,值为 templates
。
调用该方法,发送邮件,效果图以下:
推荐在 Spring Boot 中使用 Thymeleaf 来构建邮件模板。由于 Thymeleaf 的自动化配置提供了一个 TemplateEngine,经过 TemplateEngine 能够方便的将 Thymeleaf 模板渲染为 HTML ,同时,Thymeleaf 的自动化配置在这里是继续有效的 。
首先,引入 Thymeleaf 依赖:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency>
而后,建立 Thymeleaf
邮件模板:
<!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <p>hello 欢迎加入 xxx 你们庭,您的入职信息以下:</p> <table border="1"> <tr> <td>姓名</td> <td th:text="${username}"></td> </tr> <tr> <td>工号</td> <td th:text="${num}"></td> </tr> <tr> <td>薪水</td> <td th:text="${salary}"></td> </tr> </table> <div style="color: #ff1a0e">一块儿努力创造辉煌</div> </body> </html>
接下来发送邮件:
@Autowired TemplateEngine templateEngine; @Test public void sendThymeleafMail() throws MessagingException { MimeMessage mimeMessage = javaMailSender.createMimeMessage(); MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true); helper.setSubject("这是一封测试邮件"); helper.setFrom("1510161612@qq.com"); helper.setTo("25xxxxx755@qq.com"); helper.setCc("37xxxxx37@qq.com"); helper.setBcc("14xxxxx098@qq.com"); helper.setSentDate(new Date()); Context context = new Context(); context.setVariable("username", "javaboy"); context.setVariable("num","000001"); context.setVariable("salary", "99999"); String process = templateEngine.process("mail.html", context); helper.setText(process,true); javaMailSender.send(mimeMessage); }
调用该方法,发送邮件,效果图以下:
好了,这就是咱们今天说的 5 种邮件发送姿式,不知道你掌握了没有呢?
本文案例已经上传到 GitHub:https://github.com/lenve/javaboy-code-samples。
有问题欢迎留言讨论。
关注公众号【江南一点雨】,专一于 Spring Boot+微服务以及先后端分离等全栈技术,按期视频教程分享,关注后回复 Java ,领取松哥为你精心准备的 Java 干货!