一.电子邮件协议:
SMTP 简单邮件传输
SMTP是Simple Mail Transfer Protocol的简称,即简单邮件传输协议。该协议定义了邮件客户端软件和SMTP服务器之间,以及两台SMTP服务器之间的通信规则。在Java Mail API中,基于Java Mail的程序将与本公司或Internet服务提供商(ISP)的SMTP服务器通信,该SMTP服务器将会把消息转发给用于接收消息的SMTP服务器,最后用户可通过POP或IMAP协议获取该消息。由于支持身份验证,所以不需要SMTP服务器是一种开放的转发器,但需要确保SMTP服务器配置正确。Java Mail API中没有集成用于处理配置服务器以转发消息或添加/删除电子邮件账户等功能。
POP3邮局协议
POP3是Post Office Protocol 3的简称,即邮局协议第3版,该协议是在RFC 1939中定义的。它是Internet电子邮件的第一个离线协议标准,也就是说,POP3是一个简单而实用的邮件信息传输协议。目前在Internet上,大多数人都采用POP3来接收邮件。POP3为每个用户的每个邮箱提供支持,但是POP3并不支持查看邮件信息及统计新邮件的功能,因此,在使用Java Mail API时,如果想获取这些信息,需要自己进行计算。
IMAP 接收邮件协议
IMA P的含义是Internet消息访问协议,当前版本是第4版,也称作IMAP4,该协议是在RFC 2060中定义的。IMAP是接收消息的更加高级协议。使用IMAP时,所用邮件服务器必须支持该协议,但是如果所有邮件服务器只支持该协议,并不能使用全部IMAP协议,为了能够支持全部IMAP协议,所用邮件服务器还应该支持POP协议。在Java Mail程序通过IMAP协议可以在服务器上拥有包括多个文件夹的用户,并且这些文件夹可以被多个用户共享。虽然IMAP协议具有更高级的功能,但是也不要让每个用户都使用,这是因为IMAP需要服务器接收新消息,发送消息给请求的用户,并在多个文件夹中为每个用户维护消息、备份信息,这会加重邮件服务器的负荷。
MIME
MIME是多用途的网际邮件扩充协议的简称。它不是一种邮件传输协议,而是用于定义传输内容(如消息的格式、附件等)的协议。许多文档都对MIME协议作了描述(包括RFC 2045、RFC 2046和RFC 2047)。MIME是对RFC 822的扩充,RFC 822规定了内容只包括采用ASCII编码的纯文本的邮件格式,而MIME允许在邮件中包含附件。作为Java Mail API的用户,一般不需要担心这些格式。
二.采用POP3/SMTP服务发送邮件
1.配置依赖
<!--邮箱--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-mail</artifactId> </dependency>
2.在application.yml进行配置
spring: mail: # 使用的编码 default-encoding: utf-8 # 邮件协议smtp host: smtp.qq.com # 端口(默认25) port: 25 # 发送者的邮件的用户名 username: 2891434522@qq.com # 移动端客户授权码(在邮箱中设置) password: xxxxxxxxxxxxx
3.发送邮件,同时兼容简单邮件和带附件的邮件(附件可以是文件和图片,可以多个)
Controller控制层:
import com.example.service.IEmailService; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.multipart.MultipartFile; import javax.annotation.Resource; import java.util.Objects; @Controller public class EmailController { @Resource private IEmailService emailService; /** * 发送邮件接口 * @param file 附件数组 * @param to 邮件接收方 * @param subject 邮件主题 * @param contentText 邮件内容 * @return */ @RequestMapping("sendEmail") @ResponseBody public boolean sendEmail(@RequestParam("file") MultipartFile[] file, String to, String subject, String contentText) { if (Objects.nonNull(file) && file.length > 0) { return emailService.sendAttachmentMail(to, subject, contentText, file); } return emailService.sendHtmlMail(to, subject, contentText); } }
4.新建IEmailService接口,包含简单邮件,和带附件接口
import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; @Service public interface IEmailService { /** * * @Description 发送简单纯文字邮件 * @param to 收件人地址 * @param subject 邮件主题 * @param content 邮件内容<br> * @return boolean 成功返回true,失败返回false */ void sendSimpleMail(String to, String subject, String content); /** * * @Description 发送简单纯文字邮件 * @param to 收件人地址 * @param subject 邮件主题 * @param content 邮件内容<br> * @return boolean 成功返回true,失败返回false */ boolean sendHtmlMail(String to, String subject, String content); /** * * @Description 发送带单个或多个附件的邮件 * @param to 收件人地址 * @param subject 邮件主题 * @param content 邮件内容 * @param file 附件数组 * @return boolean 功返回true,失败返回false */ boolean sendAttachmentMail(String to, String subject, String content, MultipartFile[] file); }
5.新建EmailService实现类,实现IEmailService接口。
import com.example.service.IEmailService; import org.springframework.beans.factory.annotation.Value; import org.springframework.mail.SimpleMailMessage; import org.springframework.mail.javamail.JavaMailSender; import org.springframework.mail.javamail.MimeMessageHelper; import org.springframework.stereotype.Controller; import org.springframework.web.multipart.MultipartFile; import javax.annotation.Resource; import javax.mail.internet.MimeMessage; import javax.mail.internet.MimeUtility; import java.util.Objects; @Controller public class EmailServiceImpl implements IEmailService { // 从application.properties配置文件中注入发送者的邮件地址 @Value("${spring.mail.username}") private String fromEmail; @Value("${spring.mail.default-encoding}") private String encoding; //注入spring发送邮件的对象 @Resource private JavaMailSender javaMailSender; @Override public void sendSimpleMail(String to, String subject, String content) { SimpleMailMessage message = new SimpleMailMessage(); message.setFrom(fromEmail); message.setTo(to); message.setSubject(subject); message.setText(content); try{ javaMailSender.send(message); System.out.println("success"); }catch (Exception e){ System.out.println("fail"+e); } } @Override public boolean sendHtmlMail(String to, String subject, String content) { MimeMessage mimeMessage = javaMailSender.createMimeMessage(); try { // 指定 UTF-8 编码 final MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true, encoding); helper.setTo(to); helper.setSubject(subject); // 是否是html标签内容 helper.setText(content,true); helper.setFrom(fromEmail); //发送邮件 javaMailSender.send(mimeMessage); } catch (Exception e) { return false; } return true; } @Override public boolean sendAttachmentMail(String to, String subject, String content, MultipartFile[] file) { MimeMessage mimeMessage = javaMailSender.createMimeMessage(); try { // 设置参数 不允许截断文件名 System.setProperty("mail.mime.splitlongparameters", "false"); // 指定 UTF-8 编码 final MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true, encoding); helper.setTo(to); helper.setSubject(subject); // 是否是html标签内容 helper.setText(content, true); helper.setFrom(fromEmail); if (Objects.nonNull(file) && file.length > 0) { //读取附件文件(传入文件路径) for (MultipartFile tempFile : file) { String fileName = tempFile.getOriginalFilename(); // 编码文件名称 helper.addAttachment(MimeUtility.encodeWord(fileName),tempFile);
6.测试
三.附件名乱码
邮件里的附件名称中文却显示成了=UTF-8Q=E3=80=90...=UTF-8Q(2).docx=
因为编码后文件名太长被截断成多个属性名,而邮件接收端没有很好地支持这种方式,才导致乱码的。
解决方案
将系统参数mail.mime.splitlongparameters
改成false
即可解决这个问题,完整的代码如下
// 设置参数 不允许截断文件名 System.setProperty("mail.mime.splitlongparameters", "false"); final MimeMessage message = mailSender.createMimeMessage(); // 指定 UTF-8 编码 final MimeMessageHelper messageHelper = new MimeMessageHelper(message, true, "UTF-8"); messageHelper.setFrom(properties.getUsername(), SEND_ALIAS); messageHelper.setSubject(title); messageHelper.setText(subject, true); // 编码文件名称 messageHelper.addAttachment(MimeUtility.encodeWord(file.getName()), fileSystemResource);
这样就可以解决附件中文名称乱码问题。