以前发送邮件可能大家需要使用javax下的mail包,自己创建session,mimemessage这种;其实spring帮我们集成了一下,让发邮件变的更简单、可靠。
- <dependency>
- <groupId>org.springframework.bootgroupId>
- <artifactId>spring-boot-starter-mailartifactId>
- dependency>
首先spring 的依赖常规使用方式就是配置加注入,邮件模块也不例外。先来看看配置
- spring:
- mail:
- host: 10.110.xxx.xxx #邮件服务器地址
- port: 25 #邮件服务器端口
- protocol: smtp #使用的协议
- default-encoding: UTF-8 #默认编码
- username: user #这个是通过邮件服务器认证的用户名和密码,不一定是邮箱,看服务器的要求
- password: password
- properties: #properties中的属性都是比较灵活可配置的,其实是javax.mail.Session中对应的配置项,可以参考对应文档
- mail.smtp.auth: true #如果邮件服务器需要实名需要认证开启此选项
- mail.from: 100010@qq.com #统一设置发件人邮箱
然后放具体代码,后面一点一点分析
邮件实体类
- import lombok.*;
- import org.springframework.core.io.InputStreamSource;
-
- import javax.activation.DataSource;
- import javax.mail.internet.InternetAddress;
- import java.io.File;
- import java.util.Date;
- import java.util.HashMap;
- import java.util.List;
- import java.util.Map;
-
- /**
- * @author
- * @Description
- * @create 2022-07-12 14:23
- */
- @Data
- @NoArgsConstructor
- @AllArgsConstructor
- public class MailInfo {
- /**
- * 邮件标题
- */
- private String subject;
- /**
- * 邮件正文
- */
- private String content;
- /**
- * 发件时间,默认当前时间
- */
- private Date sentDate;
- /**
- * 收件人
- */
- private List
recipients; - /**
- * 抄送人
- */
- private List
ccs; - /**
- * 密件抄送人
- */
- private List
bccs; - /**
- * 是否为邮件组
- */
- private Boolean isGroup;
- /**
- * 文件形式附件
- */
- @Setter(AccessLevel.NONE)
- private Map
byte[]> attachments = new HashMap<>(); -
- public void addAttachment(String fileName, byte[] file){ attachments.put(fileName, file); }
-
- }
service层实现
- import lombok.extern.slf4j.Slf4j;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.core.io.ByteArrayResource;
- import org.springframework.core.io.InputStreamSource;
- import org.springframework.mail.javamail.JavaMailSender;
- import org.springframework.mail.javamail.MimeMessageHelper;
- import org.springframework.stereotype.Service;
- import org.springframework.transaction.annotation.Transactional;
- import org.springframework.util.StringUtils;
- import org.springframework.web.bind.annotation.PostMapping;
- import org.springframework.web.bind.annotation.RequestMapping;
- import com.cicc.op.mail.api.MailService;
-
- import javax.activation.DataSource;
- import javax.mail.MessagingException;
- import javax.mail.internet.AddressException;
- import javax.mail.internet.InternetAddress;
- import javax.mail.internet.MimeMessage;
- import javax.mail.util.ByteArrayDataSource;
- import java.io.ByteArrayInputStream;
- import java.io.File;
- import java.nio.charset.StandardCharsets;
- import java.time.LocalDate;
- import java.time.LocalDateTime;
- import java.util.ArrayList;
- import java.util.List;
-
- /**
- * @author
- * @Description
- * @create 2022-07-26 15:39
- */
- @Slf4j
- @Service
- public class MailController {
- @Autowired
- private JavaMailSender javaMailSender;
-
- @Override
- public MailResponse sendMail(MailInfo mailInfo) {
- Long id = recordLog(mailInfo);
- log.info("----------开始邮件发送------------");
- checkValue(mailInfo, id);
- //html加附件邮件发送
- try {
- MimeMessage message = javaMailSender.createMimeMessage();
- MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(message, true);
- if(mailInfo.getIsGroup() != null && mailInfo.getIsGroup()){
- List
internetAddressList = new ArrayList<>(); - mailInfo.getRecipients().forEach(to ->{
- try {
- internetAddressList.add(new InternetAddress(to, true));
- } catch (AddressException e) {
- log.error("邮件发送失败,地址信息有误", e);
- throw new CommonMailException("邮件发送失败,地址信息有误", id, e);
- }
- });
- mimeMessageHelper.setTo(internetAddressList.toArray(new InternetAddress[internetAddressList.size()]));
- }else {
- mimeMessageHelper.setTo(mailInfo.getRecipients().toArray(new String[mailInfo.getRecipients().size()]));
- }
- mimeMessageHelper.setSubject(mailInfo.getSubject());
- mimeMessageHelper.setText(mailInfo.getContent(), true);
- if (mailInfo.getAttachments() != null && !mailInfo.getAttachments().isEmpty()) {
- for (String fileName : mailInfo.getAttachments().keySet()) {
- byte[] file = mailInfo.getAttachments().get(fileName);
- if(file != null){
- mimeMessageHelper.addAttachment(fileName, new ByteArrayResource(file));
- } else {
- throw new CommonMailException("不支持的附件类型", id);
- }
- }
- }
- if (mailInfo.getSentDate() != null) {
- mimeMessageHelper.setSentDate(mailInfo.getSentDate());
- }
- if (mailInfo.getCcs() != null && !mailInfo.getCcs().isEmpty()) {
- for (String cc : mailInfo.getCcs()) {
- mimeMessageHelper.setCc(cc);
- }
- }
- if (mailInfo.getBccs() != null && !mailInfo.getBccs().isEmpty()) {
- for (String bcc : mailInfo.getBccs()) {
- mimeMessageHelper.setBcc(bcc);
- }
- }
-
- javaMailSender.send(message);
- } catch (MessagingException e) {
- log.error("邮件发送失败", e);
- throw new CommonMailException("邮件发送失败", id, e);
- }
- return new MailResponse(true, "发送成功");
- }
-
- private void checkValue(MailInfo mailInfo, Long id) {
- if (!StringUtils.hasText(mailInfo.getSubject())) {
- throw new CommonMailException("邮件标题不能为空", id);
- } else if (!StringUtils.hasText(mailInfo.getContent())) {
- throw new CommonMailException("邮件内容不能为空", id);
- } else if (mailInfo.getRecipients().isEmpty()) {
- throw new CommonMailException("收件人不能为空", id);
- }
- }
- }
首先是JavaMailSender,只要配置好spring.mail相关,就可以直接注入此Bean。
- package org.springframework.mail.javamail;
-
- import java.io.InputStream;
- import javax.mail.internet.MimeMessage;
- import org.springframework.mail.MailException;
- import org.springframework.mail.MailSender;
-
- public interface JavaMailSender extends MailSender {
- MimeMessage createMimeMessage();
-
- MimeMessage createMimeMessage(InputStream contentStream) throws MailException;
-
- void send(MimeMessage mimeMessage) throws MailException;
-
- void send(MimeMessage... mimeMessages) throws MailException;
-
- void send(MimeMessagePreparator mimeMessagePreparator) throws MailException;
-
- void send(MimeMessagePreparator... mimeMessagePreparators) throws MailException;
- }
根据接口来看,一共两个环节,创建MimeMessage对象(里面是邮件相关属性),然后send发送。
具体的实现类JavaMailSenderImpl截取
- public synchronized Session getSession() {
- if (this.session == null) {
- this.session = Session.getInstance(this.javaMailProperties);
- }
-
- return this.session;
- }
-
-
- public MimeMessage createMimeMessage() {
- return new SmartMimeMessage(this.getSession(), this.getDefaultEncoding(), this.getDefaultFileTypeMap());
- }
-
- public MimeMessage createMimeMessage(InputStream contentStream) throws MailException {
- try {
- return new MimeMessage(this.getSession(), contentStream);
- } catch (Exception var3) {
- throw new MailParseException("Could not parse raw MIME content", var3);
- }
- }
getSession方法可以看出,spring是对javax实现的邮件发送进行了一层封装,还是用的session,之前的properties配置也是在这里给到session,然后通过session创建MimeMessage。直接操作MimeMessage写入也可以,但是一个是不太方便,一个是不能发送附件,所以借助MimeMessageHelper来实现。
- public MimeMessageHelper(MimeMessage mimeMessage, boolean multipart) throws MessagingException {
- this(mimeMessage, multipart, (String)null);
- }
-
- public MimeMessageHelper(MimeMessage mimeMessage, boolean multipart, @Nullable String encoding) throws MessagingException {
- this(mimeMessage, multipart ? 3 : 0, encoding);
- }
-
- public MimeMessageHelper(MimeMessage mimeMessage, int multipartMode) throws MessagingException {
- this(mimeMessage, multipartMode, (String)null);
- }
-
- public MimeMessageHelper(MimeMessage mimeMessage, int multipartMode, @Nullable String encoding) throws MessagingException {
- this.encodeFilenames = false;
- this.validateAddresses = false;
- this.mimeMessage = mimeMessage;
- this.createMimeMultiparts(mimeMessage, multipartMode);
- this.encoding = encoding != null ? encoding : this.getDefaultEncoding(mimeMessage);
- this.fileTypeMap = this.getDefaultFileTypeMap(mimeMessage);
- }
使用MimeMessageHelper的时候注意三个点,
一个是multipart字段,如果要进行附件传输的话,这个要设置为true,还有就是如果配置文件中没有设置默认字符集,然后发送邮件出现乱码情况,可以在encoding设置编码。
还有一个是setText方法,如果需要发送的邮件正文不是简单的文本格式,而是使用了模板或者有图片表格等内容,需要在setText方法设置strict属性为true。
邮件的附件如果需要http请求进行传输,但是又不方便使用Multipartfile类型,可以使用byte数组发送,如果是JSON需要注意序列化时编码问题;直接使用form-data也可以。