SpringBoot集成邮件发送底层使用Jakarta Mail技术

一:简述

  在日常中的工作中难免会遇到程序集成邮件发送功能、接收功能;此篇文章我将使用SpringBoot集成邮件发送功能和接收功能;若对邮件一些基本协议和发送流程不懂的请务必参考我之前写的博客或者浏览网上资料。

二:SpringBoot发送邮件的基本说明

  在我们现在使用的SpringBoot的版本中,底层发送邮件的技术都是使用一个叫 Jakarta Mail 的,它可有实现SMTP、POP、IMAP等基本的邮件发送和接收协议。

1:基本环境及坐标依赖

  使用SpringBoot脚手架创建一个SpringBoot项目后导入下面邮件发送坐标,或者在脚手架创建中也可有选择

<!--注:我使用的SpringBoot版本是 2.6.0 -->
<!--注:jakarta mail版本为1.6.7   jakarta activation版本为1.2.2-->
<!--SpringBoot集成邮件发送启动器坐标-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-mail</artifactId>
</dependency>

2:快速上手发送邮件

  在发送邮件前我简单说说JavaMailSenderJavaMailSenderImpl;它们是Spring官方提供的一套邮件功能集成接口及实现,底层调用具体的Jakarta Mail技术;可以说是二次封装;使用SpringBoot提供的接口及实现是后端邮件发送最主流的集成工具;我们在业务里直接注入JavaMailSenderImpl后并调用send方法。其中简单的邮件我们可以通过SimpleMailMessage来发送,对于复杂的带有附件的我们可以借助MimeMessageHelper来构建MimeMessage发送邮件。

application.properties设置基本配置
### smtp服务器主机(163的)
spring.mail.host=smtp.163.com
### 登录服务器邮箱账号
spring.mail.username=antladdie
### 登录服务器邮箱授权码(不是邮箱密码,这个是我们开通SMTP、POP时得到的授权码)
spring.mail.password=xxxxxxxxxxxxxxx
@SpringBootTest
class SpringbootJakartamailApplicationTests {

    //注入邮件发送对象
    @Autowired
    private JavaMailSender mailSender;

    /***
     * 简单邮件发送
     */
    @Test
    void testMailA() {
        //创建简单的邮件发送对象
        SimpleMailMessage message = new SimpleMailMessage();
        message.setFrom("antladdie@163.com");           // 设置发件人邮箱(若配置默认邮箱则不用再设置)
        message.setTo("xiaofeng504@qq.com");            // 设置收件人邮箱
        message.setCc("xiaofeng500@qq.com");            // 设置抄报人邮箱(可以不填写)
        message.setBcc("575814158@qq.com");             // 设置密送人邮箱(可以不填写)
        message.setSubject("缴费通知");                  // 设置邮件主题
        message.setText("您手机已欠费100元,请及时缴费!"); // 设置邮件文本内容
        message.setSentDate(new Date());                // 设置邮件发送时间
        //发送
        mailSender.send(message);
    }
}

3:集成邮件的基本配置(约定大于配置)

  这里的 Jakarta Mail 的 properties 扩展配置不理解的可以参考 官方文档  ; 不过英文的看着头大,这里我将其翻译了

创建邮件会话Session内可配置的properties属性(中文)

#application.properties基本配置,后面我都使用此配置来发送邮件
## 基本配置
### smtp服务器主机(163的)
spring.mail.host=smtp.163.com
### 连接邮件服务器端口(默认SMTP 25 POP 110)
spring.mail.port=25
### 服务协议SMTP(代表是发送邮件)
spring.mail.protocol=smtp
### 登录服务器邮箱账号
spring.mail.username=antladdie
### 登录服务器邮箱授权码(不是邮箱密码,这个是我们开通SMTP、POP时得到的授权码)
spring.mail.password=xxxxxxxxxxxxx
### 默认邮件的编码集(MimeMessage 编码,默认UTF-8)
spring.mail.default-encoding=UTF-8

# 补充配置(这里具体可以参照Jakarta Mail的扩展配置)
## 默认发送方邮箱账号(当程序未指定发件人邮箱则默认取这个)
spring.mail.properties.mail.smtp.from=antladdie@163.com
## 开启权限认证
spring.mail.properties.mail.smtp.auth=true
## 邮件接收时间的限制
spring.mail.properties.mail.smtp.timeout=60000
## 连接时间的限制
spring.mail.properties.mail.smtp.connectiontimeout=60000
## 邮件发送时间的限制(毫秒)
spring.mail.properties.mail.smtp.writetimeout=60000
## 日志打印,邮件发送过程的日志会被输出
spring.mail.properties.mail.debug=true

三:复杂邮件发送 HTML+图片资源+附件

@SpringBootTest
class SpringbootJakartamailApplicationTests {

    //注入邮件发送对象
    @Autowired
    private JavaMailSender mailSender;

    @Test
    void testMailB() throws MessagingException {
        //创建复杂有限发送对象
        MimeMessage mimeMessage = mailSender.createMimeMessage();

        MimeMessageHelper messageHelper = new MimeMessageHelper(mimeMessage, true);
        messageHelper.setFrom("antladdie@163.com");           // 设置发件人邮箱(若配置默认邮箱则不用再设置)
        messageHelper.setTo("xiaofeng504@qq.com");            // 设置收件人邮箱
        messageHelper.setCc("xiaofeng500@qq.com");            // 设置抄报人邮箱(可以不填写)
        messageHelper.setBcc("575814158@qq.com");             // 设置密送人邮箱(可以不填写)
        messageHelper.setSubject("缴费通知");                  // 设置邮件主题

        //获取项目资源根目录 resources/file  并准备资源
        String rootPath = Objects.requireNonNull(SpringbootJakartamailApplicationTests.class.getClassLoader().getResource("file")).getFile();
        FileSystemResource png = new FileSystemResource(new File(rootPath + "/ab.png"));
        FileSystemResource xls = new FileSystemResource(new File(rootPath + "/student.xls"));
        FileSystemResource mp3 = new FileSystemResource(new File(rootPath + "/mu.mp3"));
        FileSystemResource zip = new FileSystemResource(new File(rootPath + "/redis.zip"));

        //关于附件  资源  HTML 文本的设置
        //设置附件
        //设置一个 图片附件
        messageHelper.addAttachment(Objects.requireNonNull(png.getFilename()), png);
        //设置一个 excel附件
        messageHelper.addAttachment(Objects.requireNonNull(xls.getFilename()), xls);
        //设置一个 mp3附件
        messageHelper.addAttachment(Objects.requireNonNull(mp3.getFilename()), mp3);
        //设置一个 zip附件  不过发送垃圾附件可能会被识别 554 HL:IHU 发信IP因发送垃圾邮件或存在异常的连接行为
        messageHelper.addAttachment(Objects.requireNonNull(zip.getFilename()), zip);

        //设置邮件内容   cid:资源id     在内容中引用资源    后面true代表是html内容
        messageHelper.setText("<h2 style='color:#f00;'>欠费通知:您已欠费200元<img src='cid:p01' alt='' style='width:200px;height:50px;'></h2>", true);

        //设置资源
        FileSystemResource resPng = new FileSystemResource(new File(rootPath + "/b.png"));
        messageHelper.addInline("p01",resPng);

        //发送
        mailSender.send(mimeMessage);
    }
}

四:复杂邮件发送使用Thymeleaf模板

  使用模板和不使用模板没太大区别,只是使用模板则将xx.html文件渲染成String类型的字符串文本再引用

<!--导入thymeleaf坐标-->
<dependency>
    <groupId>org.thymeleaf</groupId>
    <artifactId>thymeleaf</artifactId>
    <version>3.0.12.RELEASE</version>
</dependency>

emailTemplate.html模板文件

/***
     * 模板解析方法,解析出一个String的html返回
     * @return
     */
    public String templateHtml(){
        //设置类加载模板处理器
        ClassLoaderTemplateResolver resolver = new ClassLoaderTemplateResolver();
        //设置前缀后缀
        resolver.setPrefix("/file/");
        resolver.setSuffix(".html");
        //创建模板引擎处理器
        TemplateEngine engine = new TemplateEngine();
        //设置引擎使用的模板文件
        engine.setTemplateResolver(resolver);
        //创建Context来为模板设置填充数据
        Context context = new Context();
        //填充模板里的数据
        context.setVariable("message","欠费通知:你已经欠费100元");
        //具体处理,把模板和数据合并成一个新的文本
        //注:文件我直接放在resources/templates文件根目录下,如果有多层目录,需要写明文件位置(或者设置过前缀和后缀)
        return engine.process("emailTemplate", context);
    }

springboot 多账号发邮件 springboot接收邮件_javamail

5:结尾

  讲到这,已经对SpringBoot集成邮件发送功能说完了,若想知道如何接收并解析邮件请参考我上面给出的博客,使用javaMail发送和接收邮件;不过话说回来在大部分公司里使用SMTP、POP3协议发送和接收是完全够用的,不过我上次在项目组负责邮箱的发送使用的是内网的企业邮箱,走的是Exchange协议,这个就和我们之前讲的不一样的,如何使用Exchange方法百度搜特别多的案例发送邮件。