SpringBoot实现发送电子邮件

SpringBoot知识体系

目录html


从1969年10月世界上的第一封电子邮件发出,到2019年,已通过去将近半个世纪了。虽然即时通信和视频会议,甚至全息投影都变得日益普及,但电子邮件依然有着普遍的使用场景和不可撼动的历史地位。java

SpringBoot拥有强大的生态链,几乎能够链接全部主流的开源库。git

下面咱们就从电子邮件发送的历史再到原理,而后如何本身配置邮件服务器并发送邮件,一步步讲解。github

本文实现源码能够在这里找到: SpringBoot发送电子邮件源码web

电子邮件与Java发送邮件的历史

  1. 1969年10月,世界上的第一封电子邮件

1969年10月世界上的第一封电子邮件是由计算机科学家Leonard K.教授发给他的同事的一条简短消息。第一条网上信息就是‘LO’,意思是‘你好!’。spring

  1. 1987年9月14日中国的第一封电子邮件

在此以后,1987年9月14日中国的第一封电子邮件,这封邮件是由德国维尔纳·措恩与中国的王运丰在北京计算机应用技术研究所,发往德国一个大学的,邮件内容颇具深意,“Across the Great Wall we can reach every corner in the world.(越过长城,走向世界)”,这是中国经过北京与德国大学之间的网络链接,向全球科学网发出的第一封电子邮件。浏览器

  1. 30年代发展历程

接下来中国的电子邮件进入了30年的发展期,虽然在1987年就有了电子邮件,可是,真正的邮件兴起,应该在90年代到2000年之间,由于在1987的时候中国网速特别慢,真正能接触到互联网的用户是很是少的,到了90年代中期,互联网浏览器的诞生,使得全民上网人数激增,电子邮件被普遍使用,此时,中国的部分学生在研究中使用到电子邮件,真正普及的时间是在2000年左右。安全

  1. Java发送邮件

Java在发明之初,就开始支持发送邮件,经过java mail包方式去操做邮件发送的内容和协议,可是,这种发送方式稍微比较复杂,须要配置各类参数、协议、内容,以后产生了Spring框架。springboot

  1. Spring发送邮件

Spring在java mail的基础上进行了一些封装,使发送邮件的过程的复杂大大减小。服务器

  1. SpringBoot发送邮件

SpringBoot Mail在Spring Mail的基础上,再次进行一次封装,使得发送邮件的便利度上,更为简单。

电子邮件原理

电子邮件服务器

用户要在Internet上提供电子邮件功能,必须有专门的电子邮件服务器。这些邮件服务器就相似于现实生活中的邮局,它主要负责接收用户投递过来的邮件,并把邮件投递到邮件接收者的电子邮箱中。

邮件服务器就好像是互联网世界的邮局。按照功能划分,邮件服务器能够划分为两种类型:

  1. SMTP邮件服务器:用户替用户发送邮件和接收外面发送给本地用户的邮件。
  2. POP3/IMAP邮件服务器:用户帮助用户读取SMTP邮件服务器接收进来的邮件。

电子邮箱

电子邮箱也称为E-mail地址,用户能够经过E-mail地址来标识本身发送的电子邮件,也能够经过这个地址接收别人发来的电子邮件。电子邮箱须要到邮件服务器进行申请,也就是说,电子邮箱其实就是用户在邮件服务器上申请的帐户。邮件服务器会把接收到的邮件保存到为该帐户所分配的邮箱空间中,用户经过用户名密码登陆到邮件服务器查收该地址已经收到的邮件。通常来说,邮件服务器为用户分配的邮箱空间是有限的。

邮件客户端

咱们能够直接在网站上进行邮件收发,也可使用常见的FoxMail、Outlook等邮件客户端软件接受邮件。邮件客户端软件一般集邮件撰写、发送和收发功能于一体,主要用于帮助用户将邮件发送给SMTP邮件服务器和从POP3/IMAP邮件服务器读取用户的电子邮件。

邮件传输协议

电子邮件须要在邮件客户端和邮件服务器之间,以及两个邮件服务器之间进行邮件传递,那就必需要遵照必定的规则,这个规则就是邮件传输协议。下面咱们分别简单介绍几种协议:

  1. SMTP协议:全称为 Simple Mail Transfer Protocol,简单邮件传输协议。它定义了邮件客户端软件和SMTP邮件服务器之间,以及两台SMTP邮件服务器之间的通讯规则。
  2. POP3协议:全称为 Post Office Protocol,邮局协议。它定义了邮件客户端软件和POP3邮件服务器的通讯规则。
  3. IMAP协议:全称为 Internet Message Access Protocol,Internet消息访问协议,它是对POP3协议的一种扩展,也是定义了邮件客户端软件和IMAP邮件服务器的通讯规则。

邮件格式

要想各类邮件处理程序能识别咱们所写的电子邮件,能从咱们所书写的电子邮件中分析和提取出发件人、收件人、邮件主题和邮件内容以及附件等信息,那么咱们所写的电子邮件必需要遵循必定的格式要求,而这种邮件内容的基本格式和具体细节分别是由 RFC822 文档和 MIME 协议定义的。

  1. RFC822 文档中定义的文件格式包括两个部分:邮件头和邮件体。
  2. MIME协议(Multipurpose Internet Mail Extensions )用于定义复杂邮件体的格式,它能够表达多段平行的文本内容和非文本的邮件内容,例如,在邮件体中内嵌的图像数据和邮件附件等。另外,MIME协议的数据格式也能够避免邮件内容在传输过程当中发生信息丢失。MIME协议不是对RFC822邮件格式的升级和替代,而是基于RFC822邮件格式的扩展应用。一言以蔽之,RFC822定义了邮件内容的格式和邮件头字段的详细细节,MIME协议则是定义了如何在邮件体部分表达出的丰富多样的数据内容。

电子邮件发送和接收流程

电子邮件发送和接收流程

图示的六个步骤分别进行以下的说明:

①用户A的电子邮箱为:xx@qq.com,经过邮件客户端软件写好一封邮件,交到QQ的邮件服务器,这一步使用的协议是SMTP,对应图示的①;

②QQ邮箱会根据用户A发送的邮件进行解析,也就是根据收件地址判断是不是本身管辖的帐户,若是收件地址也是QQ邮箱,那么会直接存放到本身的存储空间。这里咱们假设收件地址不是QQ邮箱,而是163邮箱,那么QQ邮箱就会将邮件转发到163邮箱服务器,转发使用的协议也是SMTP,对应图示的②;

③163邮箱服务器接收到QQ邮箱转发过来的邮件,也会判断收件地址是不是本身,发现是本身的帐户,那么就会将QQ邮箱转发过来的邮件存放到本身的内部存储空间,对应图示的③;

④用户A将邮件发送了以后,就会通知用户B去指定的邮箱收取邮件。用户B会经过邮件客户端软件先向163邮箱服务器请求,要求收取本身的邮件,对应图示的④;

⑤163邮箱服务器收到用户B的请求后,会从本身的存储空间中取出B未收取的邮件,对应图示⑤;

⑥163邮箱服务器取出用户B未收取的邮件后,将邮件发给用户B,对应图示的⑥;最后三步用户B收取邮件的过程,使用的协议是POP3;

电子邮件的使用场景

在系统中电子邮件的使用场景:

  1. 注册验证

  2. 营销推送

  3. 触发机制

  4. 监控报警

电子邮件是业务和安全的最后一道防线 —— 当系统没法自动处理的时候,经过邮件提醒相关支持人员。

SpringBoot实现发送电子邮件

准备帐号

注册发件邮箱并设置客户端受权码,这里以163免费邮箱为例:

163邮箱协议设置-1

163邮箱协议设置-2

构建项目并配置

搭建完项目之后,进行下面的两步配置。

application.properties配置参数:

# 邮箱配置
spring.mail.host=smtp.163.com
# 你的163邮箱
spring.mail.username=ispringboot@163.com
# 注意这里不是邮箱密码,而是SMTP受权密码
spring.mail.password=isb001
spring.mail.port=25
spring.mail.protocol=smtp
spring.mail.default-encoding=UTF-8
复制代码

pom.xml依赖spring-boot-starter-mail模块:

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

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

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

<dependency>
   <groupId>org.projectlombok</groupId>
   <artifactId>lombok</artifactId>
</dependency>
复制代码

实现服务端代码

MailService.java:

package org.ijiangtao.tech.spring.boot.mail.imail.service;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
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.springframework.stereotype.Service;

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

@Service
public class MailService {

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

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

    @Autowired
    private JavaMailSender mailSender;

    /** * 简单文本邮件 * @param to 接收者邮件 * @param subject 邮件主题 * @param contnet 邮件内容 */
    public void sendSimpleMail(String to, String subject, String contnet){

        SimpleMailMessage message = new SimpleMailMessage();
        message.setTo(to);
        message.setSubject(subject);
        message.setText(contnet);
        message.setFrom(from);

        mailSender.send(message);
    }

    /** * HTML 文本邮件 * @param to 接收者邮件 * @param subject 邮件主题 * @param contnet HTML内容 * @throws MessagingException */
    public void sendHtmlMail(String to, String subject, String contnet) throws MessagingException {
        MimeMessage message = mailSender.createMimeMessage();

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

        mailSender.send(message);
    }

    /** * 附件邮件 * @param to 接收者邮件 * @param subject 邮件主题 * @param contnet HTML内容 * @param filePath 附件路径 * @throws MessagingException */
    public void sendAttachmentsMail(String to, String subject, String contnet, String filePath) throws MessagingException {
        MimeMessage message = mailSender.createMimeMessage();

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

        FileSystemResource file = new FileSystemResource(new File(filePath));
        String fileName = file.getFilename();
        helper.addAttachment(fileName, file);

        mailSender.send(message);
    }

    /** * 图片邮件 * @param to 接收者邮件 * @param subject 邮件主题 * @param contnet HTML内容 * @param rscPath 图片路径 * @param rscId 图片ID * @throws MessagingException */
    public void sendInlinkResourceMail(String to, String subject, String contnet, String rscPath, String rscId) {
        logger.info("发送静态邮件开始: {},{},{},{},{}", to, subject, contnet, rscPath, rscId);

        MimeMessage message = mailSender.createMimeMessage();
        MimeMessageHelper helper = null;

        try {

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

            FileSystemResource res = new FileSystemResource(new File(rscPath));
            helper.addInline(rscId, res);
            mailSender.send(message);
            logger.info("发送静态邮件成功!");

        } catch (MessagingException e) {
            logger.info("发送静态邮件失败: ", e);
        }

    }

}
复制代码

新建邮件模板

咱们使用thymeleaf做为模板引擎。

emailTeplate.html:

<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8"/>
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"/>
    <meta http-equiv="X-UA-Compatible" content="ie=edge"/>
    <title>注册-测试邮件模板</title>
</head>
<body>
    你好,感谢你的注册,这是一封验证邮件,请点击下面的链接完成注册,感谢您的支持。
    <a href="#" th:href="@{https://github.com/{id}(id=${id})}">激活帐户</a>
</body>
</html>
复制代码

测试发送邮件

测试发送邮件,使用单元测试MailServiceTest.java:

package org.ijiangtao.tech.spring.boot.mail.imail.service;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context;

import javax.annotation.Resource;
import javax.mail.MessagingException;

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

    @Autowired
    private MailService mailService;

    @Resource
    private TemplateEngine templateEngine;

    @Test
    public void sendSimpleMail() {
        mailService.sendSimpleMail("ispringboot@163.com","测试spring boot imail-主题","测试spring boot imail - 内容");
    }

    @Test
    public void sendHtmlMail() throws MessagingException {

        String content = "<html>\n" +
                "<body>\n" +
                "<h3>hello world</h3>\n" +
                "<h1>html</h1>\n" +
                "<body>\n" +
                "</html>\n";

        mailService.sendHtmlMail("ispringboot@163.com","这是一封HTML邮件",content);
    }

    @Test
    public void sendAttachmentsMail() throws MessagingException {
        String filePath = "/ijiangtao/软件开发前景.docx";
        String content = "<html>\n" +
                "<body>\n" +
                "<h3>hello world</h3>\n" +
                "<h1>html</h1>\n" +
                "<h1>附件传输</h1>\n" +
                "<body>\n" +
                "</html>\n";
        mailService.sendAttachmentsMail("ispringboot@163.com","这是一封HTML邮件",content, filePath);
    }

    @Test
    public void sendInlinkResourceMail() throws MessagingException {
        //TODO 改成本地图片目录
        String imgPath = "/ijiangtao/img/blob/dd9899b4cf95cbf074ddc4607007046c022564cb/blog/animal/dog/dog-at-work-with-computer-2.jpg?raw=true";
        String rscId = "admxj001";
        String content = "<html>" +
                "<body>" +
                "<h3>hello world</h3>" +
                "<h1>html</h1>" +
                "<h1>图片邮件</h1>" +
                "<img src='cid:"+rscId+"'></img>" +
                "<body>" +
                "</html>";

        mailService.sendInlinkResourceMail("ispringboot@163.com","这是一封图片邮件",content, imgPath, rscId);
    }

    @Test
    public void testTemplateMailTest() throws MessagingException {
        Context context = new Context();
        context.setVariable("id","ispringboot");

        String emailContent = templateEngine.process("emailTeplate", context);
        mailService.sendHtmlMail("ispringboot@163.com","这是一封HTML模板邮件",emailContent);

    }
}

复制代码

测试结果,收到了电子邮件:

总结

SpringBoot-Email

在生产环境,通常邮件服务会单独部署,并经过HTTP或MQ等方式暴露出来。

邮件部署架构

相关连接

相关文章
相关标签/搜索