• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

Spring boot锦集(二)整合邮件发送的四种方法 | 纯文本的邮件、带有图片的邮件、带Html的邮件、带附件的邮件很详细

武飞扬头像
血煞长虹
帮助1

前言

邮件发送,听着很神秘,然而对于Spring Boot来说,这个功能已被集成好,只需引入spring-boot-starter-mail依赖后,少量代码即可实现大部分邮件发送需求。

本文以异常教程为依托,做了进一步优化,可读性更强。

因发送邮件的方法只是在调用上,略有改动(比如,设置参数是否包含有ture),故在代码编排上,写在一个类中了,后面单元测试时分开测试即可。


¥¥¥¥¥具体操作步骤如下¥¥¥¥¥


一、创建Spring boot工程后,在pom.xml中添加依赖

1.1、方式一,新建工程时,在IO选项勾选邮件依赖

学新通

勾选后,spring-boot-starter-mail 依赖会被自动引入到pom.xml中 

1.2、方式二,手动在pom.xml中添加依赖

引入:mail核心依赖

  1.  
    <dependencies>
  2.  
    <dependency>
  3.  
    <groupId>org.springframework.boot</groupId>
  4.  
    <artifactId>spring-boot-starter-mail</artifactId>
  5.  
    </dependency>
  6.  
    </dependencies>

其他相关依赖,可以酌情引入,需要注意的是,如果在项目中,无法自动导入依赖包,则很可能是下面的某个依赖,你没有引入,引入后鼠标右键pom.xml-->Maven-->Reload Project,就可以了。

  1.  
    <dependency>
  2.  
    <groupId>org.springframework.boot</groupId>
  3.  
    <artifactId>spring-boot-starter</artifactId>
  4.  
    <exclusions>
  5.  
    <!--不使用默认的 logback日志,使用下面的log4j2-->
  6.  
    <exclusion>
  7.  
    <groupId>org.springframework.boot</groupId>
  8.  
    <artifactId>spring-boot-starter-logging</artifactId>
  9.  
    </exclusion>
  10.  
    </exclusions>
  11.  
    </dependency>
  12.  
    <dependency>
  13.  
    <groupId>org.springframework.boot</groupId>
  14.  
    <artifactId>spring-boot-starter-log4j2</artifactId>
  15.  
    </dependency>
  16.  
     
  17.  
    <dependency>
  18.  
    <groupId>org.springframework.boot</groupId>
  19.  
    <artifactId>spring-boot-starter-web</artifactId>
  20.  
    <!-- 移除掉默认支持的 Tomcat -->
  21.  
    <exclusions>
  22.  
    <exclusion>
  23.  
    <groupId>org.springframework.boot</groupId>
  24.  
    <artifactId>spring-boot-starter-tomcat</artifactId>
  25.  
    </exclusion>
  26.  
    </exclusions>
  27.  
    </dependency>
  28.  
    <!-- 添加 Undertow 容器 -->
  29.  
    <dependency>
  30.  
    <groupId>org.springframework.boot</groupId>
  31.  
    <artifactId>spring-boot-starter-undertow</artifactId>
  32.  
    </dependency>
  33.  
    <dependency>
  34.  
    <groupId>org.springframework.boot</groupId>
  35.  
    <artifactId>spring-boot-starter-test</artifactId>
  36.  
    <scope>test</scope>
  37.  
    </dependency>
  38.  
    <!-- aop 依赖 -->
  39.  
    <dependency>
  40.  
    <groupId>org.springframework.boot</groupId>
  41.  
    <artifactId>spring-boot-starter-aop</artifactId>
  42.  
    </dependency>
  43.  
     
  44.  
    <!-- 用于日志切面中,以 gson 格式打印出入参 -->
  45.  
    <dependency>
  46.  
    <groupId>com.谷歌.code.gson</groupId>
  47.  
    <artifactId>gson</artifactId>
  48.  
    </dependency>
  49.  
    <dependency>
  50.  
    <groupId>org.projectlombok</groupId>
  51.  
    <artifactId>lombok</artifactId>
  52.  
    <version>1.18.24</version>
  53.  
    </dependency>
  54.  
    <!-- 引入DevTools热部署 -->
  55.  
    <dependency>
  56.  
    <groupId>org.springframework.boot</groupId>
  57.  
    <artifactId>spring-boot-devtools</artifactId>
  58.  
    <scope>runtime</scope>
  59.  
    <optional>true</optional>
  60.  
    </dependency>
学新通

二、在工程resource目录下创建application.properties文件,并添加相关配置

注意:下面的邮箱地址,是你自己的邮箱(作为邮件的发送者);密码是对应邮箱的登录密码或授权码,授权码在下方会有详细介绍,本文以163邮箱为例!

  1.  
    # 发送邮件的服务器,
  2.  
    # QQ 邮件:smtp.qq.com
  3.  
    # 如果是163邮箱,变更为“smtp.163.com”即可
  4.  
    spring.mail.host=smtp.163.com
  5.  
    #你的邮箱地址
  6.  
    spring.mail.username=123456789@163.com
  7.  
    #授权码,或邮箱登录密码
  8.  
    spring.mail.password=123456
  9.  
    #是否开启验证 true为开启,false不开启
  10.  
    spring.mail.properties.mail.smtp.auth=true
  11.  
    #通讯是否加密,true开启,false不开启
  12.  
    spring.mail.properties.mail.smtp.starttls.enable=true
  13.  
    #是否必须通过使用加密通讯进行通讯,true开启,false不开启
  14.  
    spring.mail.properties.mail.smtp.starttls.required=true

提示:如果你想使用application.yml配置文件,则格式如下 

  1.  
    spring:
  2.  
    mail:
  3.  
    host: smtp.qq.com #发送邮件的服务器
  4.  
    username: 你的邮箱地址
  5.  
    password: 授权码,或邮箱密码
  6.  
    properties.mail.smtp.auth: true
  7.  
    properties.mail.smtp.starttls.enable: true
  8.  
    default-encoding: utf-8

三、关于授权码

如果使用的是 163 邮箱,或者 Gmail 邮箱,直接使用密码就可以了,如果使用的是 QQ 邮箱,则需要先获取授权码。

3.1、什么是 QQ 邮箱授权码

官方解释如下图所示

学新通

3.2、如何获取QQ授权码 

3.2.1、登录 QQ 邮箱

学新通

3.2.2、点击设置,再点击页签中的“账户”

学新通

3.2.3、跳转页面后,点击账户,将页面往下拖动,您会看到,授权码的开启菜单

学新通

3.2.4、点击“开启”,验证成功过后,即可获取授权码

学新通

3.3、163邮箱的授权码

我的账号默认是开启的,如果你的没有开启,如下步骤操作

3.3.1、点击顶部页签的”"设置"按钮,进入POP3设置界面

学新通

3.3.2、开启服务,也可以重新生成授权码

学新通

3.4、 发送邮件所需要遵从的POP3/SMTP/IMAP三个协议的简述

SMTP(Simple Mail Transfer Protocol):简单邮件传输协议,用于发送电子邮件的传输协议。

POP3(Post Office Protocol - Version 3):用于接收电子邮件的标准协议。

IMAP(Internet Mail Access Protocol):互联网消息协议,是POP3的替代协议。

简而言之,SMTP是发邮件必须遵从的标准,POP3是接收邮件要遵从的标准,而IMAP是对POP3协议的升级,日常工作中,我们主要使用的是发邮件操作。

四、业务代码

4.1、新增MailService接口,并声明4个发送不同类型邮件的方法

注:入参多于3个的情况下,通常也会把入参封装为一个实体Bean,方便起见,这里就不封装了。

  1.  
    package com.example.demo.service;
  2.  
     
  3.  
    /**
  4.  
    * @author xyp
  5.  
    * @create 2022-10-07 12:57
  6.  
    * @describe 邮件发送接口,定义发送不同类型邮件的方法
  7.  
    */
  8.  
    public interface MailService {
  9.  
    /**
  10.  
    * 发送简单文本的邮件
  11.  
    * @param to
  12.  
    * @param subject
  13.  
    * @param content
  14.  
    * @return
  15.  
    */
  16.  
    boolean sendSimpleText(String to, String subject, String content);
  17.  
     
  18.  
    /**
  19.  
    * 发送 html 的邮件
  20.  
    * @param to
  21.  
    * @param subject
  22.  
    * @param html
  23.  
    * @return
  24.  
    */
  25.  
    boolean sendWithHtml(String to, String subject, String html);
  26.  
     
  27.  
    /**
  28.  
    * 发送带有图片的 html 的邮件
  29.  
    * @param to
  30.  
    * @param subject
  31.  
    * @param html
  32.  
    * @param cids
  33.  
    * @param filePaths
  34.  
    * @return
  35.  
    */
  36.  
    boolean sendWithImageHtml(String to, String subject, String html, String[] cids, String[] filePaths);
  37.  
     
  38.  
     
  39.  
    /**
  40.  
    * 发送带有附件的邮件
  41.  
    * @param to
  42.  
    * @param subject
  43.  
    * @param content
  44.  
    * @param filePaths
  45.  
    * @return
  46.  
    */
  47.  
    boolean sendWithWithEnclosure(String to, String subject, String content, String[] filePaths);
  48.  
    }
  49.  
     
学新通

4.2、新增MailService接口的实现类MailServiceImpl

  1.  
    package com.example.demo.service.impl;
  2.  
     
  3.  
    import com.example.demo.service.MailService;
  4.  
    import org.slf4j.Logger;
  5.  
    import org.slf4j.LoggerFactory;
  6.  
    import org.springframework.beans.factory.annotation.Autowired;
  7.  
    import org.springframework.boot.autoconfigure.mail.MailProperties;
  8.  
    import org.springframework.core.io.FileSystemResource;
  9.  
    import org.springframework.mail.SimpleMailMessage;
  10.  
    import org.springframework.mail.javamail.JavaMailSender;
  11.  
    import org.springframework.mail.javamail.MimeMessageHelper;
  12.  
     
  13.  
    import javax.mail.internet.MimeMessage;
  14.  
     
  15.  
    /**
  16.  
    * @author xyp
  17.  
    * @create 2022-10-07 13:01
  18.  
    * @describe
  19.  
    */
  20.  
    @Component //没有这个注解,发送邮件时可能会引发空指针异常
  21.  
    public class MailServiceImpl implements MailService {
  22.  
     
  23.  
    private final static Logger logger = LoggerFactory.getLogger(MailServiceImpl.class);
  24.  
     
  25.  
    @Autowired
  26.  
    private MailProperties mailProperties;
  27.  
    @Autowired
  28.  
    private JavaMailSender javaMailSender;
  29.  
     
  30.  
    @Override
  31.  
    public boolean sendSimpleText(String to, String subject, String content) {
  32.  
    logger.info("## Ready to send mail ...");
  33.  
     
  34.  
    SimpleMailMessage simpleMailMessage = new SimpleMailMessage();
  35.  
    // 邮件发送来源
  36.  
    simpleMailMessage.setFrom(mailProperties.getUsername());
  37.  
    // 邮件发送目标
  38.  
    simpleMailMessage.setTo(to);
  39.  
    // 设置标题
  40.  
    simpleMailMessage.setSubject(subject);
  41.  
    // 设置内容
  42.  
    simpleMailMessage.setText(content);
  43.  
     
  44.  
    try {
  45.  
    // 发送
  46.  
    javaMailSender.send(simpleMailMessage);
  47.  
    logger.info("## Send the mail success ...");
  48.  
    } catch (Exception e) {
  49.  
    logger.error("Send mail error: ", e);
  50.  
    return false;
  51.  
    }
  52.  
     
  53.  
    return true;
  54.  
    }
  55.  
     
  56.  
    @Override
  57.  
    public boolean sendWithHtml(String to, String subject, String html) {
  58.  
    logger.info("## Ready to send mail ...");
  59.  
    MimeMessage mimeMessage = javaMailSender.createMimeMessage();
  60.  
     
  61.  
    MimeMessageHelper mimeMessageHelper = null;
  62.  
    try {
  63.  
    mimeMessageHelper = new MimeMessageHelper(mimeMessage, true);
  64.  
    // 邮件发送来源
  65.  
    mimeMessageHelper.setFrom(mailProperties.getUsername());
  66.  
    // 邮件发送目标
  67.  
    mimeMessageHelper.setTo(to);
  68.  
    // 设置标题
  69.  
    mimeMessageHelper.setSubject(subject);
  70.  
    // 设置内容,并设置内容 html 格式为 true
  71.  
    mimeMessageHelper.setText(html, true);
  72.  
     
  73.  
    javaMailSender.send(mimeMessage);
  74.  
    logger.info("## Send the mail with html success ...");
  75.  
    } catch (Exception e) {
  76.  
    e.printStackTrace();
  77.  
    logger.error("Send html mail error: ", e);
  78.  
    return false;
  79.  
    }
  80.  
     
  81.  
    return true;
  82.  
    }
  83.  
     
  84.  
    @Override
  85.  
    public boolean sendWithImageHtml(String to, String subject, String html, String[] cids, String[] filePaths) {
  86.  
    logger.info("## Ready to send mail ...");
  87.  
    MimeMessage mimeMessage = javaMailSender.createMimeMessage();
  88.  
     
  89.  
    MimeMessageHelper mimeMessageHelper = null;
  90.  
    try {
  91.  
    mimeMessageHelper = new MimeMessageHelper(mimeMessage, true);
  92.  
    // 邮件发送来源
  93.  
    mimeMessageHelper.setFrom(mailProperties.getUsername());
  94.  
    // 邮件发送目标
  95.  
    mimeMessageHelper.setTo(to);
  96.  
    // 设置标题
  97.  
    mimeMessageHelper.setSubject(subject);
  98.  
    // 设置内容,并设置内容 html 格式为 true
  99.  
    mimeMessageHelper.setText(html, true);
  100.  
     
  101.  
    // 设置 html 中内联的图片
  102.  
    for (int i = 0; i < cids.length; i ) {
  103.  
    FileSystemResource file = new FileSystemResource(filePaths[i]);
  104.  
    // addInline() 方法 cid 需要 html 中的 cid (Content ID) 对应,才能设置图片成功,
  105.  
    // 具体可以参见,下面 4.3.3 单元测试的参数设置
  106.  
    mimeMessageHelper.addInline(cids[i], file);
  107.  
    }
  108.  
     
  109.  
    javaMailSender.send(mimeMessage);
  110.  
    logger.info("## Send the mail with image success ...");
  111.  
    } catch (Exception e) {
  112.  
    e.printStackTrace();
  113.  
    logger.error("Send html mail error: ", e);
  114.  
    return false;
  115.  
    }
  116.  
     
  117.  
    return true;
  118.  
    }
  119.  
     
  120.  
    @Override
  121.  
    public boolean sendWithWithEnclosure(String to, String subject, String content, String[] filePaths) {
  122.  
    logger.info("## Ready to send mail ...");
  123.  
    MimeMessage mimeMessage = javaMailSender.createMimeMessage();
  124.  
     
  125.  
    MimeMessageHelper mimeMessageHelper = null;
  126.  
    try {
  127.  
    // 设置为true,代表要支持附件
  128.  
    mimeMessageHelper = new MimeMessageHelper(mimeMessage, true);
  129.  
    // 邮件发送来源
  130.  
    mimeMessageHelper.setFrom(mailProperties.getUsername());
  131.  
    // 邮件发送目标
  132.  
    mimeMessageHelper.setTo(to);
  133.  
    // 设置标题
  134.  
    mimeMessageHelper.setSubject(subject);
  135.  
    // 设置内容
  136.  
    mimeMessageHelper.setText(content);
  137.  
     
  138.  
    // 添加附件
  139.  
    for (int i = 0; i < filePaths.length; i ) {
  140.  
    FileSystemResource file = new FileSystemResource(filePaths[i]);
  141.  
    String attachementFileName = "附件" (i 1) "_" file.getFilename();
  142.  
    mimeMessageHelper.addAttachment(attachementFileName, file);
  143.  
    }
  144.  
     
  145.  
    javaMailSender.send(mimeMessage);
  146.  
    logger.info("## Send the mail with enclosure success ...");
  147.  
    } catch (Exception e) {
  148.  
    logger.error("Send html mail error: ", e);
  149.  
    return false;
  150.  
    }
  151.  
    return true;
  152.  
    }
  153.  
    }
  154.  
     
学新通

4.3、工程目录结构查看

如下图所示,核心的几个类,都被红色的框,框选着的,其他一些package与本项目无关。

学新通

五、单元测试,查看成果

准备工作

1、在pom中引入单元测试的依赖

  1.  
    <dependency>
  2.  
    <groupId>junit</groupId>
  3.  
    <artifactId>junit</artifactId>
  4.  
    <version>4.9</version>
  5.  
    <scope>test</scope>
  6.  
    </dependency>

需要注意的是,在单元测试类中,所有与单元测试类相关的类,都来自于junit,不要使用默认的。

2、在test单元测试目录,新建SpringBootMailTest.java类

学新通

5.1、发送纯文本邮件的测试

5.1.1、测试代码编写

  1.  
    package com.example.demo;
  2.  
     
  3.  
    import com.example.demo.service.MailService;
  4.  
    import org.junit.Assert;//注意这个包是junit的,不是自带的
  5.  
    import org.junit.jupiter.api.Test;
  6.  
    import org.springframework.beans.factory.annotation.Autowired;
  7.  
    import org.springframework.boot.test.context.SpringBootTest;
  8.  
     
  9.  
    /**
  10.  
    * @author xyp
  11.  
    * @create 2022-10-07 15:07
  12.  
    * @describe
  13.  
    */
  14.  
    @SpringBootTest
  15.  
    public class SpringBootMailTest {
  16.  
     
  17.  
    @Autowired(required = false)
  18.  
    private MailService mailService;
  19.  
     
  20.  
    @Test
  21.  
    public void sendSimpleText(){
  22.  
    String to="871038951@qq.com";
  23.  
    String title="标题:简单的文本发送测试";
  24.  
    String content="简单的文本";
  25.  
    Assert.assertTrue(mailService.sendSimpleText(to,title,content));
  26.  
    }
  27.  
    }
  28.  
     
学新通

5.1.2、运行查看,报错小插曲

学新通

初次运行,可能会报如下错误

学新通

 经百般百度后,得知需要给MailServicel的实现类MailServiceImpl添加@Component注解

学新通

5.1.3、给MailServiceImpl添加@Component注解后,再试

学新通

 学新通

 学新通

 至此,第一个纯文本邮件发送,测试成功! 

5.2、发送纯HTML文本测试

5.2.1、测试代码编写

  1.  
    @Test
  2.  
    public void sendHtml(){
  3.  
    String to="871038951@qq.com";
  4.  
    String title="标题:Html文本发送测试";
  5.  
    String htmlContent="<html><body><h1>欢迎来到 Spring boot 的世界</h1></body></html>";
  6.  
    Assert.assertTrue(mailService.sendWithHtml(to,title,htmlContent));
  7.  
    }

5.2.2、运行并查看结果

学新通

运行后,收到邮件提示

 学新通

进入邮箱,并打开

学新通

 学新通

至此,第二个发送Html的测试,测试成功!  

5.3、发送带图片的HTML测试

5.3.1、测试代码编写

  1.  
    @Test
  2.  
    public void sendWithImageHtml(){
  3.  
    String to="871038951@qq.com";
  4.  
    String title="标题:带有图片的Html发送测试";
  5.  
    String htmlContent="<html><body>"
  6.  
    "<h1>欢迎来到 Spring boot 的世界</h1>"
  7.  
    "<image width='50' height='60' src='cid:test1'>图片1 </image>" //cid:是约定好的固定格式,只需要修改后面的变量
  8.  
    "<image width='50' height='60' src='cid:test2'>图片1 </image>"
  9.  
    "</body></html>";
  10.  
    //数组中的cid要和上面html中image中的cid一致,否则图片将设置失败
  11.  
    String[] cids=new String[]{"test1","test2"};
  12.  
    String[] filePaths=new String[]{
  13.  
    "D:\\Documents\\ioc\\MyIco\\pao1.ico",
  14.  
    "D:\\Documents\\ioc\\MyIco\\xiang2.ico"
  15.  
    };
  16.  
    Assertions.assertTrue(mailService.sendWithImageHtml(to,title,htmlContent,cids,filePaths));
  17.  
    }
学新通

5.3.2、运行并查看结果

学新通

电脑右下角有邮件提醒

 学新通

进入邮箱,查看邮件

学新通 学新通

 至此,第三个发送带图片的Html邮件,测试成功! 

5.4、发送带附件的测试

5.4.1、测试代码编写 

  1.  
    @Test
  2.  
    public void sendWithWithEnclosure(){
  3.  
    String to="871038951@qq.com";
  4.  
    String title="标题:带有附件的邮件发送测试";
  5.  
    String content="欢迎来到 Spring boot 的世界";
  6.  
    String[] filePaths=new String[]{
  7.  
    "D:\\Documents\\ioc\\MyIco\\pao1.ico",
  8.  
    "D:\\Documents\\ioc\\MyIco\\expect5.45.tar.gz"
  9.  
    };
  10.  
    Assert.assertTrue(mailService.sendWithWithEnclosure(to,title,content,filePaths));
  11.  
    }

5.5.2、运行并查看结果

学新通

注:刚开始附件,测试的是图片,为了测试压缩包是否能被当做附件发送,又新增了压缩包的测试。

电脑右下角弹出新邮件提示:

学新通

进入收件箱查看邮件

学新通

 学新通

经测试,下载后,附件可以正常打开。 

至此,各个案例都演示完毕!

后记

文章核心源码来自异常教程,由于它存在一定的纰漏(比如,附件不能正常打开,接口实现类未被注解,导致报错等),本文在此基础上做了一下优化!

总结

案例虽然简单,总的来说,这个几个方法还是有一定的局限性,不过它为我们今后整合一个功能更齐全的邮件发送功能,带来的指引和启发,已经够用了。

注意下面几行点参数中true的含义:

  1.  
    //纯文本邮件,不用带任何参数
  2.  
    SimpleMailMessage simpleMailMessage = new SimpleMailMessage();
  3.  
    simpleMailMessage .setText(contentText);
  1.  
    // 邮件内容如果是html和图片,则下面两处都需要设置为true
  2.  
    mimeMessageHelper = new MimeMessageHelper(mimeMessage, true);//如果是仅支持附件,这一处设置为true即可
  3.  
    mimeMessageHelper.setText(html, true);

注意:连续发内容相同的邮件,会被判定为垃圾邮件,可能会被拦截。

尾言

最后,再次感谢异常教程的无私分享,希望本文能对有需要的小伙伴们有所启示。

因水平有限,整理过程中,难免也会有所纰漏和错误,如有发现望批评指正。

如果觉得还不错,赶快收藏点赞吧!

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhgekhje
系列文章
更多 icon
同类精品
更多 icon
继续加载