龙空技术网

阿里二面:说下如何基于SpringBoot发送邮件?

尚硅谷教育 1722

前言:

目前你们对“apache发送邮件”大概比较重视,咱们都想要分析一些“apache发送邮件”的相关文章。那么小编同时在网络上汇集了一些有关“apache发送邮件””的相关文章,希望姐妹们能喜欢,同学们一起来学习一下吧!

在我们实际业务开发中邮件发送其实是一个非常常见的需求,用户注册,找回密码等地方都会用到,使用JavaSE代码发送邮件步骤还是挺繁琐的。SpringBoot中对于邮件发送,提供了相关的自动化配置类,使得邮件发送变得非常容易,本篇我们就来一探究竟,解锁使用SpringBoot发送邮件的5种姿势。

一、邮件基础说明

我们经常会听到各种各样的邮件协议,比如 SMTP、POP3,那么这些协议有什么作用,有什么区别呢?

SMTP协议说明

SMTP 协议全称为 Simple Mail Transfer Protocol,译作简单邮件传输协议,它定义了邮件客户端软件与SMTP服务器之间,以及SMTP服务器与SMTP服务器之间的通信规则。它是一个基于TCP/IP的应用层协议,江湖地位有点类似于HTTP,SMTP服务器默认监听的端口号为25。

POP3协议说明

POP3协议全称为 Post Office Protocol ,译作邮局协议,它定义了邮件客户端与POP3服务器之间的通信规则。

那么该协议在什么场景下会用到呢?举例说明

当邮件到达网易的SMTP服务器之后, xxx@163.com 用户需要登录服务器查看邮件,这个时候就该协议就用上了:邮件服务商都会为每一个用户提供专门的邮件存储空间,SMTP服务器收到邮件之后,就将邮件保存到相应用户的邮件存储空间中,如果用户要读取邮件,就需要通过邮件服务商的POP3邮件服务器来完成。

二、准备工作

在账户选项卡中找到开启POP3/SMTP选项,点击开启,开启相关功能,开启过程需要手机号码验证,按照步骤操作即可,不赘述开启。成功之后,即可获取一个授权码,将该号码保存好,后面代码中要使用。

导入pom依赖

在创建的工程中,导入相关的依赖。

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="; xmlns:xsi=";

xsi:schemaLocation=" ;>

<modelVersion>4.0.0</modelVersion>

<parent>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-parent</artifactId>

<version>2.2.1.RELEASE</version>

<relativePath/>

</parent>

<groupId>com.swk</groupId>

<artifactId>email-springboot</artifactId>

<version>0.0.1-SNAPSHOT</version>

<name>email-springboot</name>

<description>Demo project for Spring Boot</description>

<properties>

<java.version>8</java.version>

</properties>

<dependencies>

<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>

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-test</artifactId>

<scope>test</scope>

</dependency>

</dependencies>

<build>

<plugins>

<plugin>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-maven-plugin</artifactId>

</plugin>

</plugins>

</build>

</project>

配置邮箱信息

在工程的yml或者properties文件中,配置邮箱相关信息。

server.port=8080

# 配置smtp服务器地址

spring.mail.host=smtp.qq.com

# 配置smtp服务器的端口

spring.mail.port=587

# 配置邮箱用户名

spring.mail.username=写你自己的邮箱

# 配置密码

spring.mail.password=gimthtwpgclabdje

# 配置默认编码

spring.mail.default-encoding=UTF-8

# 配置ssl加密工厂

spring.mail.properties.mail.smtp.socketFactoryClass=javax.net.ssl.SSLSocketFactory

# 配置开启 DEBUG 模式

spring.mail.properties.mail.debug=true

完成配置后,SpringBoot会自动帮我们配置好邮件发送类。相关源码配置如下:

@Configuration(proxyBeanMethods = false)

@ConditionalOnClass({ MimeMessage.class, MimeType.class, MailSender.class })

@ConditionalOnMissingBean(MailSender.class)

@Conditional(MailSenderCondition.class)

@EnableConfigurationProperties(MailProperties.class)

@Import({ MailSenderJndiConfiguration.class, MailSenderPropertiesConfiguration.class })

public class MailSenderAutoConfiguration {

static class MailSenderCondition extends AnyNestedCondition {

MailSenderCondition() {

super(ConfigurationPhase.PARSE_CONFIGURATION);

}

@ConditionalOnProperty(prefix = "spring.mail", name = "host")

static class HostProperty {

}

@ConditionalOnProperty(prefix = "spring.mail", name = "jndi-name")

static class JndiNameProperty {

}

}

}

从上述代码中,可以看到,导入了另一个配置MailSenderPropertiesConfiguration 类,这个类中提供了邮件发送相关的工具类,源码如下:

@Configuration(proxyBeanMethods = false)

@ConditionalOnClass(Session.class)

@ConditionalOnProperty(prefix = "spring.mail", name = "jndi-name")

@ConditionalOnJndi

class MailSenderJndiConfiguration {

// 有参构造

private final MailProperties properties;

MailSenderJndiConfiguration(MailProperties properties) {

this.properties = properties;

}

// 邮件发送组件

@Bean

JavaMailSenderImpl mailSender(Session session) {

JavaMailSenderImpl sender = new JavaMailSenderImpl();

sender.setDefaultEncoding(this.properties.getDefaultEncoding().name());

sender.setSession(session);

return sender;

}

@Bean

@ConditionalOnMissingBean

Session session() {

String jndiName = this.properties.getJndiName();

try {

return JndiLocatorDelegate.createDefaultResourceRefLocator().lookup(jndiName, Session.class);

}

catch (NamingException ex) {

throw new IllegalStateException(String.format("Unable to find Session in JNDI location %s", jndiName), ex);

}

}

}

可以看到,这里创建了一个JavaMailSenderImpl的实例,JavaMailSenderImpl是JavaMailSender的一个实现,我们将使用JavaMailSenderImpl来完成邮件的发送工作。

三 、发送邮件测试

发送简单邮件

简单邮件就是指邮件内容是一个普通的文本文档。

/**

* 1 发送简单邮件

* 简单邮件就是指邮件内容是一个普通的文本文档

*/

@Test

public void sendSimpleMail(){

//1 构建邮件接收对象

SimpleMailMessage simpleMailMessage = new SimpleMailMessage();

//2 设置邮件主题

simpleMailMessage.setSubject("这是一封测试邮件");

//3 设置邮件发送者

simpleMailMessage.setFrom("写自己的邮箱,比如qq邮箱");

//4 设置邮件接收者(可以设置多个接收者)

simpleMailMessage.setTo("写自己的邮箱,比如qq邮箱");

//5 设置邮件抄送人,可以有多个抄送人

simpleMailMessage.setCc("写自己的邮箱,比如qq邮箱");

//6 设置隐秘抄送人,可以有多个

simpleMailMessage.setBcc("写自己的邮箱,比如qq邮箱");

//7 设置邮件发送日期

simpleMailMessage.setSentDate(new Date());

//8 设置邮件的正文

simpleMailMessage.setText("这是测试邮件的正文");

//9 发送邮件

javaMailSender.send(simpleMailMessage);

}

运行程序之后,查看邮箱:

发送带附件的邮件

邮件的附件可以是图片,也可以是普通文件,都是支持的。

/**

* 2 发送带附件的邮件

*

*/

@Test

public void sendAttachFileMail() throws MessagingException {

//1 构建复杂邮件对象

MimeMessage mimeMessage = javaMailSender.createMimeMessage();

// MimeMessageHelper 邮件信息配置的辅助类

MimeMessageHelper helper = new MimeMessageHelper(mimeMessage,true);

//2 设置邮件主题

helper.setSubject("这是一封测试邮件");

//3 设置邮件发送者

helper.setFrom("写自己的邮箱,比如qq邮箱");

//4 设置邮件接收者(可以设置多个接收者)

helper.setTo("写自己的邮箱,比如qq邮箱");

//5 设置邮件抄送人,可以有多个抄送人

helper.setCc("写自己的邮箱,比如qq邮箱");

//6 设置隐秘抄送人,可以有多个

helper.setBcc("写自己的邮箱,比如qq邮箱");

helper.setSentDate(new Date());

helper.setText("这是测试邮件的正文");

//7 添加附件

helper.addAttachment("1680510755381.jpg",new File("C:\\Users\\Administrator\\Pictures\\Saved Pictures\\1680510755381.jpg"));

javaMailSender.send(mimeMessage);

}

运行程序之后,查看邮箱:

发送带图片资源的邮件

图片资源和附件有什么区别呢?

图片资源是放在邮件正文中的,即一打开邮件,就能看到图片。但是一般来说,不建议使用这种方式,一些公司会对邮件内容的大小有限制(因为这种方式是将图片一起发送的)。

/**

* 3 发送带图片资源的邮件

*

*/

@Test

public void sendImgResMail() throws MessagingException {

//1 构建复杂邮件对象

MimeMessage mimeMessage =javaMailSender.createMimeMessage();

// MimeMessageHelper 邮件信息配置的辅助类

MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true);

//2 设置邮件主题

helper.setSubject("这是一封测试邮件");

//3 设置邮件发送者

helper.setFrom("写自己的邮箱,比如qq邮箱");

//4 设置邮件接收者(可以设置多个接收者)

helper.setTo("写自己的邮箱,比如qq邮箱");

//5 设置邮件抄送人,可以有多个抄送人

helper.setCc("写自己的邮箱,比如qq邮箱");

//6 设置隐秘抄送人,可以有多个

helper.setBcc("写自己的邮箱,比如qq邮箱");

helper.setSentDate(new Date());

//7 setText方法参数一表示:是一个 HTML 文本,里边涉及到的图片资源先用一个占位符占着

// 参数二表示:设置为true,表示第一个参数是一个 HTML 文本

helper.setText("<p>hello 大家好,这是一封测试邮件,这封邮件包含两种图片,分别如下</p><p>第一张图片:</p><img src='cid:p01'/><p>第二张图片:</p><img src='cid:p02'/>",true);

//8 设置图片资源

helper.addInline("p01",new FileSystemResource(new File("C:\\Users\\Administrator\\Pictures\\Saved Pictures\\1680510755381.jpg")));

helper.addInline("p02",new FileSystemResource(new File("C:\\Users\\Administrator\\Pictures\\Saved Pictures\\1680510755381.jpg")));

javaMailSender.send(mimeMessage);

}

运行程序后,查看邮箱:

在实际开发中,第一种和第三种都不是使用最多的邮件发送方案。因为正常来说,邮件的内容都是比较的丰富的,所以大部分邮件都是通过HTML来呈现的,如果直接拼接 HTML字符串,这样以后不好维护,为了解决这个问题,一般邮件发送,都会有相应的邮件模板。最具代表性的两个模板就是Freemarker模板和Thyemeleaf模板了。

测试Freemarker模板发送邮件

在pom文件中引入freemarker依赖:

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-freemarker</artifactId>

</dependency>

在项目的resources/templates目录下创建一个email.ftl文件,作为邮件发送模板:

<!DOCTYPE html>

<html lang="en">

<head>

<meta charset="UTF-8">

<title>Title</title>

</head>

<body>

<p>hello 欢迎加入 邮件测试 大家庭,您的入职信息如下:</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>

编写User实体类:

public class User {

private String username;

private Integer num;

private Double salary;

public User() {

}

public User(String username, Integer num, Double salary) {

this.username = username;

this.num = num;

this.salary = salary;

}

public String getUsername() {

return username;

}

public void setUsername(String username) {

this.username = username;

}

public Integer getNum() {

return num;

}

public void setNum(Integer num) {

this.num = num;

}

public Double getSalary() {

return salary;

}

public void setSalary(Double salary) {

this.salary = salary;

}

@Override

public String toString() {

return "User{" +

"username='" + username + '\'' +

", num=" + num +

", salary=" + salary +

'}';

}

}

编写测试类,将邮件模板渲染成为HTML,然后发送。

/**

* 4 基于freemarker发送邮件

*

*/

@Test

public void sendFreemarkerMail() throws MessagingException,

IOException, TemplateException {

MimeMessage mimeMessage =

javaMailSender.createMimeMessage();

MimeMessageHelper helper = new

MimeMessageHelper(mimeMessage, true);

helper.setSubject("这是一封测试邮件");

helper.setFrom("写自己的邮箱,比如qq邮箱");

helper.setTo("写自己的邮箱,比如qq邮箱");

helper.setCc("写自己的邮箱,比如qq邮箱");

helper.setBcc("写自己的邮箱,比如qq邮箱");

helper.setSentDate(new Date());

//构建 Freemarker 的基本配置

Configuration configuration = new

Configuration(Configuration.VERSION_2_3_0);

// 配置模板位置

ClassLoader loader = EmailSpringbootApplicationTests.class.getClassLoader();

configuration.setClassLoaderForTemplateLoading(loader,

"templates");

//加载模板

Template template = configuration.getTemplate("email.ftl");

User user = new User();

user.setUsername("swk");

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);

}

运行程序后,查看邮箱:

测试Thymleaf模板发送邮件

推荐在SpringBoot中使用Thymeleaf来构建邮件模板。因为Thymeleaf的自动化配置提供了一个TemplateEngine ,通过TemplateEngine可以方便的将Thymeleaf模板渲染为HTML ,同时,Thymeleaf的自动化配置在这里是继续有效的。

在pom中引入Thymleaf依赖

<!DOCTYPE html>

<html lang="en" xmlns:th=";>

<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

private TemplateEngine templateEngine;

/**

* 5 基于thymleaf发送邮件

*

*/

@Test

public void sendThymeleafMail() throws MessagingException {

MimeMessage mimeMessage =

javaMailSender.createMimeMessage();

MimeMessageHelper helper = new

MimeMessageHelper(mimeMessage, true);

helper.setSubject("这是一封测试邮件");

helper.setFrom("写自己的邮箱,比如qq邮箱");

helper.setTo("写自己的邮箱,比如qq邮箱");

helper.setCc("写自己的邮箱,比如qq邮箱");

helper.setBcc("写自己的邮箱,比如qq邮箱");

helper.setSentDate(new Date());

// 使用thymleaf上下文对象设置对象信息

Context context = new Context();

context.setVariable("username", "swk");

context.setVariable("num","000001");

context.setVariable("salary", "8888");

// 指定写出的模板

String process = templateEngine.process("email.html", context);

helper.setText(process,true);

javaMailSender.send(mimeMessage);

}

运行程序后,查看邮箱:

总结

上述就是使用SpringBoot发送邮件的5种方式,针对发送内容可以分为简单文本邮件、带附件邮件、带图片资源邮件、整合FreeMarker发送邮件、整合ThymLeaf发送邮件。在实际开发中使用SpringBoot默认整合的ThymLeaf模板完成,也可以根据需要进行自定义配置。

标签: #apache发送邮件