因为自己毕业设计需要用到邮件发送和接收功能,所以打算记录一下如何使用springBoot来发送邮件。此文章思路来自于慕课网关于springboot发送邮件,相当于笔记。首先我们来了解一下关于邮件的一些协议。
简单邮件传输协议 (Simple Mail Transfer Protocol, SMTP)是在Internet传输email的事实标准。
SMTP是一个相对简单的基于文本的协议。在其之上指定了一条消息的一个或多个接收者(在大多数情况下被确认是存在的),然后消息文本会被传输。可以很简单地通过telnet程序来测试一个SMTP服务器。SMTP使用TCP端口25。要为一个给定的域名决定一个SMTP服务器,需要使用MX (Mail eXchange)DNS。
在八十年代早期SMTP开始被广泛地使用。当时,它只是作为UUCP的补充,UUCP更适合于处理在间歇连接的机器间传送邮件。相反,SMTP在发送和接收的机器在持续连线的网络情况下工作得最好。
Sendmail是最早使用SMTP的邮件传输代理之一。到2001年至少有50个程序将SMTP实现为一个客户端(消息的发送者)或一个服务器(消息的接收者)。一些其他的流行的SMTP服务器程序包括了Philip Hazel的exim,IBM的Postfix,D. J. Bernstein的Qmail,以及Microsoft Exchange Server。
由于这个协议开始是基于纯ASCII文本的,它在二进制文件上处理得并不好。诸如MIME的标准被开发来编码二进制文件以使其通过SMTP来传输。今天,大多数SMTP服务器都支持8位MIME扩展,它使二进制文件的传输变得几乎和纯文本一样简单。
SMTP是一个“推”的协议,它不允许根据需要从远程服务器上“拉”来消息。要做到这点,邮件客户端必须使用POP3或IMAP。另一个SMTP服务器可以使用ETRN在SMTP上触发一个发送。
POP3,全名为“Post Office Protocol - Version 3”,即“邮局协议版本3”。是TCP/IP协议族中的一员,由RFC1939 定义。本协议主要用于支持使用客户端远程管理在服务器上的电子邮件。提供了SSL加密的POP3协议被称为POP3S。
POP 协议支持“离线”邮件处理。其具体过程是:邮件发送到服务器上,电子邮件客户端调用邮件客户机程序以连接服务器,并下载所有未阅读的电子邮件。这种离线访问模式是一种存储转发服务,将邮件从邮件服务器端送到个人终端机器上,一般是PC机或 MAC。一旦邮件发送到 PC 机或MAC上,邮件服务器上的邮件将会被删除。但目前的POP3邮件服务器大都可以“只下载邮件,服务器端并不删除”,也就是改进的POP3协议。
IMAP(Internet Mail Access Protocol,Internet邮件访问协议)以前称作交互邮件访问协议(Interactive Mail Access Protocol)。IMAP是斯坦福大学在1986年开发的一种邮件获取协议。它的主要作用是邮件客户端(例如MS Outlook Express)可以通过这种协议从邮件服务器上获取邮件的信息,下载邮件等。当前的权威定义是RFC3501。IMAP协议运行在TCP/IP协议之上,使用的端口是143。它与POP3协议的主要区别是用户可以不用把所有的邮件全部下载,可以通过客户端直接对服务器上的邮件进行操作。
MIME(Multipurpose Internet Mail Extensions)多用途互联网邮件扩展类型。是设定某种扩展名的文件用一种应用程序来打开的方式类型,当该扩展名文件被访问的时候,浏览器会自动使用指定应用程序来打开。多用于指定一些客户端自定义的文件名,以及一些媒体文件打开方式。
它是一个互联网标准,扩展了电子邮件标准,使其能够支持:
非ASCII字符文本;非文本格式附件(二进制、声音、图像等);由多部分(multiple parts)组成的消息体;包含非ASCII字符的头信息(Header information)。
这个标准被定义在RFC 2045、RFC 2046、RFC 2047、RFC 2048、RFC 2049等RFC中。 MIME改善了由RFC 822转变而来的RFC 2822,这些旧标准规定电子邮件标准并不允许在邮件消息中使用7位ASCII字符集以外的字符。正因如此,一些非英语字符消息和二进制文件,图像,声音等非文字消息原本都不能在电子邮件中传输(MIME可以)。MIME规定了用于表示各种各样的数据类型的符号化方法。 此外,在万维网中使用的HTTP协议中也使用了MIME的框架,标准被扩展为互联网媒体类型。
使用springBoot去发送邮件的大概步骤为:1.引入相关的jar包。2.配置邮箱参数。3.封装SimpleMailMessage。4.JavaMailSender进行发送。
添加相应的依赖包
<!--发送邮件所需要依赖的包-->
<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>
邮箱参数配置
##添加邮件相关的参数
##配置我们使用的邮箱协议以及使用的邮箱,这里是126邮箱
spring.mail.host=smtp.qq.com
##邮箱用户名
spring.mail.username=xxxxx@qq.com
# 设置密码,该处的密码是QQ邮箱开启SMTP的授权码而非QQ密码
spring.mail.password=vqcnnfyvkjnshebg
##我们使用的字符编码
spring.mail.default-encoding=UTF-8
# 设置是否需要认证,如果为true,那么用户名和密码就必须的,
# 如果设置false,可以不设置用户名和密码,当然也得看你的对接的平台是否支持无密码进行访问的。
spring.mail.properties.mail.smtp.auth=true
# STARTTLS[1] 是对纯文本通信协议的扩展。它提供一种方式将纯文本连接升级为加密连接(TLS或SSL),而不是另外使用一个端口作加密通信。
spring.mail.properties.mail.smtp.starttls.enable=true
spring.mail.properties.mail.smtp.starttls.required=true
第一个是普通的文本邮件发送,以下是各类
package com.test.email.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 log=LoggerFactory.getLogger(this.getClass());
@Value("${spring.mail.username}")//将配置中的属性注入到这个类中
private String from;//发送人
@Autowired
private JavaMailSender mailSender;
/**
* 发送文本邮件
* @param to 发给谁
* @param subject 发送主题
* @param content 发送内容
*/
public void sendSimpleMail(String to,String subject,String content){
SimpleMailMessage message=new SimpleMailMessage();//这个是一个发送文本邮件的对象
message.setTo(to);//发给谁
message.setSubject(subject);//发送主题
message.setText(content);//发送内容
System.out.println(from);
message.setFrom(from);//谁发的
mailSender.send(message);//通过mailSender对象将邮件发给目标人
}
/**
* 发送HTML邮件
* @param to 发给谁
* @param subject 发送主题
* @param content 发送内容
*/
public void sendHtmlMail(String to,String subject,String content) {
//创建可以发送h't'm'l类型邮件的类
MimeMessage message=mailSender.createMimeMessage();
MimeMessageHelper helper= null;
try {
helper = new MimeMessageHelper(message,true);
helper.setTo(to);
helper.setSubject(subject);
helper.setText(content,true);
helper.setFrom(from);
} catch (MessagingException e) {
e.printStackTrace();
}
mailSender.send(message);
}
/**
* 发送附件邮件
* @param to 发给谁
* @param subject 发送主题
* @param content 发送内容
* @param filePath 附件的地址
*/
public void sendAtachmentsMail(String to,String subject,String content,String filePath) {
MimeMessage mimeMessage=mailSender.createMimeMessage();
MimeMessageHelper helper= null;
try {
helper = new MimeMessageHelper(mimeMessage,true);
helper.setTo(to);
helper.setSubject(subject);
helper.setFrom(from);
helper.setText(content,true);
//构建文件流对象
FileSystemResource file=new FileSystemResource(new File(filePath));
//获取文件名
String fileName=file.getFilename();
helper.addAttachment(fileName,file);
//如果发送多份则再添加即可
//helper.addAttachment(fileName,file);
} catch (MessagingException e) {
e.printStackTrace();
}
mailSender.send(mimeMessage);
}
/**
* 发送带图片的邮件
* @param to 发给谁
* @param subject 发送主题
* @param content 发送内容
* @param rscPath 资源路径
* @param rscId 资源id--自定义即可
*/
public void sendInLineResourceMail(String to,String subject,String content,
String rscPath,String rscId) {
MimeMessage message=mailSender.createMimeMessage();
log.info("发送今天邮件开始:{},{},{},{}",to,subject,content,rscPath,rscId);
MimeMessageHelper helper= null;
try {
helper = new MimeMessageHelper(message,true);
helper.setTo(to);
helper.setText(content,true);
helper.setFrom(from);
helper.setSubject(subject);
FileSystemResource res=new FileSystemResource(new File(rscPath));
helper.addInline(rscId,res);
//需要多张图片时,应该多一个addInline方法
//helper.addInline(rscId,res);
log.info("发送静态图片邮件成功");
} catch (MessagingException e) {
log.error("发送静态图片邮件失败",e);
}
mailSender.send(message);
}
}
package com.test.email.service;
import org.junit.Test;
import org.junit.runner.RunWith;
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;
import javax.mail.internet.MimeMessage;
/**
* 邮件测试类
*/
@RunWith(SpringRunner.class)
@SpringBootTest
public class HelloService {
private String to="to@126.com";
@Resource
MailService mailService;
@Resource
TemplateEngine templateEngine;
//测试发送文本文件
@Test
public void sendSimpleTest(){
mailService.sendSimpleMail(to,"这是第一封邮件","你好");
}
//测试发送html类型的邮件
@Test
public void sendHtmlMailTest(){
String content="<html>\n"+
"<body>\n"+
"<h3>helloworld,这是一个html邮件</h3>\n"+
"</body>\n"+
"</html>";
mailService.sendHtmlMail(to,"这是第一封html邮件",content);
}
/**
* 测试发送附件邮件
*/
@Test
public void sendAtachmentsMail(){
//找一个文件
String filePath="E:\\知名互联网公司校招中常见的算法题.docx";
mailService.sendAtachmentsMail(to,"这是一个带附件的邮件","" +
"这是一篇带附件的邮件内容",filePath);
}
@Test
public void sendInLineResourceMailTest() throws MessagingException {
String imgPath="E:\\banner_1.jpg";
String rscId="neo001";
String content="<html><body>这是有图片的邮件;<img src=\'cid:"+rscId+"\'></img></body></html>";
//需要加多张图片时应该再加impPath和rscId
/**另外加如下的代码
* String imgPath="E:\\banner_1.jpg";
String rscId="neo001";
String content="<html><body>这是有图片的邮件;<img src=\'cid:"+rscId+"\'></img></body></html>";
*/
mailService.sendInLineResourceMail(to,"这是一个图片邮件",content,imgPath,rscId);
}
/**
* 测试我们使用的模板引擎,实际上后面使用的html邮件
*/
@Test
public void testTemplateMailTest() throws MessagingException {
Context context=new Context();
//传入参数
context.setVariable("id",006);
//写入模板引擎的名字,emailContent是一个带html格式的文本
String emailContent=templateEngine.process("emailTemplate.html",context);
mailService.sendHtmlMail(to,"这是一个模板邮件",emailContent);
}
}
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>邮件模板(发送模板邮件的时候需要用到)</title>
</head>
<body>
您好,感谢您的注册,这是一封验证邮件,请点击下面的链接完成注册,感谢您的支持!
<!--模板后面的id是变化的,所以我们通过传不同的id来发送不同的邮件-->
<a href="#" th:href="@{https://blog.youkuaiyun.com/lxh123456789asd?{id}(id=${id})}">激活账户</a>
</body>
</html>
结果:
常见异常:
421 HL:ICC 该ip同时并发连接数过大,如果是公司申请的企业邮箱,那应该企业去和运营商沟通一下,设置一个并发数。
451 Requested mail action not taken:too much fail.... 登陆失败次数过多,被临时禁止登陆,
553 authentication is required 认证失败,通常是我们的密码或者配置不对