@@ -0,0 +1,255 @@ | |||
## spring-boot-demo-email | |||
> 此 demo 主要演示了 Spring Boot 如何整合邮件功能,包括发送简单文本邮件、HTML邮件(包括模板HTML邮件)、附件邮件、静态资源邮件。 | |||
### 1.开发步骤 | |||
#### 1.1.添加依赖 | |||
```xml | |||
<dependencies> | |||
<dependency> | |||
<groupId>com.xkcoding</groupId> | |||
<artifactId>common-tools</artifactId> | |||
</dependency> | |||
<!-- Spring Boot 邮件依赖 --> | |||
<dependency> | |||
<groupId>org.springframework.boot</groupId> | |||
<artifactId>spring-boot-starter-mail</artifactId> | |||
</dependency> | |||
<!-- jasypt配置文件加解密 --> | |||
<dependency> | |||
<groupId>com.github.ulisesbocchio</groupId> | |||
<artifactId>jasypt-spring-boot-starter</artifactId> | |||
<version>${jasypt.version}</version> | |||
</dependency> | |||
<dependency> | |||
<groupId>org.springframework.boot</groupId> | |||
<artifactId>spring-boot-starter-test</artifactId> | |||
<scope>test</scope> | |||
</dependency> | |||
<!-- Spring Boot 模板依赖 --> | |||
<dependency> | |||
<groupId>org.springframework.boot</groupId> | |||
<artifactId>spring-boot-starter-thymeleaf</artifactId> | |||
</dependency> | |||
</dependencies> | |||
``` | |||
#### 1.2.添加邮件相关配置 | |||
```yaml | |||
spring: | |||
mail: | |||
host: smtp.mxhichina.com | |||
port: 465 | |||
from: "SpringBootDemo测试<${spring.mail.username}>" | |||
username: spring-boot-demo@xkcoding.com | |||
# 使用 jasypt 加密密码,使用com.xkcoding.email.PasswordTest.testGeneratePassword 生成加密密码,替换 ENC(加密密码) | |||
password: ENC(aef0+nM5440HO7YFAo7iUz8ZHpkjZVlR0hNw3OI/QOPSkNhYRImE/Oy1LBgFKoB1OjqW0v4ZdM0xNS0eKxELfA==) | |||
protocol: smtp | |||
test-connection: true | |||
default-encoding: UTF-8 | |||
properties: | |||
mail.smtp.auth: true | |||
mail.smtp.starttls.enable: true | |||
mail.smtp.starttls.required: true | |||
mail.smtp.ssl.enable: true | |||
mail.display.sendmail: spring-boot-demo | |||
# 为 jasypt 配置解密秘钥 | |||
jasypt: | |||
encryptor: | |||
password: spring-boot-demo | |||
``` | |||
#### 1.3.编写发送邮件代码 | |||
- **抽象邮件服务接口**,方便后期替换不同的客户端实现 | |||
```java | |||
public interface MailService { | |||
/** | |||
* 发送文本邮件 | |||
* | |||
* @param to 收件人地址 | |||
* @param subject 邮件主题 | |||
* @param content 邮件内容 | |||
* @param cc 抄送地址 | |||
*/ | |||
void sendSimpleMail(String to, String subject, String content, String... cc); | |||
/** | |||
* 发送HTML邮件 | |||
* | |||
* @param to 收件人地址 | |||
* @param subject 邮件主题 | |||
* @param content 邮件内容 | |||
* @param cc 抄送地址 | |||
* @throws MessagingException 邮件发送异常 | |||
*/ | |||
void sendHtmlMail(String to, String subject, String content, String... cc) | |||
throws MessagingException, MessagingException; | |||
/** | |||
* 发送带附件的邮件 | |||
* | |||
* @param to 收件人地址 | |||
* @param subject 邮件主题 | |||
* @param content 邮件内容 | |||
* @param filePath 附件地址 | |||
* @param cc 抄送地址 | |||
* @throws MessagingException 邮件发送异常 | |||
*/ | |||
void sendAttachmentsMail(String to, String subject, String content, String filePath, String... cc) | |||
throws MessagingException; | |||
/** | |||
* 发送正文中有静态资源的邮件 | |||
* | |||
* @param to 收件人地址 | |||
* @param subject 邮件主题 | |||
* @param content 邮件内容 | |||
* @param rscPath 静态资源地址 | |||
* @param rscId 静态资源id | |||
* @param cc 抄送地址 | |||
* @throws MessagingException 邮件发送异常 | |||
*/ | |||
void sendResourceMail(String to, String subject, String content, String rscPath, String rscId, String... cc) | |||
throws MessagingException; | |||
``` | |||
- 接口实现 | |||
```java | |||
@Service | |||
public class MailServiceImpl implements MailService { | |||
@Autowired | |||
private JavaMailSender mailSender; | |||
@Value("${spring.mail.from}") | |||
private String from; | |||
/** | |||
* 发送文本邮件 | |||
* | |||
* @param to 收件人地址 | |||
* @param subject 邮件主题 | |||
* @param content 邮件内容 | |||
* @param cc 抄送地址 | |||
*/ | |||
@Override | |||
public void sendSimpleMail(String to, String subject, String content, String... cc) { | |||
SimpleMailMessage message = new SimpleMailMessage(); | |||
message.setFrom(from); | |||
message.setTo(to); | |||
message.setSubject(subject); | |||
message.setText(content); | |||
if (ArrayUtil.isNotEmpty(cc)) { | |||
message.setCc(cc); | |||
} | |||
mailSender.send(message); | |||
} | |||
/** | |||
* 发送HTML邮件 | |||
* | |||
* @param to 收件人地址 | |||
* @param subject 邮件主题 | |||
* @param content 邮件内容 | |||
* @param cc 抄送地址 | |||
*/ | |||
@Override | |||
public void sendHtmlMail(String to, String subject, String content, String... cc) throws MessagingException { | |||
MimeEmail mimeEmail = basicMimeEmailBuilder(to, subject, content, cc); | |||
mailSender.send(mimeEmail.message()); | |||
} | |||
/** | |||
* 发送带附件的邮件 | |||
* | |||
* @param to 收件人地址 | |||
* @param subject 邮件主题 | |||
* @param content 邮件内容 | |||
* @param filePath 附件地址 | |||
* @param cc 抄送地址 | |||
* @throws MessagingException 邮件发送异常 | |||
*/ | |||
@Override | |||
public void sendAttachmentsMail(String to, String subject, String content, String filePath, String... cc) | |||
throws MessagingException { | |||
MimeEmail mimeEmail = basicMimeEmailBuilder(to, subject, content, cc); | |||
MimeMessageHelper helper = mimeEmail.helper(); | |||
FileSystemResource file = new FileSystemResource(new File(filePath)); | |||
String fileName = filePath.substring(filePath.lastIndexOf(File.separator)); | |||
helper.addAttachment(fileName, file); | |||
mailSender.send(mimeEmail.message()); | |||
} | |||
/** | |||
* 发送正文中有静态资源的邮件 | |||
* | |||
* @param to 收件人地址 | |||
* @param subject 邮件主题 | |||
* @param content 邮件内容 | |||
* @param rscPath 静态资源地址 | |||
* @param rscId 静态资源id | |||
* @param cc 抄送地址 | |||
* @throws MessagingException 邮件发送异常 | |||
*/ | |||
@Override | |||
public void sendResourceMail(String to, String subject, String content, String rscPath, String rscId, String... cc) | |||
throws MessagingException { | |||
MimeEmail mimeEmail = basicMimeEmailBuilder(to, subject, content, cc); | |||
MimeMessageHelper helper = mimeEmail.helper(); | |||
FileSystemResource res = new FileSystemResource(new File(rscPath)); | |||
helper.addInline(rscId, res); | |||
mailSender.send(mimeEmail.message()); | |||
} | |||
/** | |||
* 富文本邮件构造器,抽取重复代码,返回一个 MimeEmail record | |||
*/ | |||
private MimeEmail basicMimeEmailBuilder(String to, String subject, String content, String... cc) | |||
throws MessagingException { | |||
MimeMessage message = mailSender.createMimeMessage(); | |||
MimeMessageHelper helper = new MimeMessageHelper(message, true); | |||
helper.setFrom(from); | |||
helper.setTo(to); | |||
helper.setSubject(subject); | |||
helper.setText(content, true); | |||
if (ArrayUtil.isNotEmpty(cc)) { | |||
helper.setCc(cc); | |||
} | |||
return new MimeEmail(message, helper); | |||
} | |||
private record MimeEmail(MimeMessage message, MimeMessageHelper helper) { | |||
} | |||
} | |||
``` | |||
- 其他资源文件参考 `classpath://resources` 目录 | |||
### 2.测试 | |||
参考 `MailServiceTest` 测试用例,分别运行各个方法,进行邮件测试 | |||
> 注意: | |||
> 1. 最好是每个方法分别运行,不要直接在测试类上一下跑所有测试用例,因为 Spring 的 `templateResolver` 一旦初始化是不允许修改的 | |||
> 2. **强烈建议各位同学测试的时候,把邮箱改成自己的邮箱进行测试,这样才能实际体会到收到的邮件内容** | |||
> 3. 请勿将 `spring-boot-demo@xkcoding.com` 的邮箱用于发送违法内容,否则作者将收回邮箱权限,同时提交给公安依法追究 | |||
### 3.参考 | |||
- Spring Boot 官方文档:https://docs.spring.io/spring-boot/docs/3.0.0-M4/reference/htmlsingle/#io.email | |||
- Spring 官方文档:https://docs.spring.io/spring-framework/docs/6.0.0-M5/reference/html/integration.html#mail | |||
- jasypt 加解密文档:https://github.com/ulisesbocchio/jasypt-spring-boot#what-to-do-first |
@@ -1,36 +1,40 @@ | |||
<?xml version="1.0" encoding="UTF-8"?> | |||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | |||
<parent> | |||
<groupId>com.xkcoding</groupId> | |||
<artifactId>demo-base</artifactId> | |||
<version>1.0.0-SNAPSHOT</version> | |||
</parent> | |||
<modelVersion>4.0.0</modelVersion> | |||
<artifactId>demo-email</artifactId> | |||
<artifactId>demo-base-email</artifactId> | |||
<version>1.0.0-SNAPSHOT</version> | |||
<packaging>jar</packaging> | |||
<name>demo-email</name> | |||
<name>demo-base-email</name> | |||
<description>Demo project for Spring Boot</description> | |||
<parent> | |||
<groupId>com.xkcoding</groupId> | |||
<artifactId>spring-boot-demo</artifactId> | |||
<version>1.0.0-SNAPSHOT</version> | |||
</parent> | |||
<properties> | |||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> | |||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> | |||
<java.version>1.8</java.version> | |||
<jasypt.version>2.1.1</jasypt.version> | |||
<java.version>17</java.version> | |||
<jasypt.version>3.0.4</jasypt.version> | |||
</properties> | |||
<dependencies> | |||
<dependency> | |||
<groupId>com.xkcoding</groupId> | |||
<artifactId>common-tools</artifactId> | |||
</dependency> | |||
<!-- Spring Boot 邮件依赖 --> | |||
<dependency> | |||
<groupId>org.springframework.boot</groupId> | |||
<artifactId>spring-boot-starter-mail</artifactId> | |||
</dependency> | |||
<!--jasypt配置文件加解密--> | |||
<!-- jasypt配置文件加解密 --> | |||
<dependency> | |||
<groupId>com.github.ulisesbocchio</groupId> | |||
<artifactId>jasypt-spring-boot-starter</artifactId> | |||
@@ -43,11 +47,6 @@ | |||
<scope>test</scope> | |||
</dependency> | |||
<dependency> | |||
<groupId>cn.hutool</groupId> | |||
<artifactId>hutool-all</artifactId> | |||
</dependency> | |||
<!-- Spring Boot 模板依赖 --> | |||
<dependency> | |||
<groupId>org.springframework.boot</groupId> | |||
@@ -56,7 +55,7 @@ | |||
</dependencies> | |||
<build> | |||
<finalName>demo-email</finalName> | |||
<finalName>demo-base-email</finalName> | |||
<plugins> | |||
<plugin> | |||
<groupId>org.springframework.boot</groupId> |
@@ -12,9 +12,9 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; | |||
* @date Created in 2018-11-04 22:38 | |||
*/ | |||
@SpringBootApplication | |||
public class SpringBootDemoEmailApplication { | |||
public class EmailApplication { | |||
public static void main(String[] args) { | |||
SpringApplication.run(SpringBootDemoEmailApplication.class, args); | |||
SpringApplication.run(EmailApplication.class, args); | |||
} | |||
} |
@@ -1,6 +1,6 @@ | |||
package com.xkcoding.email.service; | |||
import javax.mail.MessagingException; | |||
import jakarta.mail.MessagingException; | |||
/** | |||
* <p> | |||
@@ -30,7 +30,7 @@ public interface MailService { | |||
* @param cc 抄送地址 | |||
* @throws MessagingException 邮件发送异常 | |||
*/ | |||
void sendHtmlMail(String to, String subject, String content, String... cc) throws MessagingException; | |||
void sendHtmlMail(String to, String subject, String content, String... cc) throws MessagingException, MessagingException; | |||
/** | |||
* 发送带附件的邮件 |
@@ -2,6 +2,8 @@ package com.xkcoding.email.service.impl; | |||
import cn.hutool.core.util.ArrayUtil; | |||
import com.xkcoding.email.service.MailService; | |||
import jakarta.mail.MessagingException; | |||
import jakarta.mail.internet.MimeMessage; | |||
import org.springframework.beans.factory.annotation.Autowired; | |||
import org.springframework.beans.factory.annotation.Value; | |||
import org.springframework.core.io.FileSystemResource; | |||
@@ -10,8 +12,6 @@ import org.springframework.mail.javamail.JavaMailSender; | |||
import org.springframework.mail.javamail.MimeMessageHelper; | |||
import org.springframework.stereotype.Service; | |||
import javax.mail.MessagingException; | |||
import javax.mail.internet.MimeMessage; | |||
import java.io.File; | |||
/** | |||
@@ -26,7 +26,7 @@ import java.io.File; | |||
public class MailServiceImpl implements MailService { | |||
@Autowired | |||
private JavaMailSender mailSender; | |||
@Value("${spring.mail.username}") | |||
@Value("${spring.mail.from}") | |||
private String from; | |||
/** | |||
@@ -57,20 +57,11 @@ public class MailServiceImpl implements MailService { | |||
* @param subject 邮件主题 | |||
* @param content 邮件内容 | |||
* @param cc 抄送地址 | |||
* @throws MessagingException 邮件发送异常 | |||
*/ | |||
@Override | |||
public void sendHtmlMail(String to, String subject, String content, String... cc) throws MessagingException { | |||
MimeMessage message = mailSender.createMimeMessage(); | |||
MimeMessageHelper helper = new MimeMessageHelper(message, true); | |||
helper.setFrom(from); | |||
helper.setTo(to); | |||
helper.setSubject(subject); | |||
helper.setText(content, true); | |||
if (ArrayUtil.isNotEmpty(cc)) { | |||
helper.setCc(cc); | |||
} | |||
mailSender.send(message); | |||
MimeEmail mimeEmail = basicMimeEmailBuilder(to, subject, content, cc); | |||
mailSender.send(mimeEmail.message()); | |||
} | |||
/** | |||
@@ -85,21 +76,14 @@ public class MailServiceImpl implements MailService { | |||
*/ | |||
@Override | |||
public void sendAttachmentsMail(String to, String subject, String content, String filePath, String... cc) throws MessagingException { | |||
MimeMessage message = mailSender.createMimeMessage(); | |||
MimeEmail mimeEmail = basicMimeEmailBuilder(to, subject, content, cc); | |||
MimeMessageHelper helper = new MimeMessageHelper(message, true); | |||
helper.setFrom(from); | |||
helper.setTo(to); | |||
helper.setSubject(subject); | |||
helper.setText(content, true); | |||
if (ArrayUtil.isNotEmpty(cc)) { | |||
helper.setCc(cc); | |||
} | |||
MimeMessageHelper helper = mimeEmail.helper(); | |||
FileSystemResource file = new FileSystemResource(new File(filePath)); | |||
String fileName = filePath.substring(filePath.lastIndexOf(File.separator)); | |||
helper.addAttachment(fileName, file); | |||
mailSender.send(message); | |||
mailSender.send(mimeEmail.message()); | |||
} | |||
/** | |||
@@ -114,9 +98,22 @@ public class MailServiceImpl implements MailService { | |||
* @throws MessagingException 邮件发送异常 | |||
*/ | |||
@Override | |||
public void sendResourceMail(String to, String subject, String content, String rscPath, String rscId, String... cc) throws MessagingException { | |||
MimeMessage message = mailSender.createMimeMessage(); | |||
public void sendResourceMail(String to, String subject, String content, String rscPath, String rscId, String... cc) | |||
throws MessagingException { | |||
MimeEmail mimeEmail = basicMimeEmailBuilder(to, subject, content, cc); | |||
MimeMessageHelper helper = mimeEmail.helper(); | |||
FileSystemResource res = new FileSystemResource(new File(rscPath)); | |||
helper.addInline(rscId, res); | |||
mailSender.send(mimeEmail.message()); | |||
} | |||
/** | |||
* 富文本邮件构造器,抽取重复代码,返回一个 MimeEmail record | |||
*/ | |||
private MimeEmail basicMimeEmailBuilder(String to, String subject, String content, String... cc) throws MessagingException { | |||
MimeMessage message = mailSender.createMimeMessage(); | |||
MimeMessageHelper helper = new MimeMessageHelper(message, true); | |||
helper.setFrom(from); | |||
helper.setTo(to); | |||
@@ -125,9 +122,10 @@ public class MailServiceImpl implements MailService { | |||
if (ArrayUtil.isNotEmpty(cc)) { | |||
helper.setCc(cc); | |||
} | |||
FileSystemResource res = new FileSystemResource(new File(rscPath)); | |||
helper.addInline(rscId, res); | |||
return new MimeEmail(message, helper); | |||
} | |||
private record MimeEmail(MimeMessage message, MimeMessageHelper helper) { | |||
mailSender.send(message); | |||
} | |||
} |
@@ -2,9 +2,10 @@ spring: | |||
mail: | |||
host: smtp.mxhichina.com | |||
port: 465 | |||
from: "SpringBootDemo测试<${spring.mail.username}>" | |||
username: spring-boot-demo@xkcoding.com | |||
# 使用 jasypt 加密密码,使用com.xkcoding.email.PasswordTest.testGeneratePassword 生成加密密码,替换 ENC(加密密码) | |||
password: ENC(OT0qGOpXrr1Iog1W+fjOiIDCJdBjHyhy) | |||
# 使用 jasypt 加密密码,使用com.xkcoding.email.PasswordTest.testGeneratePassword 生成加密密码,替换 ENC(加密密码) | |||
password: ENC(aef0+nM5440HO7YFAo7iUz8ZHpkjZVlR0hNw3OI/QOPSkNhYRImE/Oy1LBgFKoB1OjqW0v4ZdM0xNS0eKxELfA==) | |||
protocol: smtp | |||
test-connection: true | |||
default-encoding: UTF-8 |
@@ -0,0 +1,13 @@ | |||
package com.xkcoding.email; | |||
import org.junit.jupiter.api.Test; | |||
import org.springframework.boot.test.context.SpringBootTest; | |||
@SpringBootTest | |||
class EmailApplicationTests { | |||
@Test | |||
void contextLoads() { | |||
} | |||
} |
@@ -1,8 +1,9 @@ | |||
package com.xkcoding.email; | |||
import org.jasypt.encryption.StringEncryptor; | |||
import org.junit.Test; | |||
import org.junit.jupiter.api.Test; | |||
import org.springframework.beans.factory.annotation.Autowired; | |||
import org.springframework.boot.test.context.SpringBootTest; | |||
/** | |||
* <p> | |||
@@ -12,7 +13,8 @@ import org.springframework.beans.factory.annotation.Autowired; | |||
* @author yangkai.shen | |||
* @date Created in 2019-08-27 16:15 | |||
*/ | |||
public class PasswordTest extends SpringBootDemoEmailApplicationTests { | |||
@SpringBootTest | |||
class PasswordTest { | |||
@Autowired | |||
private StringEncryptor encryptor; | |||
@@ -20,7 +22,7 @@ public class PasswordTest extends SpringBootDemoEmailApplicationTests { | |||
* 生成加密密码 | |||
*/ | |||
@Test | |||
public void testGeneratePassword() { | |||
void testGeneratePassword() { | |||
// 你的邮箱密码 | |||
String password = "Just4Test!"; | |||
// 加密后的密码(注意:配置上去的时候需要加 ENC(加密密码)) |
@@ -1,15 +1,16 @@ | |||
package com.xkcoding.email.service; | |||
import cn.hutool.core.io.resource.ResourceUtil; | |||
import com.xkcoding.email.SpringBootDemoEmailApplicationTests; | |||
import org.junit.Test; | |||
import com.xkcoding.email.EmailApplication; | |||
import jakarta.mail.MessagingException; | |||
import org.junit.jupiter.api.Test; | |||
import org.springframework.beans.factory.annotation.Autowired; | |||
import org.springframework.boot.test.context.SpringBootTest; | |||
import org.springframework.context.ApplicationContext; | |||
import org.thymeleaf.TemplateEngine; | |||
import org.thymeleaf.context.Context; | |||
import org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver; | |||
import org.thymeleaf.spring6.templateresolver.SpringResourceTemplateResolver; | |||
import javax.mail.MessagingException; | |||
import java.net.URL; | |||
/** | |||
@@ -20,7 +21,8 @@ import java.net.URL; | |||
* @author yangkai.shen | |||
* @date Created in 2018-11-21 13:49 | |||
*/ | |||
public class MailServiceTest extends SpringBootDemoEmailApplicationTests { | |||
@SpringBootTest(classes = EmailApplication.class) | |||
class MailServiceTest { | |||
@Autowired | |||
private MailService mailService; | |||
@Autowired | |||
@@ -37,19 +39,19 @@ public class MailServiceTest extends SpringBootDemoEmailApplicationTests { | |||
} | |||
/** | |||
* 测试HTML邮件 | |||
* 测试HTML邮件(使用 classpath://templates/ 下的模板) | |||
* | |||
* @throws MessagingException 邮件异常 | |||
*/ | |||
@Test | |||
public void sendHtmlMail() throws MessagingException { | |||
Context context = new Context(); | |||
context.setVariable("project", "Spring Boot Demo"); | |||
context.setVariable("author", "Yangkai.Shen"); | |||
context.setVariable("url", "https://github.com/xkcoding/spring-boot-demo"); | |||
void sendHtmlMail1() throws MessagingException { | |||
Context varContext = new Context(); | |||
varContext.setVariable("project", "Spring Boot Demo"); | |||
varContext.setVariable("author", "Yangkai.Shen"); | |||
varContext.setVariable("url", "https://github.com/xkcoding/spring-boot-demo"); | |||
String emailTemplate = templateEngine.process("welcome", context); | |||
mailService.sendHtmlMail("237497819@qq.com", "这是一封模板HTML邮件", emailTemplate); | |||
String emailTemplate = templateEngine.process("welcome", varContext); | |||
mailService.sendHtmlMail("237497819@qq.com", "这是一封模板HTML邮件(templates目录)", emailTemplate); | |||
} | |||
/** | |||
@@ -58,7 +60,7 @@ public class MailServiceTest extends SpringBootDemoEmailApplicationTests { | |||
* @throws MessagingException 邮件异常 | |||
*/ | |||
@Test | |||
public void sendHtmlMail2() throws MessagingException { | |||
void sendHtmlMail2() throws MessagingException { | |||
SpringResourceTemplateResolver templateResolver = new SpringResourceTemplateResolver(); | |||
templateResolver.setApplicationContext(context); | |||
@@ -68,13 +70,13 @@ public class MailServiceTest extends SpringBootDemoEmailApplicationTests { | |||
templateEngine.setTemplateResolver(templateResolver); | |||
Context context = new Context(); | |||
context.setVariable("project", "Spring Boot Demo"); | |||
context.setVariable("author", "Yangkai.Shen"); | |||
context.setVariable("url", "https://github.com/xkcoding/spring-boot-demo"); | |||
Context varContext = new Context(); | |||
varContext.setVariable("project", "Spring Boot Demo"); | |||
varContext.setVariable("author", "Yangkai.Shen"); | |||
varContext.setVariable("url", "https://github.com/xkcoding/spring-boot-demo"); | |||
String emailTemplate = templateEngine.process("test", context); | |||
mailService.sendHtmlMail("237497819@qq.com", "这是一封模板HTML邮件", emailTemplate); | |||
String emailTemplate = templateEngine.process("test", varContext); | |||
mailService.sendHtmlMail("237497819@qq.com", "这是一封模板HTML邮件(自定义目录)", emailTemplate); | |||
} | |||
/** | |||
@@ -83,7 +85,7 @@ public class MailServiceTest extends SpringBootDemoEmailApplicationTests { | |||
* @throws MessagingException 邮件异常 | |||
*/ | |||
@Test | |||
public void sendAttachmentsMail() throws MessagingException { | |||
void sendAttachmentsMail() throws MessagingException { | |||
URL resource = ResourceUtil.getResource("static/xkcoding.png"); | |||
mailService.sendAttachmentsMail("237497819@qq.com", "这是一封带附件的邮件", "邮件中有附件,请注意查收!", resource.getPath()); | |||
} | |||
@@ -94,7 +96,7 @@ public class MailServiceTest extends SpringBootDemoEmailApplicationTests { | |||
* @throws MessagingException 邮件异常 | |||
*/ | |||
@Test | |||
public void sendResourceMail() throws MessagingException { | |||
void sendResourceMail() throws MessagingException { | |||
String rscId = "xkcoding"; | |||
String content = "<html><body>这是带静态资源的邮件<br/><img src=\'cid:" + rscId + "\' ></body></html>"; | |||
URL resource = ResourceUtil.getResource("static/xkcoding.png"); |
@@ -23,6 +23,7 @@ | |||
<module>demo-base-properties</module> | |||
<module>demo-base-async</module> | |||
<module>demo-base-exception</module> | |||
<module>demo-base-email</module> | |||
</modules> | |||
</project> |
@@ -1,25 +0,0 @@ | |||
/target/ | |||
!.mvn/wrapper/maven-wrapper.jar | |||
### STS ### | |||
.apt_generated | |||
.classpath | |||
.factorypath | |||
.project | |||
.settings | |||
.springBeans | |||
.sts4-cache | |||
### IntelliJ IDEA ### | |||
.idea | |||
*.iws | |||
*.iml | |||
*.ipr | |||
### NetBeans ### | |||
/nbproject/private/ | |||
/build/ | |||
/nbbuild/ | |||
/dist/ | |||
/nbdist/ | |||
/.nb-gradle/ |
@@ -1,441 +0,0 @@ | |||
# spring-boot-demo-email | |||
> 此 demo 主要演示了 Spring Boot 如何整合邮件功能,包括发送简单文本邮件、HTML邮件(包括模板HTML邮件)、附件邮件、静态资源邮件。 | |||
## pom.xml | |||
```xml | |||
<?xml version="1.0" encoding="UTF-8"?> | |||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | |||
<modelVersion>4.0.0</modelVersion> | |||
<artifactId>spring-boot-demo-email</artifactId> | |||
<version>1.0.0-SNAPSHOT</version> | |||
<packaging>jar</packaging> | |||
<name>spring-boot-demo-email</name> | |||
<description>Demo project for Spring Boot</description> | |||
<parent> | |||
<groupId>com.xkcoding</groupId> | |||
<artifactId>spring-boot-demo</artifactId> | |||
<version>1.0.0-SNAPSHOT</version> | |||
</parent> | |||
<properties> | |||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> | |||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> | |||
<java.version>1.8</java.version> | |||
<jasypt.version>2.1.1</jasypt.version> | |||
</properties> | |||
<dependencies> | |||
<!-- Spring Boot 邮件依赖 --> | |||
<dependency> | |||
<groupId>org.springframework.boot</groupId> | |||
<artifactId>spring-boot-starter-mail</artifactId> | |||
</dependency> | |||
<!--jasypt配置文件加解密--> | |||
<dependency> | |||
<groupId>com.github.ulisesbocchio</groupId> | |||
<artifactId>jasypt-spring-boot-starter</artifactId> | |||
<version>${jasypt.version}</version> | |||
</dependency> | |||
<dependency> | |||
<groupId>org.springframework.boot</groupId> | |||
<artifactId>spring-boot-starter-test</artifactId> | |||
<scope>test</scope> | |||
</dependency> | |||
<dependency> | |||
<groupId>cn.hutool</groupId> | |||
<artifactId>hutool-all</artifactId> | |||
</dependency> | |||
<!-- Spring Boot 模板依赖 --> | |||
<dependency> | |||
<groupId>org.springframework.boot</groupId> | |||
<artifactId>spring-boot-starter-thymeleaf</artifactId> | |||
</dependency> | |||
</dependencies> | |||
<build> | |||
<finalName>spring-boot-demo-email</finalName> | |||
<plugins> | |||
<plugin> | |||
<groupId>org.springframework.boot</groupId> | |||
<artifactId>spring-boot-maven-plugin</artifactId> | |||
</plugin> | |||
</plugins> | |||
</build> | |||
</project> | |||
``` | |||
## application.yml | |||
```yaml | |||
spring: | |||
mail: | |||
host: smtp.mxhichina.com | |||
port: 465 | |||
username: spring-boot-demo@xkcoding.com | |||
# 使用 jasypt 加密密码,使用com.xkcoding.email.PasswordTest.testGeneratePassword 生成加密密码,替换 ENC(加密密码) | |||
password: ENC(OT0qGOpXrr1Iog1W+fjOiIDCJdBjHyhy) | |||
protocol: smtp | |||
test-connection: true | |||
default-encoding: UTF-8 | |||
properties: | |||
mail.smtp.auth: true | |||
mail.smtp.starttls.enable: true | |||
mail.smtp.starttls.required: true | |||
mail.smtp.ssl.enable: true | |||
mail.display.sendmail: spring-boot-demo | |||
# 为 jasypt 配置解密秘钥 | |||
jasypt: | |||
encryptor: | |||
password: spring-boot-demo | |||
``` | |||
## MailService.java | |||
```java | |||
/** | |||
* <p> | |||
* 邮件接口 | |||
* </p> | |||
* | |||
* @author yangkai.shen | |||
* @date Created in 2018-11-21 11:16 | |||
*/ | |||
public interface MailService { | |||
/** | |||
* 发送文本邮件 | |||
* | |||
* @param to 收件人地址 | |||
* @param subject 邮件主题 | |||
* @param content 邮件内容 | |||
* @param cc 抄送地址 | |||
*/ | |||
void sendSimpleMail(String to, String subject, String content, String... cc); | |||
/** | |||
* 发送HTML邮件 | |||
* | |||
* @param to 收件人地址 | |||
* @param subject 邮件主题 | |||
* @param content 邮件内容 | |||
* @param cc 抄送地址 | |||
* @throws MessagingException 邮件发送异常 | |||
*/ | |||
void sendHtmlMail(String to, String subject, String content, String... cc) throws MessagingException; | |||
/** | |||
* 发送带附件的邮件 | |||
* | |||
* @param to 收件人地址 | |||
* @param subject 邮件主题 | |||
* @param content 邮件内容 | |||
* @param filePath 附件地址 | |||
* @param cc 抄送地址 | |||
* @throws MessagingException 邮件发送异常 | |||
*/ | |||
void sendAttachmentsMail(String to, String subject, String content, String filePath, String... cc) throws MessagingException; | |||
/** | |||
* 发送正文中有静态资源的邮件 | |||
* | |||
* @param to 收件人地址 | |||
* @param subject 邮件主题 | |||
* @param content 邮件内容 | |||
* @param rscPath 静态资源地址 | |||
* @param rscId 静态资源id | |||
* @param cc 抄送地址 | |||
* @throws MessagingException 邮件发送异常 | |||
*/ | |||
void sendResourceMail(String to, String subject, String content, String rscPath, String rscId, String... cc) throws MessagingException; | |||
} | |||
``` | |||
## MailServiceImpl.java | |||
```java | |||
/** | |||
* <p> | |||
* 邮件接口 | |||
* </p> | |||
* | |||
* @author yangkai.shen | |||
* @date Created in 2018-11-21 13:49 | |||
*/ | |||
@Service | |||
public class MailServiceImpl implements MailService { | |||
@Autowired | |||
private JavaMailSender mailSender; | |||
@Value("${spring.mail.username}") | |||
private String from; | |||
/** | |||
* 发送文本邮件 | |||
* | |||
* @param to 收件人地址 | |||
* @param subject 邮件主题 | |||
* @param content 邮件内容 | |||
* @param cc 抄送地址 | |||
*/ | |||
@Override | |||
public void sendSimpleMail(String to, String subject, String content, String... cc) { | |||
SimpleMailMessage message = new SimpleMailMessage(); | |||
message.setFrom(from); | |||
message.setTo(to); | |||
message.setSubject(subject); | |||
message.setText(content); | |||
if (ArrayUtil.isNotEmpty(cc)) { | |||
message.setCc(cc); | |||
} | |||
mailSender.send(message); | |||
} | |||
/** | |||
* 发送HTML邮件 | |||
* | |||
* @param to 收件人地址 | |||
* @param subject 邮件主题 | |||
* @param content 邮件内容 | |||
* @param cc 抄送地址 | |||
* @throws MessagingException 邮件发送异常 | |||
*/ | |||
@Override | |||
public void sendHtmlMail(String to, String subject, String content, String... cc) throws MessagingException { | |||
MimeMessage message = mailSender.createMimeMessage(); | |||
MimeMessageHelper helper = new MimeMessageHelper(message, true); | |||
helper.setFrom(from); | |||
helper.setTo(to); | |||
helper.setSubject(subject); | |||
helper.setText(content, true); | |||
if (ArrayUtil.isNotEmpty(cc)) { | |||
helper.setCc(cc); | |||
} | |||
mailSender.send(message); | |||
} | |||
/** | |||
* 发送带附件的邮件 | |||
* | |||
* @param to 收件人地址 | |||
* @param subject 邮件主题 | |||
* @param content 邮件内容 | |||
* @param filePath 附件地址 | |||
* @param cc 抄送地址 | |||
* @throws MessagingException 邮件发送异常 | |||
*/ | |||
@Override | |||
public void sendAttachmentsMail(String to, String subject, String content, String filePath, String... cc) throws MessagingException { | |||
MimeMessage message = mailSender.createMimeMessage(); | |||
MimeMessageHelper helper = new MimeMessageHelper(message, true); | |||
helper.setFrom(from); | |||
helper.setTo(to); | |||
helper.setSubject(subject); | |||
helper.setText(content, true); | |||
if (ArrayUtil.isNotEmpty(cc)) { | |||
helper.setCc(cc); | |||
} | |||
FileSystemResource file = new FileSystemResource(new File(filePath)); | |||
String fileName = filePath.substring(filePath.lastIndexOf(File.separator)); | |||
helper.addAttachment(fileName, file); | |||
mailSender.send(message); | |||
} | |||
/** | |||
* 发送正文中有静态资源的邮件 | |||
* | |||
* @param to 收件人地址 | |||
* @param subject 邮件主题 | |||
* @param content 邮件内容 | |||
* @param rscPath 静态资源地址 | |||
* @param rscId 静态资源id | |||
* @param cc 抄送地址 | |||
* @throws MessagingException 邮件发送异常 | |||
*/ | |||
@Override | |||
public void sendResourceMail(String to, String subject, String content, String rscPath, String rscId, String... cc) throws MessagingException { | |||
MimeMessage message = mailSender.createMimeMessage(); | |||
MimeMessageHelper helper = new MimeMessageHelper(message, true); | |||
helper.setFrom(from); | |||
helper.setTo(to); | |||
helper.setSubject(subject); | |||
helper.setText(content, true); | |||
if (ArrayUtil.isNotEmpty(cc)) { | |||
helper.setCc(cc); | |||
} | |||
FileSystemResource res = new FileSystemResource(new File(rscPath)); | |||
helper.addInline(rscId, res); | |||
mailSender.send(message); | |||
} | |||
} | |||
``` | |||
## MailServiceTest.java | |||
```java | |||
/** | |||
* <p> | |||
* 邮件测试 | |||
* </p> | |||
* | |||
* @author yangkai.shen | |||
* @date Created in 2018-11-21 13:49 | |||
*/ | |||
public class MailServiceTest extends SpringBootDemoEmailApplicationTests { | |||
@Autowired | |||
private MailService mailService; | |||
@Autowired | |||
private TemplateEngine templateEngine; | |||
@Autowired | |||
private ApplicationContext context; | |||
/** | |||
* 测试简单邮件 | |||
*/ | |||
@Test | |||
public void sendSimpleMail() { | |||
mailService.sendSimpleMail("237497819@qq.com", "这是一封简单邮件", "这是一封普通的SpringBoot测试邮件"); | |||
} | |||
/** | |||
* 测试HTML邮件 | |||
* | |||
* @throws MessagingException 邮件异常 | |||
*/ | |||
@Test | |||
public void sendHtmlMail() throws MessagingException { | |||
Context context = new Context(); | |||
context.setVariable("project", "Spring Boot Demo"); | |||
context.setVariable("author", "Yangkai.Shen"); | |||
context.setVariable("url", "https://github.com/xkcoding/spring-boot-demo"); | |||
String emailTemplate = templateEngine.process("welcome", context); | |||
mailService.sendHtmlMail("237497819@qq.com", "这是一封模板HTML邮件", emailTemplate); | |||
} | |||
/** | |||
* 测试HTML邮件,自定义模板目录 | |||
* | |||
* @throws MessagingException 邮件异常 | |||
*/ | |||
@Test | |||
public void sendHtmlMail2() throws MessagingException { | |||
SpringResourceTemplateResolver templateResolver = new SpringResourceTemplateResolver(); | |||
templateResolver.setApplicationContext(context); | |||
templateResolver.setCacheable(false); | |||
templateResolver.setPrefix("classpath:/email/"); | |||
templateResolver.setSuffix(".html"); | |||
templateEngine.setTemplateResolver(templateResolver); | |||
Context context = new Context(); | |||
context.setVariable("project", "Spring Boot Demo"); | |||
context.setVariable("author", "Yangkai.Shen"); | |||
context.setVariable("url", "https://github.com/xkcoding/spring-boot-demo"); | |||
String emailTemplate = templateEngine.process("test", context); | |||
mailService.sendHtmlMail("237497819@qq.com", "这是一封模板HTML邮件", emailTemplate); | |||
} | |||
/** | |||
* 测试附件邮件 | |||
* | |||
* @throws MessagingException 邮件异常 | |||
*/ | |||
@Test | |||
public void sendAttachmentsMail() throws MessagingException { | |||
URL resource = ResourceUtil.getResource("static/xkcoding.png"); | |||
mailService.sendAttachmentsMail("237497819@qq.com", "这是一封带附件的邮件", "邮件中有附件,请注意查收!", resource.getPath()); | |||
} | |||
/** | |||
* 测试静态资源邮件 | |||
* | |||
* @throws MessagingException 邮件异常 | |||
*/ | |||
@Test | |||
public void sendResourceMail() throws MessagingException { | |||
String rscId = "xkcoding"; | |||
String content = "<html><body>这是带静态资源的邮件<br/><img src=\'cid:" + rscId + "\' ></body></html>"; | |||
URL resource = ResourceUtil.getResource("static/xkcoding.png"); | |||
mailService.sendResourceMail("237497819@qq.com", "这是一封带静态资源的邮件", content, resource.getPath(), rscId); | |||
} | |||
} | |||
``` | |||
## welcome.html | |||
> 此文件为邮件模板,位于 resources/templates 目录下 | |||
```html | |||
<!DOCTYPE html> | |||
<html lang="en" xmlns:th="http://www.thymeleaf.org"> | |||
<head> | |||
<meta charset="UTF-8"> | |||
<title>SpringBootDemo(入门SpringBoot的首选Demo)</title> | |||
<style> | |||
body { | |||
text-align: center; | |||
margin-left: auto; | |||
margin-right: auto; | |||
} | |||
#welcome { | |||
text-align: center; | |||
} | |||
</style> | |||
</head> | |||
<body> | |||
<div id="welcome"> | |||
<h3>欢迎使用 <span th:text="${project}"></span> - Powered By <span th:text=" ${author}"></span></h3> | |||
<span th:text="${url}"></span> | |||
<div style="text-align: center; padding: 10px"> | |||
<a style="text-decoration: none;" href="#" th:href="@{${url}}" target="_bank"> | |||
<strong>spring-boot-demo,入门Spring Boot的首选Demo!:)</strong> | |||
</a> | |||
</div> | |||
<div style="text-align: center; padding: 4px"> | |||
如果对你有帮助,请任意打赏 | |||
</div> | |||
<div style="width: 100%;height: 100%;text-align: center;display: flex"> | |||
<div style="flex: 1;"></div> | |||
<div style="display: flex;width: 400px;"> | |||
<div style="flex: 1;text-align: center;"> | |||
<div> | |||
<img width="180px" height="180px" src="http://xkcoding.com/resources/wechat-reward-image.png"> | |||
</div> | |||
<div>微信打赏</div> | |||
</div> | |||
<div style="flex: 1;text-align: center;"> | |||
<div><img width="180px" height="180px" src="http://xkcoding.com/resources/alipay-reward-image.png"> | |||
</div> | |||
<div>支付宝打赏</div> | |||
</div> | |||
</div> | |||
<div style="flex: 1;"></div> | |||
</div> | |||
</div> | |||
</body> | |||
</html> | |||
``` | |||
## 参考 | |||
- Spring Boot 官方文档:https://docs.spring.io/spring-boot/docs/2.1.0.RELEASE/reference/htmlsingle/#boot-features-email | |||
- Spring Boot 官方文档:https://docs.spring.io/spring/docs/5.1.2.RELEASE/spring-framework-reference/integration.html#mail |
@@ -1,16 +0,0 @@ | |||
package com.xkcoding.email; | |||
import org.junit.Test; | |||
import org.junit.runner.RunWith; | |||
import org.springframework.boot.test.context.SpringBootTest; | |||
import org.springframework.test.context.junit4.SpringRunner; | |||
@RunWith(SpringRunner.class) | |||
@SpringBootTest | |||
public class SpringBootDemoEmailApplicationTests { | |||
@Test | |||
public void contextLoads() { | |||
} | |||
} |
@@ -43,7 +43,6 @@ | |||
<!-- <module>demo-upload</module>--> | |||
<!-- <module>demo-cache-redis</module>--> | |||
<!-- <module>demo-cache-ehcache</module>--> | |||
<!-- <module>demo-email</module>--> | |||
<!-- <module>demo-task</module>--> | |||
<!-- <module>demo-task-quartz</module>--> | |||
<!-- <module>demo-task-xxl-job</module>--> | |||