SpringBoot实现发送电子邮件
目录
- 电子邮件与Java发送邮件的历史
- 电子邮件原理
- 电子邮件服务器
- 电子邮箱
- 邮件客户端
- 邮件传输协议
- 邮件格式
- 电子邮件发送和接收流程
- 电子使用场景
- SpringBoot实现发送电子邮件
- 准备账号
- 构建项目并配置
- 实现服务端代码
- 新建邮件模板
- 测试发送邮件
- 总结
- 相关链接
从1969年10月世界上的第一封电子邮件发出,到2019年,已经过去将近半个世纪了。虽然即时通讯和视频会议,甚至全息投影都变得日益普及,但电子邮件依然有着广泛的使用场景和不可撼动的历史地位。
SpringBoot拥有强大的生态链,几乎可以连接所有主流的开源库。
下面我们就从电子邮件发送的历史再到原理,然后如何自己配置邮件服务器并发送邮件,一步步讲解。
本文实现源码可以在这里找到: SpringBoot发送电子邮件源码
电子邮件与Java发送邮件的历史
- 1969年10月,世界上的第一封电子邮件
1969年10月世界上的第一封电子邮件是由计算机科学家Leonard K.教授发给他的同事的一条简短消息。第一条网上信息就是‘LO’,意思是‘你好!’。
- 1987年9月14日中国的第一封电子邮件
在此之后,1987年9月14日中国的第一封电子邮件,这封邮件是由德国维尔纳·措恩与中国的王运丰在北京计算机应用技术研究所,发往德国一个大学的,邮件内容颇具深意,“Across the Great Wall we can reach every corner in the world.(越过长城,走向世界)”,这是中国通过北京与德国大学之间的网络连接,向全球科学网发出的第一封电子邮件。
- 30年代发展历程
接下来中国的电子邮件进入了30年的发展期,虽然在1987年就有了电子邮件,但是,真正的邮件兴起,应该在90年代到2000年之间,因为在1987的时候中国网速特别慢,真正能接触到互联网的用户是非常少的,到了90年代中期,互联网浏览器的诞生,使得全民上网人数激增,电子邮件被广泛使用,此时,中国的部分学生在研究中使用到电子邮件,真正普及的时间是在2000年左右。
- Java发送邮件
Java在发明之初,就开始支持发送邮件,通过java mail包方式去操作邮件发送的内容和协议,但是,这种发送方式稍微比较复杂,需要配置各种参数、协议、内容,之后产生了Spring框架。
- Spring发送邮件
Spring在java mail的基础上进行了一些封装,使发送邮件的过程的复杂大大减少。
- SpringBoot发送邮件
SpringBoot Mail在Spring Mail的基础上,再次进行一次封装,使得发送邮件的便利度上,更为简单。
电子邮件原理
电子邮件服务器
用户要在Internet上提供电子邮件功能,必须有专门的电子邮件服务器。这些邮件服务器就类似于现实生活中的邮局,它主要负责接收用户投递过来的邮件,并把邮件投递到邮件接收者的电子邮箱中。
邮件服务器就好像是互联网世界的邮局。按照功能划分,邮件服务器可以划分为两种类型:
- SMTP邮件服务器:用户替用户发送邮件和接收外面发送给本地用户的邮件。
- POP3/IMAP邮件服务器:用户帮助用户读取SMTP邮件服务器接收进来的邮件。
电子邮箱
电子邮箱也称为E-mail地址,用户可以通过E-mail地址来标识自己发送的电子邮件,也可以通过这个地址接收别人发来的电子邮件。电子邮箱需要到邮件服务器进行申请,也就是说,电子邮箱其实就是用户在邮件服务器上申请的账户。邮件服务器会把接收到的邮件保存到为该账户所分配的邮箱空间中,用户通过用户名密码登录到邮件服务器查收该地址已经收到的邮件。一般来讲,邮件服务器为用户分配的邮箱空间是有限的。
邮件客户端
我们可以直接在网站上进行邮件收发,也可以使用常见的FoxMail、Outlook等邮件客户端软件接受邮件。邮件客户端软件通常集邮件撰写、发送和收发功能于一体,主要用于帮助用户将邮件发送给SMTP邮件服务器和从POP3/IMAP邮件服务器读取用户的电子邮件。
邮件传输协议
电子邮件需要在邮件客户端和邮件服务器之间,以及两个邮件服务器之间进行邮件传递,那就必须要遵守一定的规则,这个规则就是邮件传输协议。下面我们分别简单介绍几种协议:
- SMTP协议:全称为 Simple Mail Transfer Protocol,简单邮件传输协议。它定义了邮件客户端软件和SMTP邮件服务器之间,以及两台SMTP邮件服务器之间的通信规则。
- POP3协议:全称为 Post Office Protocol,邮局协议。它定义了邮件客户端软件和POP3邮件服务器的通信规则。
- IMAP协议:全称为 Internet Message Access Protocol,Internet消息访问协议,它是对POP3协议的一种扩展,也是定义了邮件客户端软件和IMAP邮件服务器的通信规则。
邮件格式
要想各种邮件处理程序能识别我们所写的电子邮件,能从我们所书写的电子邮件中分析和提取出发件人、收件人、邮件主题和邮件内容以及附件等信息,那么我们所写的电子邮件必须要遵循一定的格式要求,而这种邮件内容的基本格式和具体细节分别是由 RFC822 文档和 MIME 协议定义的。
- RFC822 文档中定义的文件格式包括两个部分:邮件头和邮件体。
- 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;
电子邮件的使用场景
在系统中电子邮件的使用场景:
注册验证
营销推送
触发机制
监控报警
电子邮件是业务和安全的最后一道防线 —— 当系统无法自动处理的时候,通过邮件提醒相关支持人员。
SpringBoot实现发送电子邮件
准备账号
注册发件邮箱并设置客户端授权码,这里以163免费邮箱为例:
构建项目并配置
搭建完项目以后,进行下面的两步配置。
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;@Autowiredprivate 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 {@Autowiredprivate MailService mailService;@Resourceprivate TemplateEngine templateEngine;@Testpublic void sendSimpleMail() {mailService.sendSimpleMail("ispringboot@163.com","测试spring boot imail-主题","测试spring boot imail - 内容");}@Testpublic 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);}@Testpublic 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);}@Testpublic 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);}@Testpublic 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);}
}
测试结果,收到了电子邮件:
总结
在生产环境,一般邮件服务会单独部署,并通过HTTP或MQ等方式暴露出来。
相关链接
- SpringBoot系列-前置知识
- Github-JavaMail
- imooc - SpringBoot发送电子邮件
- SpringBoot发送电子邮件源码
- 邮件发送的基本过程与概念
- 邮件的组织结构
SpringBoot实现发送电子邮件相关推荐
- SpringBoot整合:Druid、MyBatis、MyBatis-Plus、多数据源、knife4j、日志、Redis,Redis的Java操作工具类、封装发送电子邮件等等
SpringBoot笔记 一.SpringBoot 介绍 1.1.SpringBoot简介 SpringBoot 是一个快速开发的框架, 封装了Maven常用依赖.能够快速的整合第三方框架:简化XML ...
- javamailsender注入失败_Springboot 之 JavaMailSender发送电子邮件
本文章来自[知识林] 在很多网站系统应用中,电子邮件的发送应该非常常见,如:验证码发送.密码找回邮件发送.事件通知邮件发送等. 下面简单介绍一下在Springboot的开发中如何使用JavaMailS ...
- Spring Boot - 发送电子邮件
文章目录 环境 发送邮件 邮箱设置 项目结构 配置 编码 测试 参考 环境 操作系统: Windows 10 x64 集成开发环境: Spring Tool Suite 4 Version: 4.14 ...
- 亚马逊ses如何发qq_使用Amazon SES发送电子邮件
亚马逊ses如何发qq by Kangze Huang 黄康泽 使用Amazon SES发送电子邮件 (Sending emails with Amazon SES) 完整的AWS Web样板-教程3 ...
- php mail函数_PHP发送电子邮件函数mail详解
重要:本文最后更新于2019-10-09 08:49:07,某些文章具有时效性,若有错误或已失效,请在下方留言或联系代码狗. PHP作为一门使用广泛的脚本语言,经过这么多年发展已经非常完善了,发送电子 ...
- 如何使用PHP发送电子邮件?
本文翻译自:How to send an email using PHP? I am using PHP on a website and I want to add emailing functio ...
- 如何从我的Android应用程序发送电子邮件?
我正在为Android编写应用程序. 如何从中发送电子邮件? #1楼 简单尝试这个 public void onCreate(Bundle savedInstanceState) {super.onC ...
- 在Python中使用SMTP发送电子邮件
Python中有内置的smtplib模块,完成一封邮件的发送,需要做很多准备工作.第三方的py_smtp这个包也是基于smtplib的,在Python中使用py_smtp发送电子邮件非常方便,只要填写 ...
- C# 发送电子邮件(含附件)用到的类 system.web.mail
主要是用到了System.Web.Mail命名空间,用到了此空间的三个类,分别是: ●MailMessage类,用于构造电子邮件 ●MailAttachment类,用于构造电子邮件附件 ●SmtpMa ...
- net类库中发送电子邮件的方法总结
发送电子邮件是许多需要用户注册的网站的通用功能,通过正则表达式我们可以过滤掉不符合电子邮件格式的输入,但是仍没有办法确保用户填写的电子邮件地址一定是他本人真实有效的电子邮件地址,通常验证电子邮件真实有 ...
最新文章
- Java开发者 IntelliJ IDEA 转换 VScode 时的优缺点
- ActiveMovie属性说明,使用资料。
- Linux中关于 su 和 su - 的区别
- Java 类在 Tomcat 中是如何加载的?
- 利用redis List队列简单实现秒杀 PHP代码实现
- Android之layout属性介绍
- 使用fiddler获取手机上的数据
- default value of template parameter c++
- C语言数据结构之图的邻接矩阵的应用实例
- QT - 实例 - Qt实现局域网聊天工具软件
- php 银行卡二要素验证
- 【挨踢人物传】向立天:从电视编导到技术总监,只要努力,你也能铸就传奇(第七期)...
- [翻译]Templates in WPF
- 在proteus中的排阻的查找_排阻在proteus中怎么找
- 戴尔计算机主机型号,戴尔电脑在哪看型号_戴尔电脑型号怎么看
- 服务器制作raid,实战案例——服务器制作raid磁盘阵列并管理
- 婚宴座位图html5,婚宴酒席座位安排图 20桌婚宴座位安排图
- 编程方法论/架构设计/模式相关转载链接汇总
- YUV采样与格式总结
- 开始利用CSDN做学习笔记,从windows 游戏编程大师技巧和3D游戏编程大师开始