Browse Source

基础模块之 邮件 案例完成

3.x
Yangkai.Shen 2 years ago
parent
commit
0ace6bfd9c
18 changed files with 349 additions and 561 deletions
  1. +255
    -0
      demo-base/demo-base-email/README.md
  2. +17
    -18
      demo-base/demo-base-email/pom.xml
  3. +2
    -2
      demo-base/demo-base-email/src/main/java/com/xkcoding/email/EmailApplication.java
  4. +2
    -2
      demo-base/demo-base-email/src/main/java/com/xkcoding/email/service/MailService.java
  5. +27
    -29
      demo-base/demo-base-email/src/main/java/com/xkcoding/email/service/impl/MailServiceImpl.java
  6. +3
    -2
      demo-base/demo-base-email/src/main/resources/application.yml
  7. +0
    -0
      demo-base/demo-base-email/src/main/resources/email/test.html
  8. BIN
      demo-base/demo-base-email/src/main/resources/static/xkcoding.png
  9. +0
    -0
      demo-base/demo-base-email/src/main/resources/templates/welcome.html
  10. +13
    -0
      demo-base/demo-base-email/src/test/java/com/xkcoding/email/EmailApplicationTests.java
  11. +5
    -3
      demo-base/demo-base-email/src/test/java/com/xkcoding/email/PasswordTest.java
  12. +24
    -22
      demo-base/demo-base-email/src/test/java/com/xkcoding/email/service/MailServiceTest.java
  13. +1
    -0
      demo-base/pom.xml
  14. +0
    -25
      demo-email/.gitignore
  15. +0
    -441
      demo-email/README.md
  16. BIN
      demo-email/src/main/resources/static/xkcoding.png
  17. +0
    -16
      demo-email/src/test/java/com/xkcoding/email/SpringBootDemoEmailApplicationTests.java
  18. +0
    -1
      pom.xml

+ 255
- 0
demo-base/demo-base-email/README.md View File

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

demo-email/pom.xml → demo-base/demo-base-email/pom.xml View File

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

demo-email/src/main/java/com/xkcoding/email/SpringBootDemoEmailApplication.java → demo-base/demo-base-email/src/main/java/com/xkcoding/email/EmailApplication.java View File

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

demo-email/src/main/java/com/xkcoding/email/service/MailService.java → demo-base/demo-base-email/src/main/java/com/xkcoding/email/service/MailService.java View File

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

/**
* 发送带附件的邮件

demo-email/src/main/java/com/xkcoding/email/service/impl/MailServiceImpl.java → demo-base/demo-base-email/src/main/java/com/xkcoding/email/service/impl/MailServiceImpl.java View File

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

demo-email/src/main/resources/application.yml → demo-base/demo-base-email/src/main/resources/application.yml View File

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

demo-email/src/main/resources/email/test.html → demo-base/demo-base-email/src/main/resources/email/test.html View File


BIN
demo-base/demo-base-email/src/main/resources/static/xkcoding.png View File

Before After
Width: 1450  |  Height: 1448  |  Size: 95 kB

demo-email/src/main/resources/templates/welcome.html → demo-base/demo-base-email/src/main/resources/templates/welcome.html View File


+ 13
- 0
demo-base/demo-base-email/src/test/java/com/xkcoding/email/EmailApplicationTests.java View File

@@ -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() {
}

}

demo-email/src/test/java/com/xkcoding/email/PasswordTest.java → demo-base/demo-base-email/src/test/java/com/xkcoding/email/PasswordTest.java View File

@@ -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(加密密码))

demo-email/src/test/java/com/xkcoding/email/service/MailServiceTest.java → demo-base/demo-base-email/src/test/java/com/xkcoding/email/service/MailServiceTest.java View File

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

+ 1
- 0
demo-base/pom.xml View File

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

+ 0
- 25
demo-email/.gitignore View File

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

+ 0
- 441
demo-email/README.md View File

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

BIN
demo-email/src/main/resources/static/xkcoding.png View File

Before After
Width: 100  |  Height: 100  |  Size: 7.3 kB

+ 0
- 16
demo-email/src/test/java/com/xkcoding/email/SpringBootDemoEmailApplicationTests.java View File

@@ -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() {
}

}

+ 0
- 1
pom.xml View File

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


Loading…
Cancel
Save