Spring Boot 发送邮件

Spring Boot 发送邮件的几种方式

准备工作(以QQ邮箱为例)

SMTP 协议全称为 Simple Mail Transfer Protocol,译作简单邮件传输协议,它定义了邮件客户端软件与 SMTP 服务器之间,以及 SMTP 服务器与 SMTP 服务器之间的通信规则。

也就是说 aaa@qq.com 用户先将邮件投递到腾讯的 SMTP 服务器这个过程就使用了 SMTP 协议,然后腾讯的 SMTP 服务器将邮件投递到网易的 SMTP 服务器这个过程也依然使用了 SMTP 协议,SMTP 服务器就是用来收邮件。

而 POP3 协议全称为 Post Office Protocol ,译作邮局协议,它定义了邮件客户端与 POP3 服务器之间的通信规则,那么该协议在什么场景下会用到呢?当邮件到达网易的 SMTP 服务器之后, 111@163.com 用户需要登录服务器查看邮件,这个时候就该协议就用上了:邮件服务商都会为每一个用户提供专门的邮件存储空间,SMTP 服务器收到邮件之后,就将邮件保存到相应用户的邮件存储空间中,如果用户要读取邮件,就需要通过邮件服务商的 POP3 邮件服务器来完成。

所以在使用springboot发送邮件之前,要开启POP3和SMTP协议,需要获得邮件服务器的授权码,这里以qq邮箱为例,展示获取授权码的过程:

image

在账户的下面有一个开启SMTP协议的开关并进行密码验证:

以下就是你的授权码:

创建项目

添加依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-mail</artifactId>
</dependency>

配置邮箱基本信息

spring:
  mail:
    # 配置 SMTP 服务器地址
    host: smtp.qq.com
    # 发送者邮箱
    username:  ## 自己的邮箱
    # 配置密码,注意不是真正的密码,而是刚刚申请到的授权码
    password:  ## 自己的密钥
    # 端口号465或587
    port: 587 
    # 默认的邮件编码为UTF-8
    default-encoding: UTF-8
    # 配置SSL 加密工厂
    properties:
      mail:
        smtp:
          socketFactoryClass: javax.net.ssl.SSLSocketFactory
        #表示开启 DEBUG 模式,这样,邮件发送过程的日志会在控制台打印出来,方便排查错误
        debug: true
  • 126邮箱SMTP服务器地址: smtp.126.com, 端口号: 465或者994
  • 2163邮箱SMTP服务器地址: smtp.163.com, 端口号: 465或者994
  • yeah邮箱SMTP服务器地址: smtp.yeah.net, 端口号: 465或者994
  • qq邮箱SMTP服务器地址:smtp.qq.com, 端口号: 465或587

配置好这些后,springboot会自动帮我们配置好相关的邮件发送类。

发送普通邮件

@Autowired
private JavaMailSender mailSender;

@Value("${spring.mail.username}")
private String fromMail;

@Test
void testSendSimpleMail() {
    // 构建一个邮件对象
    SimpleMailMessage message = new SimpleMailMessage();
    // 设置邮件主题
    message.setSubject("这是一封测试邮件");
    // 设置邮件发送者,这个跟application.yml中设置的要一致
    message.setFrom(fromMail);
    // 设置邮件接收者,可以有多个接收者,中间用逗号隔开,以下类似
    // message.setTo("10*****16@qq.com","12****32*qq.com");
    message.setTo("1367256434@qq.com");
    // 设置邮件抄送人,可以有多个抄送人
    message.setCc("728578649@qq.com");
    // 设置隐秘抄送人,可以有多个
    // message.setBcc("");
    // 设置邮件发送日期
    message.setSentDate(new Date());
    // 设置邮件的正文
    message.setText("这是测试邮件的正文");
    // 发送邮件
    mailSender.send(message);
}

抄送:将邮件同时送给收信人以外的人,用户所写的邮件抄送一份给别人,对方可以看见该用户的E-mail发送给了谁。

密送:将邮件同时送给收信人以外的人,用户所写的邮件抄送一份给别人,但是对方不能查看到这封邮件同时还发送给了哪些人。

发送的效果如下:

发送带附件的邮件

@Test
void testSendAttachFileMail() throws Exception {
    MimeMessage mimeMessage = mailSender.createMimeMessage();
    // true表示构建一个可以带附件的邮件对象
    MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true);
    // 设置邮件主题
    helper.setSubject("这是一封测试邮件");
    // 设置邮件发送者,这个跟application.yml中设置的要一致
    helper.setFrom(fromMail);
    // 设置邮件接收者,可以有多个接收者,中间用逗号隔开,以下类似
    // message.setTo("10*****16@qq.com","12****32*qq.com");
    helper.setTo("1367256434@qq.com");
    // 设置邮件抄送人,可以有多个抄送人
    helper.setCc("728578649@qq.com");
    // 设置隐秘抄送人,可以有多个
    // message.setBcc("");
    // 设置邮件发送日期
    helper.setSentDate(new Date());
    // 设置邮件的正文
    helper.setText("这是测试邮件的正文");
    // 第一个参数是自定义的名称,后缀需要加上,第二个参数是文件的位置
    helper.addAttachment("资料.txt", new File("D:\\data\\附件.txt"));
    // 发送邮件
    mailSender.send(mimeMessage);
}

注意这里的构建邮件对象的方式跟上面有一点不同,因为这里是需要带附件上传,所以先使用javaMailSender创建一个复杂的邮件对象,然后使用MimeMessageHelper对邮件进行配置,MimeMessageHelper 是一个邮件配置的辅助工具类,创建时候的 true 表示构建一个 multipart message 类型的邮件,有了 MimeMessageHelper 之后,我们针对邮件的配置都是由 MimeMessageHelper 来代劳。然后通过addAttachment()方法添加附件。

发送的效果如下:

发送带图片资源的邮件

/**
 * 正文中带图片的邮件
 *
 * @throws MessagingException 邮件异常
 */
@Test
void testSendImgResMail() throws MessagingException {
    MimeMessage mimeMessage = mailSender.createMimeMessage();
    MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true);
    helper.setSubject("这是一封测试邮件");
    // 设置邮件发送者,这个跟application.yml中设置的要一致
    helper.setFrom(fromMail);
    // 设置邮件接收者,可以有多个接收者,中间用逗号隔开,以下类似
    // message.setTo("10*****16@qq.com","12****32*qq.com");
    helper.setTo("1367256434@qq.com");
    // 设置邮件抄送人,可以有多个抄送人
    helper.setCc("728578649@qq.com");
    // 设置隐秘抄送人,可以有多个
    // message.setBcc("");
    // 设置邮件发送日期
    helper.setSentDate(new Date());
    // src='cid:image01' 占位符写法 ,第二个参数true表示这是一个html文本
    helper.setText("<p>hello 大家好,这是一封测试邮件,这封邮件包含两种图片,分别如下</p><p>第一张图片:</p><img src='cid:image01'/><p>第二张图片:</p><img src='cid:image02'/>", true);
    // 第一个参数指的是html中占位符的名字,第二个参数就是文件的位置
    helper.addInline("image01", new FileSystemResource(new File("D:\\image\\test01.jpg")));
    helper.addInline("image02", new FileSystemResource(new File("D:\\image\\test02.jpg")));
    mailSender.send(mimeMessage);
}

发送的效果如下:

在公司实际开发中,第一种和第三种都不是使用最多的邮件发送方案。因为正常来说,邮件的内容都是比较的丰富的,所以大部分邮件都是通过 HTML 来呈现的,如果直接拼接 HTML 字符串,这样以后不好维护,为了解决这个问题,一般邮件发送,都会有相应的邮件模板。

使用 Thymeleaf 作邮件模板

推荐在 Spring Boot 中使用 Thymeleaf 来构建邮件模板。因为 Thymeleaf 的自动化配置提供了一个 TemplateEngine,通过 TemplateEngine 可以方便的将 Thymeleaf 模板渲染为 HTML ,同时,Thymeleaf 的自动化配置在这里是继续有效的 。

首先,引入 Thymeleaf 依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

创建模板:

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" lang="en">
<head>
    <meta charset="UTF-8">
    <title>发送验证码</title>
    <base target="_blank"/>
    <style type="text/css">::-webkit-scrollbar {
        display: none;
    }</style>
    <style id="cloudAttachStyle" type="text/css">#divNeteaseBigAttach, #divNeteaseBigAttach_bak {
        display: none;
    }</style>
    <style id="blockquoteStyle" type="text/css">blockquote {
        display: none;
    }</style>
    <style type="text/css">
        body {
            font-size: 14px;
            font-family: arial, verdana, sans-serif;
            line-height: 1.666;
            padding: 0;
            margin: 0;
            overflow: auto;
            white-space: normal;
            word-wrap: break-word;
            min-height: 100px
        }

        td, input, button, select, body {
            font-family: Helvetica, 'Microsoft Yahei', verdana
        }

        pre {
            white-space: pre-wrap;
            white-space: -moz-pre-wrap;
            white-space: -pre-wrap;
            white-space: -o-pre-wrap;
            word-wrap: break-word;
            width: 95%
        }

        th, td {
            font-family: arial, verdana, sans-serif;
            line-height: 1.666
        }

        img {
            border: 0
        }

        header, footer, section, aside, article, nav, hgroup, figure, figcaption {
            display: block
        }

        blockquote {
            margin-right: 0px
        }
    </style>
</head>
<body tabindex="0" role="listitem">
<table width="700" border="0" align="center" cellspacing="0" style="width:700px;">
    <tbody>
    <tr>
        <td>
            <div style="width:700px;margin:0 auto;border-bottom:1px solid #ccc;margin-bottom:30px;">
                <table border="0" cellpadding="0" cellspacing="0" width="700" height="39"
                       style="font:12px Tahoma, Arial, 宋体;">
                    <tbody>
                    <tr>
                        <td width="210"></td>
                    </tr>
                    </tbody>
                </table>
            </div>
            <div style="width:680px;padding:0 10px;margin:0 auto;">
                <div style="line-height:1.5;font-size:14px;margin-bottom:25px;color:#4d4d4d;">
                    <strong style="display:block;margin-bottom:15px;">尊敬的用户:<span
                            style="color:#f60;font-size: 16px;"></span>您好!</strong>
                    <strong style="display:block;margin-bottom:15px;">
                        您的验证码为:<span style="color:#f60;font-size: 16px" th:text="${code}"></span>。
                    </strong>
                </div>
                <div style="margin-bottom:30px;">
                    <small style="display:block;margin-bottom:20px;font-size:12px;">
                        <p style="color:#747474;">
                            注意:此操作可能会修改您的密码、登录邮箱或绑定手机。如非本人操作,请及时登录并修改密码以保证帐户安全
                            <br>(工作人员不会向你索取此验证码,请勿泄漏!)
                        </p>
                    </small>
                </div>
            </div>
            <div style="width:700px;margin:0 auto;">
                <div style="padding:10px 10px 0;border-top:1px solid #ccc;color:#747474;margin-bottom:20px;line-height:1.3em;font-size:12px;">
                    <p>此为系统邮件,请勿回复<br>
                        请保管好您的邮箱,避免账号被他人盗用
                    </p>
                    <p>公司名称</p>
                </div>
            </div>
        </td>
    </tr>
    </tbody>
</table>
</body>
</html>

发送邮件:

@Autowired
private TemplateEngine templateEngine;
@Test
void testSendThymeleafMail() throws MessagingException {
    MimeMessage mimeMessage = mailSender.createMimeMessage();
    MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true);
    helper.setSubject("这是一封测试邮件");
    // 设置邮件发送者,这个跟application.yml中设置的要一致
    helper.setFrom(fromMail);
    // 设置邮件接收者,可以有多个接收者,中间用逗号隔开,以下类似
    // message.setTo("10*****16@qq.com","12****32*qq.com");
    helper.setTo("1367256434@qq.com");
    // 设置邮件抄送人,可以有多个抄送人
    helper.setCc("728578649@qq.com");
    // 设置隐秘抄送人,可以有多个
    // message.setBcc("");
    // 设置邮件发送日期
    helper.setSentDate(new Date());
    // 这里引入的是Template的Context
    Context context = new Context();
    // 设置模板中的变量
    context.setVariable("code", "123456");
    // 第一个参数为模板的名称
    String process = templateEngine.process("mailTemplate.html", context);
    // 第二个参数true表示这是一个html文本
    helper.setText(process, true);
    mailSender.send(mimeMessage);
}

发送的效果如下:

完整代码:

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.core.io.FileSystemResource;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context;

import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import java.io.File;
import java.util.Date;

@SpringBootTest
public class MailSenderTest {

    @Autowired
    private JavaMailSender mailSender;

    @Value("${spring.mail.username}")
    private String fromMail;

    @Autowired
    private TemplateEngine templateEngine;

    @Test
    void testSendSimpleMail() {
        // 构建一个邮件对象
        SimpleMailMessage message = new SimpleMailMessage();
        // 设置邮件主题
        message.setSubject("这是一封测试邮件");
        // 设置邮件发送者,这个跟application.yml中设置的要一致
        message.setFrom(fromMail);
        // 设置邮件接收者,可以有多个接收者,中间用逗号隔开,以下类似
        // message.setTo("10*****16@qq.com","12****32*qq.com");
        message.setTo("1367256434@qq.com");
        // 设置邮件抄送人,可以有多个抄送人
        message.setCc("728578649@qq.com");
        // 设置隐秘抄送人,可以有多个
        // message.setBcc("");
        // 设置邮件发送日期
        message.setSentDate(new Date());
        // 设置邮件的正文
        message.setText("这是测试邮件的正文");
        // 发送邮件
        mailSender.send(message);
    }

    @Test
    void testSendAttachFileMail() throws Exception {
        MimeMessage mimeMessage = mailSender.createMimeMessage();
        // true表示构建一个可以带附件的邮件对象
        MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true);
        // 设置邮件主题
        helper.setSubject("这是一封测试邮件");
        // 设置邮件发送者,这个跟application.yml中设置的要一致
        helper.setFrom(fromMail);
        // 设置邮件接收者,可以有多个接收者,中间用逗号隔开,以下类似
        // message.setTo("10*****16@qq.com","12****32*qq.com");
        helper.setTo("1367256434@qq.com");
        // 设置邮件抄送人,可以有多个抄送人
        helper.setCc("728578649@qq.com");
        // 设置隐秘抄送人,可以有多个
        // message.setBcc("");
        // 设置邮件发送日期
        helper.setSentDate(new Date());
        // 设置邮件的正文
        helper.setText("这是测试邮件的正文");
        // 第一个参数是自定义的名称,后缀需要加上,第二个参数是文件的位置
        helper.addAttachment("资料.txt", new File("D:\\data\\附件.txt"));
        // 发送邮件
        mailSender.send(mimeMessage);
    }

    /**
     * 正文中带图片的邮件
     *
     * @throws MessagingException 邮件异常
     */
    @Test
    void testSendImgResMail() throws MessagingException {
        MimeMessage mimeMessage = mailSender.createMimeMessage();
        MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true);
        helper.setSubject("这是一封测试邮件");
        // 设置邮件发送者,这个跟application.yml中设置的要一致
        helper.setFrom(fromMail);
        // 设置邮件接收者,可以有多个接收者,中间用逗号隔开,以下类似
        // message.setTo("10*****16@qq.com","12****32*qq.com");
        helper.setTo("1367256434@qq.com");
        // 设置邮件抄送人,可以有多个抄送人
        helper.setCc("728578649@qq.com");
        // 设置隐秘抄送人,可以有多个
        // message.setBcc("");
        // 设置邮件发送日期
        helper.setSentDate(new Date());
        // src='cid:image01' 占位符写法 ,第二个参数true表示这是一个html文本
        helper.setText("<p>hello 大家好,这是一封测试邮件,这封邮件包含两种图片,分别如下</p><p>第一张图片:</p><img src='cid:image01'/><p>第二张图片:</p><img src='cid:image02'/>", true);
        // 第一个参数指的是html中占位符的名字,第二个参数就是文件的位置
        helper.addInline("image01", new FileSystemResource(new File("D:\\image\\test01.jpg")));
        helper.addInline("image02", new FileSystemResource(new File("D:\\image\\test02.jpg")));
        mailSender.send(mimeMessage);
    }

    @Test
    void testSendThymeleafMail() throws MessagingException {
        MimeMessage mimeMessage = mailSender.createMimeMessage();
        MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true);
        helper.setSubject("这是一封测试邮件");
        // 设置邮件发送者,这个跟application.yml中设置的要一致
        helper.setFrom(fromMail);
        // 设置邮件接收者,可以有多个接收者,中间用逗号隔开,以下类似
        // message.setTo("10*****16@qq.com","12****32*qq.com");
        helper.setTo("1367256434@qq.com");
        // 设置邮件抄送人,可以有多个抄送人
        helper.setCc("728578649@qq.com");
        // 设置隐秘抄送人,可以有多个
        // message.setBcc("");
        // 设置邮件发送日期
        helper.setSentDate(new Date());
        // 这里引入的是Template的Context
        Context context = new Context();
        // 设置模板中的变量
        context.setVariable("code", "123456");
        // 第一个参数为模板的名称
        String process = templateEngine.process("mailTemplate.html", context);
        // 第二个参数true表示这是一个html文本
        helper.setText(process, true);
        mailSender.send(mimeMessage);
    }
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

天青色的小白

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值