Foreword
Send a message should be one of the essential expanded functionality of the site, registration verification, forgotten passwords or send marketing information to the user. We will normally associated with JavaMail api to write the relevant code to send mail, but now Spring Boot package provides a set of integrated spring-boot-starter-mail is easier to use.
basic concepts
spring-boot-starter-mail:
Official Documents
Spring:https://docs.spring.io/spring/docs/5.2.3.RELEASE/spring-framework-reference/integration.html#mail
Maven
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
Dependency tree:
spring-boot-starter-mail-xxx.jar api Sun's e-mail function of the respective packages.
Note : Sun's Java SE JDK is not in the mail API, you need to download the Java EE JDK & Java EE SDK
(In fact, Java EE is built in Java SE development on the basis of a series of technical specifications provided by the official Java EE SDK is Java EE reference implementation, Java EE is to achieve the most complete development kit, and we often say just Java SE JDK comprising the API implementation, associated with the presence of Java EE specifications the Java SE; Java EE. 7 contains the following main technical specifications: http://www.oracle.com/technetwork/cn/java/javaee/tech/index .html )
Java EE JDK Specification:https://jcp.org/aboutJava/communityprocess/final/jsr366/index.html
Java EE SDK:https://www.oracle.com/java/technologies/java-ee-sdk-download.html
Configuration
application.properties Configuration
#Email Config
spring.mail.test-connection=true
# 设置邮箱主机
spring.mail.host=smtp.qq.com
spring.mail.port=587
# 设置用户名
[email protected]
# 设置密码,该处的密码是QQ邮箱开启SMTP的授权码而非QQ密码
spring.mail.password=xxxxxxxxxxxx
spring.mail.protocol=smtp
spring.mail.default-encoding=UTF-8
# 设置是否需要认证,如果为true,那么用户名和密码就必须的,
# 如果设置false,可以不设置用户名和密码,当然也得看你的对接的平台是否支持无密码进行访问的。
spring.mail.properties.mail.smtp.auth=true
# STARTTLS[1] 是对纯文本通信协议的扩展。它提供一种方式将纯文本连接升级为加密连接(TLS或SSL),而不是另外使用一个端口作加密通信。
spring.mail.properties.mail.smtp.starttls.enable=true
spring.mail.properties.mail.smtp.starttls.required=true
spring.mail.properties.mail.smtp.socketFactory.port=465
spring.mail.properties.mail.smtp.socketFactory.class=javax.net.ssl.SSLSocketFactory
spring.mail.properties.mail.smtp.socketFactory.fallback=false
application.yml arrangement
spring:
mail:
# 163
host: smtp.163.com
port:
username: [email protected]
password: ************
protocol: smtp
default-encoding: UTF-8
properties:
mail.smtp.auth: true
mail.smtp.starttls.enable: true
mail.smtp.starttls.required: true
mail.smtp.socketFactory.port: 465
mail.smtp.socketFactory.class: javax.net.ssl.SSLSocketFactory
mail.smtp.socketFactory.fallback: false
Mail categories autoconfiguration: MailSenderAutoConfiguration (Learn)
Spring Boot Mail function has been configured to the relevant basic configuration information, it is Spring Boot official, whose class is MailSenderAutoConfiguration :
//MailSenderAutoConfiguration
@Configuration
@ConditionalOnClass({ MimeMessage.class, MimeType.class })
@ConditionalOnMissingBean(MailSender.class)
@Conditional(MailSenderCondition.class)
@EnableConfigurationProperties(MailProperties.class)
@Import(JndiSessionConfiguration.class)
public class MailSenderAutoConfiguration {
private final MailProperties properties;
private final Session session;
public MailSenderAutoConfiguration(MailProperties properties,
ObjectProvider<Session> session) {
this.properties = properties;
this.session = session.getIfAvailable();
}
@Bean
public JavaMailSenderImpl mailSender() {
JavaMailSenderImpl sender = new JavaMailSenderImpl();
if (this.session != null) {
sender.setSession(this.session);
}
else {
applyProperties(sender);
}
return sender;
}
//other code...
}
In MailSenderAutoConfiguration automatic configuration class, create a Bean, whose class is JavaMailSenderImpl, it is Spring class service designed to send Mail messages, SpringBoot also use it to send mail. It is JavaMailSender interface implementation class to send different types of messages via its send () method, divided into two categories,
One is a simple text message, without any html format, without attachments, without pictures, etc. Simple Mail,
There is a class with html formatted text or links, there is a complex e-mail attachments or pictures.
163 E-mail
spring:
mail:
host: smtp.163.com
port:
username: [email protected]
password: ************
Which spring.mail.port not specify; spring.mail.password not mail password, you need to log mail.163.com, go to Settings client license key acquired a 16 character password, while allowing POP3 / SMTP services.
QQ-mail
spring:
mail:
host: smtp.qq.com
port: 587
username: [email protected]
password: ************
spring.mail.password not QQ password, login mail.qq.com, go to Settings accounts POP3 / IMAP / SMTP / Exchange / CardDAV / CalDAV service enabling POP3 / SMTP service to get a 16-character password
Gmail mailbox
spring:
mail:
host: smtp.gmail.com
port: 465
username: [email protected]
password: ****************
spring.mail.password is Gmail password, but to go less secure access to applications Google accounts allowed insecure applications.
Email configuration class
Spring Boot for parsing configuration files mail custom configuration attributes related
Note: do not need custom configuration can not write Email configuration class
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
@Component
public class EmailConfig {
/**
* 发件邮箱
*/
@Value("${spring.mail.username}")
private String emailFrom;
public String getEmailFrom() {
return emailFrom;
}
public void setEmailFrom(String emailFrom) {
this.emailFrom = emailFrom;
}
}
or
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
@Component
@ConfigurationProperties(prefix = "spring.mail")
public class EmailConfig {
/**
* 发件邮箱
*/
private String emailFrom;
public String getEmailFrom() {
return emailFrom;
}
public void setEmailFrom(String emailFrom) {
this.emailFrom = emailFrom;
}
}
Simple Mail
@SpringBootTest
@RunWith(SpringJUnit4ClassRunner.class)
public class SimpleMailTest {
@Autowired
private MailService mailService;
@Test
public void sendMail(){
mailService.sendSimpleMail("测试Springboot发送邮件", "发送邮件...");
}
}
@Override
public void sendSimpleMail(String subject, String text) {
SimpleMailMessage mailMessage = new SimpleMailMessage();
mailMessage.setFrom(mailProperties.getFrom());
mailMessage.setTo(mailProperties.getTo());
mailMessage.setSubject(subject);
mailMessage.setText(text);
javaMailSender.send(mailMessage);
}
The results :
Simple Mail with Attachments
A file file.txt, on the resources / public / directory
@SpringBootTest
@RunWith(SpringJUnit4ClassRunner.class)
public class MimeMailTest {
@Autowired
private MailService mailService;
@Test
public void testMail() throws MessagingException {
Map<String, String> attachmentMap = new HashMap<>();
attachmentMap.put("附件", "file.txt的绝对路径");
mailService.sendHtmlMail("测试Springboot发送带附件的邮件", "欢迎进入<a href=\"http://www.baidu.com\">百度首页</a>", attachmentMap);
}
}
@Override
public void sendHtmlMail(String subject, String text, Map<String, String> attachmentMap) throws MessagingException {
MimeMessage mimeMessage = javaMailSender.createMimeMessage();
//是否发送的邮件是富文本(附件,图片,html等)
MimeMessageHelper messageHelper = new MimeMessageHelper(mimeMessage, true);
messageHelper.setFrom(mailProperties.getFrom());
messageHelper.setTo(mailProperties.getTo());
messageHelper.setSubject(subject);
messageHelper.setText(text, true);//重点,默认为false,显示原始html代码,无效果
if(attachmentMap != null){
attachmentMap.entrySet().stream().forEach(entrySet -> {
try {
File file = new File(entrySet.getValue());
if(file.exists()){
messageHelper.addAttachment(entrySet.getKey(), new FileSystemResource(file));
}
} catch (MessagingException e) {
e.printStackTrace();
}
});
}
javaMailSender.send(mimeMessage);
}
The results :
Mail Templates
Template engine :
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
@SpringBootTest
@RunWith(SpringJUnit4ClassRunner.class)
public class MailTemplateTest {
@Autowired
private MailService mailService;
@Test
public void testFreemarkerMail() throws MessagingException, IOException, TemplateException {
Map<String, Object> params = new HashMap<>();
params.put("username", "Cay");
mailService.sendTemplateMail("测试Springboot发送模版邮件", params);
}
}
FreeMarker template
<html>
<body>
<h3>你好, <span style="color: red;">${username}</span>, 这是一封模板邮件!</h3>
</body>
</html>
@Override
public void sendTemplateMail(String subject, Map<String, Object> params) throws MessagingException, IOException, TemplateException {
MimeMessage mimeMessage = javaMailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true);
helper.setFrom(mailProperties.getFrom());
helper.setTo(mailProperties.getTo());
Configuration configuration = new Configuration(Configuration.VERSION_2_3_28);
configuration.setClassForTemplateLoading(this.getClass(), "/templates");
String html = FreeMarkerTemplateUtils.processTemplateIntoString(configuration.getTemplate("mail.ftl"), params);
helper.setSubject(subject);
helper.setText(html, true);//重点,默认为false,显示原始html代码,无效果
javaMailSender.send(mimeMessage);
}
The results :
or
Template engine :
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-velocity</artifactId>
</dependency>
or
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity</artifactId>
<version>1.7</version>
</dependency>
Velocity Template
<tr>
<td style="padding: 70px 0 0 185px">
<span style="font-size:14px">Hi,$name:</span>
</td>
</tr>
<tr>
<td style="padding: 12px 0 70px 185px">
<span style="font-size:14px">$tel</span>
</td>
</tr>
public void sendTemplateMail(String sendTo, String titel, Map<String, Object> content, List<Pair<String, File>> attachments) {
MimeMessage mimeMessage = mailSender.createMimeMessage();
try {
MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true);
helper.setFrom(emailConfig.getEmailFrom());
helper.setTo(sendTo);
helper.setSubject(titel);
String text = VelocityEngineUtils.mergeTemplateIntoString(velocityEngine, "template.vm", "UTF-8", content);
helper.setText(text, true);
for (Pair<String, File> pair : attachments) {
helper.addAttachment(pair.getLeft(), new FileSystemResource(pair.getRight()));
}
} catch (Exception e) {
throw new RuntimeServiceException(e);
}
mailSender.send(mimeMessage);
}
or
Template engine :
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
Thymeleaf template
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<p th:text="'尊敬的 ' + ${user} + '用户:'"></p>
<p th:text=" '恭喜您注册成为'+${web}+'网的用户,同时感谢您对'+${company}+'的关注与支持并欢迎您使用'+${product}+'的产品与服务。'"></p>
</body>
</html>
public String sendTemplateMail() {
//创建邮件正文
Context context = new Context();
context.setVariable("user", "1111");
context.setVariable("web", "tttt");
context.setVariable("company", "我是一个公司");
context.setVariable("product","我是一个产品");
String emailContent = templateEngine.process("emailTemplate", context);
mailService.sendHtmlMail("[email protected]","主题:这是模板邮件",emailContent);
return "success";
}
common problem
Gmail邮箱:[Couldn't connect to host, port: smtp.gmail.com, 465; timeout -1]
参考文章
https://blog.csdn.net/a286352250/article/details/53157963
https://blog.csdn.net/caychen/article/details/82887926
https://blog.csdn.net/yimcarson/article/details/84936440
https://blog.csdn.net/shangyuanlang/article/details/80883253