走进Java接口测试之使用JavaMailSender发送邮件

举报
zuozewei 发表于 2021/09/23 21:20:20 2021/09/23
【摘要】 一般我们在做接口自动化时,都会通过钉钉或者邮件的方式通知测试结果信息。而且基本上邮件的内容都是报告模版,一些差异化的可根据实际情况来进行替换。所以,今天就来讲讲如何利用spring提供的JavaMailSender接口,实现邮件发送功能。

引言

一般我们在做接口自动化时,都会通过钉钉或者邮件的方式通知测试结果信息。而且基本上邮件的内容都是报告模版,一些差异化的可根据实际情况来进行替换。所以,今天就来讲讲如何利用pring提供的JavaMailSender接口,实现邮件发送功能。

背景

讲解前,我们先来简单了解下相关邮件知识。
最早期的时候我们会使用JavaMail相关api来写发送邮件的相关代码,后来spring推出了JavaMailSender更加简化了邮件发送的过程,在之后springboot对此进行了封装就有了现在的spring-boot-starter-mail,本文的介绍主要来自于此包。

JavaMail介绍

JavaMail是由Sun定义的一套收发电子邮件的API,不同的厂商可以提供自己的实现类。但它并没有包含在JDK中,而是作为JavaEE的一部分。而JavaMailSender底层也是基于JavaMailjar包的。

邮件通信协议

  • SMTP:简单邮件传输协议,用于发送电子邮件的传输协议;
  • POP3:用于接收电子邮件的标准协议;
  • IMAP:互联网消息协议,是POP3的替代协议。

这三种协议都有对应SSL加密传输的协议,分别是SMTPSPOP3SIMAPS。除JavaMail服务提供程序之外,JavaMail还需要JAF(JavaBeans Activation Framework)来处理不是纯文本的邮件内容,这包括MIME(多用途互联网邮件扩展)、URL页面和文件附件等内容

JavaMail关键对象

  • Properties:属性对象。针对不同的的邮件协议,JavaMail规定了服务提供者必须支持一系列属性。
    在这里插入图片描述

  • Session会话对象
    这个不要混淆了,和web中的session不一样的,简单来说,它就是配置的集合。
    Session的主要作用包括两个方面:

    • 接收各种配置属性信息:通过Properties对象设置的属性信息;
    • 初始化JavaMail环境:根据JavaMail的配置文件,初始化JavaMail环境,以便通过Session对象创建其他重要类的实例。
  • TransportStore:传输和存储邮件操作只有发送或接收两种处理方式,JavaMail将这两种不同操作描述为传输(javax.mail.Transport)和存储(javax.mail.Store),传输对应邮件的发送,而存储对应邮件的接收。

  • Message:消息对象一旦获得Session对象,就可以继续创建要发送的消息。Message是个抽象类,常用的实现类为:javax.mail.internet.MimeMessage

  • Address:地址创建了SessionMessage,并将内容填入消息后,就可以用Address确定信件地址了。Address也是个抽象类。对应常用实现类:javax.mail.internet.InternetAddress

Spring封装后,使用起来基本上都不需要去关心这些对象值了,简单了解下即可。有兴趣,可以去官网查看:https://java.net/projects/javamail/pages/Home

SpringBoot集成

pom包配置

pom包里面添加包引用

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

        <!-- 模板引擎 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>

        <!-- 效率插件 -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
    </dependencies>

邮箱配置

application.yml中添加邮箱配置

spring:
  mail:
    host: smtp.techstar.com.cn # 邮箱服务器地址
    username: zuozewei@techstar.com.cn # 用户名
    password: 123456      # 密码
    default-encoding: UTF-8

mail:
  fromMail:
    addr: zuozewei@techstar.com.cn  # 以谁来发送邮件

发送纯文本格式

编写mailService接口并实现

/**
 * @author zuozewei
 */
@Component
@Slf4j
public class MailServiceImpl implements MailService {

    @Autowired
    private JavaMailSender mailSender;

    @Value("${mail.fromMail.addr}")
    private String from;

    /**
     * 发送文本邮件
     * @param to
     * @param subject
     * @param content
     */
    @Override
    public void sendSimpleMail(String to, String subject, String content) {
        SimpleMailMessage message = new SimpleMailMessage();
        message.setFrom(from);
        message.setTo(to);
        message.setSubject(subject);
        message.setText(content);

        try {
            mailSender.send(message);
            log.info("简单邮件已经发送。");
        } catch (Exception e) {
            log.error("发送简单邮件时发生异常!", e);
        }

    }
}

编写test类进行测试

@RunWith(SpringRunner.class)
@SpringBootTest
public class MailServiceTest {

    @Autowired
    private MailService mailService;
    
    @Test
    public void testSimpleMail() throws Exception {
        mailService.sendSimpleMail("zuozewei@hotmail.com","test simple mail"," hello this is simple mail");
    }
}

查看收件箱

在这里插入图片描述
至此一个简单的文本发送就完成了。

发送html邮件

但是在正常接口测试的过程中,我们通常在邮件中加入附件完整HTML测试报告来通知测试结果,下面讲介绍如何使用springboot来发送html报告的邮件。

发送html格式邮件

其它都不变在MailService添加sendHtmlMail方法


    /**
     * 发送html邮件
     * @param to
     * @param subject
     * @param content
     */
    @Override
    public void sendHtmlMail(String to, String subject, String content) {
        MimeMessage message = mailSender.createMimeMessage();

        try {
            //true表示需要创建一个multipart message
            MimeMessageHelper helper = new MimeMessageHelper(message, true);
            helper.setFrom(from);
            helper.setTo(to);
            helper.setSubject(subject);
            helper.setText(content, true);

            mailSender.send(message);
            log.info("html邮件发送成功");
        } catch (MessagingException e) {
            log.error("发送html邮件时发生异常!", e);
        }
    }

编写test类进行测试

@Test
    public void testHtmlMail() throws Exception {
        String content="<html>\n" +
                "<body>\n" +
                "    <h3>hello world ! 这是一封html邮件!</h3>\n" +
                "</body>\n" +
                "</html>";
        mailService.sendHtmlMail("zuozewei@hotmail.com","test simple mail",content);
    }

查看收件箱

在这里插入图片描述

发送带附件的邮件

MailService添加sendAttachmentsMail方法

/**
     * 发送带附件的邮件
     * @param to
     * @param subject
     * @param content
     * @param filePath
     */
    public void sendAttachmentsMail(String to, String subject, String content, String filePath){
        MimeMessage message = mailSender.createMimeMessage();

        try {
            MimeMessageHelper helper = new MimeMessageHelper(message, true);
            helper.setFrom(from);
            helper.setTo(to);
            helper.setSubject(subject);
            helper.setText(content, true);
            
			 File file = new File(filePath);
			//获取文件名
            String fileName = file.getAbsolutePath().substring(file.getAbsolutePath().lastIndexOf("/")+1);
            helper.addAttachment(fileName, file);
            mailSender.send(message);
            log.info("带附件的邮件已经发送。");
        } catch (MessagingException e) {
            log.error("发送带附件的邮件时发生异常!", e);
        }

添加多个附件可以使用多条helper.addAttachment(fileName, file)

编写test类进行测试

    @Test
    public void sendAttachmentsMail() {
        String filePath="./test-output/index.html";
        mailService.sendAttachmentsMail("zuozewei@hotmail.com", "主题:带附件测试报告的邮件", "有附件测试报告,请查收!", filePath);
    }

查看收件箱

在这里插入图片描述

发送带静态资源的邮件

邮件中的静态资源一般就是指图片,在MailService添加sendAttachmentsMail方法

/**
     * 发送正文中有静态资源(图片)的邮件
     * @param to
     * @param subject
     * @param content
     * @param rscPath
     * @param rscId
     */
    public void sendInlineResourceMail(String to, String subject, String content, String rscPath, String rscId){
        MimeMessage message = mailSender.createMimeMessage();

        try {
            MimeMessageHelper helper = new MimeMessageHelper(message, true);
            helper.setFrom(from);
            helper.setTo(to);
            helper.setSubject(subject);
            helper.setText(content, true);

            FileSystemResource res = new FileSystemResource(new File(rscPath));
            helper.addInline(rscId, res);

            mailSender.send(message);
            log.info("嵌入静态资源的邮件已经发送。");
        } catch (MessagingException e) {
            log.error("发送嵌入静态资源的邮件时发生异常!", e);
        }

测试类中添加test方法

    @Test
    public void sendInlineResourceMail() {
        String rscId = "test";
        String content="<html><body>这是有图片的邮件:<img src=\'cid:" + rscId + "\' ></body></html>";
        String imgPath = "/Users/apple/Downloads/图片/ads-beverage-black-coffee-33972.jpg";

        mailService.sendInlineResourceMail("zuozewei@hotmail.com", "主题:这是有图片的邮件", content, imgPath, rscId);
    }

查看收件箱
在这里插入图片描述

添加多个图片可以使用多条 <img src='cid:" + rscId + "' >helper.addInline(rscId, res) 来实现

发送模板邮件

接口测试后我们希望收到这样的 ExtentReports 邮件:
在这里插入图片描述

其中只有邮件这个报告内容在变化,其它邮件内容均不变,因此对于这类邮件需求,都建议做成邮件模板来处理。模板的本质很简单,就是在模板中替换变化的参数,转换为html字符串即可,这里以thymeleaf为例来演示。

emailable-report.html放到在resorces/templates下(正式测试需要修改其生成目录)


<!doctype html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Emailable Report</title>
</head>
<body>
<h1>Emailable Report</h1>


<table width="100%" border="1" cellspacing="2" cellpadding="10" style="border-collapse: collapse; display: table;">
    <tbody>
        <tr>
          <th>Test Method</th>
          <th>Status</th>
          <th>Start Time</th>
          <th>Duration</th>
        </tr>

              <tr>
                <th colspan="4">Test Name: <em>first</em> (Suite: <em>first</em>)</th>
              </tr>

                  <tr bgcolor=#FF7F7F>
                    <td>
                        <font color="white"><em>test1</em></font>
                    </td>
                    <td>
                        <font color="white">FAIL</font>
                    </td>
                    <td>
                        <font color="white">Jul 23, 2018 11:50:45 PM</font>
                    </td>
                    <td>
                        <font color="white">0h 0m 0s+5ms</font>
                    </td>
                  </tr>
                  <tr bgcolor=#8CA93E>
                    <td>
                        <font color="white"><em>test2</em></font>
                    </td>
                    <td>
                        <font color="white">PASS</font>
                    </td>
                    <td>
                        <font color="white">Jul 23, 2018 11:50:45 PM</font>
                    </td>
                    <td>
                        <font color="white">0h 0m 0s+1ms</font>
                    </td>
                  </tr>
                  <tr bgcolor=#FF7F7F>
                    <td>
                        <font color="white"><em>test3</em></font>
                    </td>
                    <td>
                        <font color="white">FAIL</font>
                    </td>
                    <td>
                        <font color="white">Jul 23, 2018 11:50:45 PM</font>
                    </td>
                    <td>
                        <font color="white">0h 0m 0s+0ms</font>
                    </td>
                  </tr>
                  <tr bgcolor=#8CA93E>
                    <td>
                        <font color="white"><em>logDemo</em></font>
                    </td>
                    <td>
                        <font color="white">PASS</font>
                    </td>
                    <td>
                        <font color="white">Jul 23, 2018 11:50:45 PM</font>
                    </td>
                    <td>
                        <font color="white">0h 0m 0s+1ms</font>
                    </td>
                  </tr>
    </tbody>
</table>

<p style="color: gray; font-size: 10px; text-align: right;">
    Reports by <a href="http://vimalselvam.com">vimalselvam.com</a>
</p>


您好,请点击下面的链接查看历史报告<br/>
<a href="#" th:href="@{ https://blog.csdn.net/{id}(id=${id}) }">访问Klov ExtentReports</a>

</body>
</html>

解析Html报告并发送

   @Test
    public void sendTemplateMail() {
        //创建邮件正文
        Context context = new Context();
        context.setVariable("id", "zuozewei");
        String emailContent = templateEngine.process("emailable-report.html", context);

        mailService.sendHtmlMail("zuozewei@hotmail.com","主题:这是模板邮件",emailContent);
    }

查看收件箱
在这里插入图片描述

发送失败

因为各种原因,总会有邮件发送失败的情况,比如:邮件发送过于频繁、网络异常等。在出现这种情况的时候,我们一般会考虑重新重试发送邮件,会分为以下几个步骤来实现:

  • 接收到发送邮件请求,首先记录请求并且入库。
  • 调用邮件发送接口发送邮件,并且将发送结果记录入库。
  • 启动定时系统扫描时间段内,未发送成功并且重试次数小于3次的邮件,进行再次发送

本文源码:

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。