SpringBoot 整合邮件服务

开发中,经常需要及时通知用户消息,常见的方式有两种:邮件、短信

这里我们使用邮件服务,因为可以免费使用

SMTP简介

SMTP是一种提供可靠且有效的电子邮件传输的协议。SMTP是建立在FTP文件传输服务上的一种邮件服务,主要用于系统之间的邮件信息传递,并提供有关来信的通知。SMTP独立于特定的传输子系统,且只需要可靠有序的数据流信道支持,SMTP的重要特性之一是其能跨越网络传输邮件,即“SMTP邮件中继”。使用SMTP,可实现相同网络处理进程之间的邮件传输,也可通过中继器或网关实现某处理进程与其他网络之间的邮件传输。

简单来说:我们使用的这些邮件发送功能,他们之间都有一个专门的电子邮件的服务器,类似于邮局,你将邮件发给邮局,邮局又会根据你的邮寄地址发送给相应的邮局,然后接收方去邮局取邮件。而邮件服务器呢,就是互联网之间的一个邮局,不同的网络之间也能实现电子邮件的发送。

SpringBoot使用

引入依赖

pom.xml 中添加

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

yml设置邮件服务

application.yml 配置

mail:
    # 配置 SMTP 服务器地址
    host: smtp.qq.com
    # 发送者邮箱
    username: *******@qq.com
    # 配置密码,注意不是真正的密码,而是刚刚申请到的授权码
    password: *******
    # 端口号465或587
    port: 587
    # 默认的邮件编码为UTF-8
    default-encoding: UTF-8
    # 配置SSL 加密工厂
    properties:
      mail:
        smtp:
          socketFactoryClass: javax.net.ssl.SSLSocketFactory
        #表示开启 DEBUG 模式,这样,邮件发送过程的日志会在控制台打印出来,方便排查错误

代码中使用

邮箱工具类

这里我使用mongodb的gridFS服务提供附件,不需要附件可以删除相关代码或替换自己的文件方法

import com.mongodb.client.gridfs.GridFSBucket;
import com.mongodb.client.gridfs.GridFSDownloadStream;
import com.mongodb.client.gridfs.model.GridFSFile;
import com.zykj.business.entity.mongo.FileModel;
import com.zykj.business.entity.pojo.MailPojo;
import com.zykj.business.repository.FileRepository;
import lombok.SneakyThrows;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.gridfs.GridFsResource;
import org.springframework.data.mongodb.gridfs.GridFsTemplate;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.mail.internet.MimeMessage;
import java.io.InputStream;
import java.util.Date;
import java.util.Optional;

/**
 * @author sungang
 * 邮箱工具类
 */
@Service
public class MailService {

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

    @Resource
    JavaMailSender javaMailSender;


    @Resource
    private FileRepository fileRepository;

    @Resource
    private GridFsTemplate gridFsTemplate;

    @Resource
    private GridFSBucket fsBucket;

    /**
     * 普通邮件发送,立即发送
     */
    public void sendSimpleMail(MailPojo mailPojo) {
        // 构建一个邮件对象
        SimpleMailMessage message = new SimpleMailMessage();
        // 设置邮件主题
        message.setSubject(mailPojo.getTitle());
        // 设置邮件发送者,这个跟application.yml中设置的要一致
        message.setFrom(fromUser);
        // 设置邮件接收者,可以有多个接收者,中间用逗号隔开,以下类似
        message.setTo(mailPojo.getSentTo());
        // 设置邮件抄送人,可以有多个抄送人
        message.setCc(mailPojo.getCc());
        // 设置邮件发送日期
        message.setSentDate(new Date());
        // 设置邮件的正文
        message.setText(mailPojo.getText());
        // 发送邮件
        javaMailSender.send(message);
    }


    @SneakyThrows
    public void sendMineMail(MailPojo mailPojo) {
        //1、创建一个复杂的邮件
        MimeMessage mimeMessage = javaMailSender.createMimeMessage();
        // 设置邮件发送日期
        mimeMessage.setSentDate(new Date());
        MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true);
        //邮件主题
        helper.setSubject(mailPojo.getTitle());
        //邮件内容
        helper.setText(mailPojo.getText(),true);
        helper.setTo(mailPojo.getSentTo());
        helper.setFrom(fromUser);
        String[] fileIds = mailPojo.getFileIds();
        if(fileIds!=null){
            for (String fileId : fileIds
            ) {
                Optional<FileModel> fileInfoByName = fileRepository.findById(fileId);
                if (!fileInfoByName.isPresent()) {
                    return;
                }
                FileModel fileModel = fileInfoByName.get();
                String objectId = fileModel.getFsId();
                Query query = Query.query(Criteria.where("_id").is(objectId));
                GridFSFile file = gridFsTemplate.findOne(query);
                if (file != null) {
                    String contentType = fileModel.getContentType();
                    GridFSDownloadStream in = fsBucket.openDownloadStream(file.getObjectId());
                    GridFsResource resource = new GridFsResource(file, in);
                    InputStream inputStream = resource.getInputStream();
                    //添加附件
                    helper.addAttachment(fileModel.getName(), new ByteArrayResource(IOUtils.toByteArray(inputStream)), contentType);
                }
            }
        }
        javaMailSender.send(mimeMessage);
    }

}

邮箱实体类

import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

/**
 * @author sungang
 * @date 2021/11/3 11:06 上午
 */
@Data
public class MailPojo {

    //邮件接收者,可以有多个接收者,中间用逗号隔开
    private String[] sentTo;

   //邮件抄送者,可以有多个接收者,中间用逗号隔开
    private String[] cc;

   //邮件主题
    private String title;

    //邮件内容
    private String text;

    //文件
    private String[] fileIds;
}

在需要发送消息的地方调用方法即可

@Resource
    public MailService mailService;

    MailPojo mailPojo = new MailPojo();
    mailPojo.setTitle("title");
    String[] mails = {"132****@qq.com","133****@qq.com"};
    mailPojo.setSentTo(mails);
    mailPojo.setText("text");
    mailService.sendSimpleMail(mailPojo);