每一年都奔走在自己热爱里

没有人是一座孤岛,总有谁爱着你

SpringBoot整合邮箱发送邮件

1. SpringBoot整合邮箱发送邮件

在开发中,经常会碰到email邮件发送的场景,如发送验证码,向客户发送邮件等等。

今天,本项目将讲解通过 SpringBoot 发送 email 邮件(普通文本邮件 ,HTML内容板式邮件 ,包含静态资源邮件,以及带附件邮件)。

2. 项目配置

2.1 创建SpringBoot项目

项目结构,简单测试没有分包

2.2 pom文件导入需要的依赖

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

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

    <dependency>
        <groupId>org.freemarker</groupId>
        <artifactId>freemarker</artifactId>
        <version>2.3.28</version>
        <scope>compile</scope>
    </dependency>

    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.18.22</version>
    </dependency>

</dependencies>

2.3 邮箱smtp配置

  因为各大邮件都有其对应安全系统,不是项目中想用就可以用的,我们必须要拿到其对应的客户端授权码才行,拿到授权码,在项目中配置SMTP服务协议以及主机配置账户,才可以在项目中使用各大邮件

运营商进行发送邮件了。

  什么是SMTP?SMTP全称为Simple Mail Transfer Protocol(简单邮件传输协议),它是一组用于从源地址到目的地址传输邮件的规范,通过它来控制邮件的中转方式。SMTP认证要求必须提供账号和密码

才能登陆服务器,其设计目的在于避免用户受到垃圾邮件的侵扰。

  什么是IMAP?IMAP全称为Internet Message Access Protocol(互联网邮件访问协议),IMAP允许从邮件服务器上获取邮件的信息、下载邮件等。IMAP与POP类似,都是一种邮件获取协议。

  什么是POP3?POP3全称为Post Office Protocol 3(邮局协议),POP3支持客户端远程管理服务器端的邮件。POP3常用于“离线”邮件处理,即允许客户端下载服务器邮件,然后服务器上的邮件将会被删

除。目前很多POP3的邮件服务器只提供下载邮件功能,服务器本身并不删除邮件,这种属于改进版的POP3协议。

  获取客户端授权码过程,由于国内使用163邮箱以及qq邮箱较多,仅展示163邮箱获取客户端授权码的步骤(qq的类似)

 如果没有开启,选择开启发送验证码即可,我的是已经开过了(如果忘记授权码,重新发送短信生成)

2.4 配置yml文件

在拿到授权码后,就可以在我们Springboot工程中的配置文件 aplication.yml 或者properties文件中配置了

server:
  port: 8091
# 邮件配置
spring:
  mail:
    # 这里换成自己的邮箱类型 例如smtp.163.com, smtp.qq.com
    host: smtp.163.com
    # 发送邮件服务协议
    protocol: smtp
    # 编码集
    default-encoding: UTF-8
    # 发送邮件的账户
    username: liy22222@163.com
    # 授权码(自己邮箱的授权码)
    password: AWYFJEIJSDFJASSDDDVOC
    test-connection: true
    properties:
      mail:
        smtp:
          # 表示SMTP发送邮件,需要进行身份验证
          auth: true
          starttls:
            enable: true
            required: true

2.5 创建接收消息的对象

package com.liyh;

import lombok.*;

@Data
public class MessageInfo {

    /**
     * 收件人邮箱
     **/
    private String receiver;

    /**
     * 一对多群发收件人邮箱
     **/
    private String receivers;

    /**
     * 邮件标题
     **/
    private String subject;

    /**
     * 邮件内容
     **/
    private String content;

    /**
     * 图片路径
     **/
    private String imgPath;

    /**
     * 文件路径
     **/
    private String filePath1;

    /**
     * 文件路径
     **/
    private String filePath2;

    /**
     * 发件人姓名
     **/
    private String fromName;

    /**
     * 收件人姓名
     **/
    private String receiverName;

}

2.6 Html邮箱模板

<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8"/>
    <title>邮件通知</title>
</head>
<body>

<div>
    <includetail>
        <div align="center">
            <div class="open_email" style="margin-left: 8px; margin-top: 8px; margin-bottom: 8px; margin-right: 8px;">
                <div>
                    <br>
                    <span class="genEmailContent">
                        <div id="cTMail-Wrap"
                             style="word-break: break-all;box-sizing:border-box;text-align:center;min-width:320px; max-width:660px; border:1px solid #f6f6f6; background-color:#f7f8fa; margin:auto; padding:20px 0 30px; font-family:'helvetica neue',PingFangSC-Light,arial,'hiragino sans gb','microsoft yahei ui','microsoft yahei',simsun,sans-serif">
                            <div class="main-content" style="">
                                <table style="width:100%;font-weight:300;margin-bottom:10px;border-collapse:collapse">
                                    <tbody>
                                    <tr style="font-weight:300">
                                        <td style="width:3%;max-width:30px;"></td>
                                        <td style="max-width:600px;">
                                            <div id="cTMail-logo" style="width:92px; height:25px;">
                                                <a href="">
                                                    <img border="0" src="https://image.youyoushop.work/yahoo/zhenyu.png"
                                                         style="height:50px;display:block">
                                                </a>
                                            </div>
                                            <p style="height:2px;background-color: #00a4ff;border: 0;font-size:0;padding:0;width:100%;margin-top:20px;"></p>

                                            <div id="cTMail-inner" style="background-color:#fff; padding:23px 0 20px;box-shadow: 0px 1px 1px 0px rgba(122, 55, 55, 0.2);text-align:left;">
                                                <table style="width:100%;font-weight:300;margin-bottom:10px;border-collapse:collapse;text-align:left;">
                                                    <tbody>
                                                    <tr style="font-weight:300">
                                                        <td style="width:3.2%;max-width:30px;"></td>
                                                        <td style="max-width:480px;text-align:left;">
                                                            <h1 id="cTMail-title" style="font-size: 20px; line-height: 36px; margin: 0px 0px 22px;">
                                                                邮件测试平台
                                                            </h1>
                                                            <p id="cTMail-receiverName" style="font-size:14px;color:#333; line-height:24px; margin:0;">
                                                                尊敬的<span style="font-weight: bold;">&nbsp;${receiverName}&nbsp;</span>用户,您好!
                                                            </p>

                                                            <p class="cTMail-content" style="line-height: 24px; margin: 6px 0px 0px; overflow-wrap: break-word; word-break: break-all;">
                                                                <span style="color: rgb(51, 51, 51); font-size: 14px;">
                                                                    由<span style="font-weight: bold;">&nbsp;${fromName}&nbsp;</span>发送的邮件请及时处理。消息内容如下:<br/>
                                                                </span>
                                                            </p>

                                                            <p class="cTMail-content" style="line-height: 24px; margin: 6px 0px 0px; overflow-wrap: break-word; word-break: break-all;">
                                                                <span style="color: rgb(51, 51, 51); font-size: 14px;">
                                                                    <span style="font-weight: bold;">${content}</span>
                                                                </span>
                                                            </p>

                                                            <dl style="font-size: 14px; color: rgb(51, 51, 51); line-height: 18px;">
                                                                <dd style="margin: 0px 0px 6px; padding: 0px; font-size: 12px; line-height: 22px;">
                                                                    <p id="cTMail-sender" style="font-size: 14px; line-height: 26px; word-wrap: break-word; word-break: break-all; margin-top: 32px;">
                                                                        发送时间
                                                                        <br>
                                                                        <strong>${sendTime}</strong>
                                                                    </p>
                                                                </dd>
                                                            </dl>
                                                        </td>
                                                        <td style="width:3.2%;max-width:30px;"></td>
                                                    </tr>
                                                    </tbody>
                                                </table>
                                            </div>

                                        </td>
                                        <td style="width:3%;max-width:30px;"></td>
                                    </tr>
                                    </tbody>
                                </table>
                            </div>
                        </div>
                    </span>
                </div>
            </div>
        </div>
    </includetail>
</div>

</body>
</html>

2.7 创建Spring工具类

package com.liyh;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

/**
 * spring工具类 方便在非spring管理环境中获取bean
 */
@Component
public final class SpringUtils implements BeanFactoryPostProcessor, ApplicationContextAware {
    /**
     * Spring应用上下文环境
     */
    private static ConfigurableListableBeanFactory beanFactory;

    private static ApplicationContext applicationContext;

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        SpringUtils.beanFactory = beanFactory;
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        SpringUtils.applicationContext = applicationContext;
    }

    /**
     * 获取对象
     *
     * @param name
     * @return Object 一个以所给名字注册的bean的实例
     * @throws org.springframework.beans.BeansException
     */
    @SuppressWarnings("unchecked")
    public static <T> T getBean(String name) throws BeansException {
        return (T) beanFactory.getBean(name);
    }

    /**
     * 获取类型为requiredType的对象
     *
     * @param clz
     * @return
     * @throws org.springframework.beans.BeansException
     */
    public static <T> T getBean(Class<T> clz) throws BeansException {
        T result = (T) beanFactory.getBean(clz);
        return result;
    }

}

2.8 创建 MailUtil 工具类

package com.liyh;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;

@Component
public class MailUtil {

    /**
     * 从配置文件中注入发件人的姓名
     */
    @Value("${spring.mail.username}")
    private String fromEmail;

    /**
     * Spring官方提供的集成邮件服务的实现类,目前是Java后端发送邮件和集成邮件服务的主流工具。
     */
    @Autowired
    private JavaMailSender mailSender;

    @Autowired
    private FreeMarkerConfigurer freeMarkerConfigurer;

}

2.9 创建 MailUtils 工具类

package com.liyh;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

/**
 * 统一邮件发送工具类
 *
 * @author Liyh
 * @date 2022/03/28
 */

@Component
public class MailUtils {

    /**
     * 从配置文件中注入是否需要身份验证
     */
    @Value("${spring.mail.properties.mail.smtp.auth}")
    private String auth;

    /**
     * 从配置文件中注入邮箱类型
     */
    @Value("${spring.mail.host}")
    private String emailHost;

    /**
     * 从配置文件中注入发件人
     */
    @Value("${spring.mail.username}")
    private String fromEmail;

    /**
     * 从配置文件中注入授权码
     */
    @Value("${spring.mail.password}")
    private String password;

}

2.10 创建 SendMailController

package com.liyh;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * 发送邮件接口
 */
@RestController
@RequestMapping("/mail")
public class SendMailController {
    
}

3. 第一种方式可以配置模板使用

下面开始 SpringBoot 项目中发送邮件的代码编写

其实也非常简单 ,SpringBoot已经给我们邮件发送进行了非常好的整合了,我们只需要注入邮件发送接口 调用其中的方法,就能轻松而愉悦的进行邮件发送了!

3.1 发送文本邮件

3.1.1 创建 MailUtil 工具类,添加代码

/**
* 发送文本邮件
*
* @param receiver 收件人
* @param subject  邮件标题
* @param content  邮件内容
*/
public String sendSimpleMail(String receiver, String subject, String content) {
    try {
        SimpleMailMessage message = new SimpleMailMessage();
        // 发件人
        message.setFrom(fromEmail);
        // 收件人
        message.setTo(receiver);
        // 邮件标题
        message.setSubject(subject);
        // 邮件内容
        message.setText(content);

        mailSender.send(message);
        return "发送文本邮件成功";
    } catch (MailException e) {
        e.printStackTrace();
        return "发送文本邮件失败!!!";
    }
}

3.1.2 添加访问接口

/**
* 发送文本邮件
*
* @param messageInfo 邮件信息
*/
@PostMapping("sendSimpleMail")
public String sendSimpleMail(MessageInfo messageInfo) {
    MailUtil mailUtil = SpringUtils.getBean(MailUtil.class);
    return mailUtil.sendSimpleMail(messageInfo.getReceiver(), messageInfo.getSubject(), messageInfo.getContent());
}

3.1.3 测试接口

  

3.2 发送带附件的邮件

3.2.1 在MailUtil工具类添加代码

/**
* 发送带附件的邮件
*
* @param receiver      收件人
* @param subject       邮件标题
* @param content       邮件内容
* @param filePath      文件路径
* @param imgPath       图片路径
* @param multipartFile 上传的文件
*/
public String sendAttachmentsMail(String receiver, String subject, String content, String filePath, String imgPath, MultipartFile multipartFile) {
    try {
        MimeMessage message = mailSender.createMimeMessage();
        // 要带附件第二个参数设为true
        MimeMessageHelper helper = new MimeMessageHelper(message, true);
        // 发件人
        helper.setFrom(fromEmail);
        // 收件人
        helper.setTo(receiver);
        // 邮件标题
        helper.setSubject(subject);
        // 邮件内容,第二个参数:格式是否为html
        helper.setText(content, true);

        // 添加文件附件1
        FileSystemResource file = new FileSystemResource(new File(filePath));
        helper.addAttachment(file.getFilename(), file);

        // 添加文件附件2
        FileSystemResource files = new FileSystemResource(multipartFileToFile(multipartFile));
        helper.addAttachment(files.getFilename(), files);

        // 添加图片附件
        FileSystemResource image = new FileSystemResource(new File(imgPath));
        helper.addAttachment(image.getFilename(), image);

        mailSender.send(message);
        return "发送带附件的邮件成功";
    } catch (MessagingException e) {
        e.printStackTrace();
        return "发送带附件的邮件失败!!!";
    }

} 

3.2.2 在MailUtil工具类添加代码

/**
* 把 multiFile 转换为 file
*
* @param multiFile
* @return
*/
private File multipartFileToFile(MultipartFile multiFile) {
    // 获取文件名
    String fileName = multiFile.getOriginalFilename();
    // 获取文件后缀
    String prefix = fileName.substring(fileName.lastIndexOf("."));
    // 若需要防止生成的临时文件重复,可以在文件名后添加随机码
    try {
        File file = File.createTempFile(fileName, prefix);
        multiFile.transferTo(file);
        return file;
    } catch (Exception e) {
        e.printStackTrace();
    }
    return null;
} 

3.2.3 添加访问接口

/**
* 发送带附件的邮件
*
* @param messageInfo 邮件信息
* @param multipartFile 上传的文件
*/
@PostMapping("sendAttachmentsMail")
public String sendAttachmentsMail(MessageInfo messageInfo, MultipartFile multipartFile) {
    MailUtil mailUtil = SpringUtils.getBean(MailUtil.class);
    // 发送带附件的邮件( 路径中的 \ 通常需要使用 \\, 如果是 / 就不需要使用转义了, \ 常用于本地,而/ 常用于网络连接地址 )
    // D:\nacos1.2.1\bin\logs\access_log.2022-03-22.log
    // C:/Users/Administrator/Pictures/1.jpg
    return mailUtil.sendAttachmentsMail(messageInfo.getReceiver(), messageInfo.getSubject(), messageInfo.getContent(),
                                        messageInfo.getFilePath1(), messageInfo.getImgPath(), multipartFile);
} 

3.2.4 测试接口

 

3.3 发送模板邮件

3.3.1 在MailUtil工具类添加代码

/**
* 发送模板邮件
*
* @param receiver     收件人
* @param subject      邮件标题
* @param content      邮件内容
* @param fromName     发件人姓名
* @param receiverName 收件人姓名
* @return
*/
public String sendTemplateMail(String receiver, String subject, String content, String fromName, String receiverName) {
    SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    // 获得模板
    Template template = null;
    try {
        template = freeMarkerConfigurer.getConfiguration().getTemplate("message.ftl");
    } catch (IOException e) {
        e.printStackTrace();
        return "获取模板失败!!!";
    }
    // 使用Map作为数据模型,定义属性和值
    Map<String, Object> model = new HashMap<>();
    model.put("fromName", fromName);
    model.put("receiverName", receiverName);
    model.put("content", content);
    model.put("sendTime", simpleDateFormat.format(new Date()));

    // 传入数据模型到模板,替代模板中的占位符,并将模板转化为html字符串
    String templateHtml = null;
    try {
        templateHtml = FreeMarkerTemplateUtils.processTemplateIntoString(template, model);
    } catch (IOException e) {
        e.printStackTrace();
        return "转换模板失败!!!";
    } catch (TemplateException e) {
        e.printStackTrace();
        return "转换模板失败!!!";
    }

    // 该方法本质上还是发送html邮件,调用之前发送html邮件的方法
    return this.sendHtmlMail(receiver, subject, templateHtml);
} 
/**
* 发送html邮件
*
* @param receiver 收件人
* @param subject  邮件标题
* @param content  邮件内容
*/
public String sendHtmlMail(String receiver, String subject, String content) {
    try {
        // 注意这里使用的是MimeMessage
        MimeMessage message = mailSender.createMimeMessage();
        MimeMessageHelper helper = new MimeMessageHelper(message, true);
        // 发件人
        helper.setFrom(fromEmail);
        // 收件人
        helper.setTo(receiver);
        // 邮件标题
        helper.setSubject(subject);
        // 邮件内容,第二个参数:格式是否为html
        helper.setText(content, true);
        mailSender.send(message);
        return "发送html邮件成功";
    } catch (MessagingException e) {
        e.printStackTrace();
        return "发送html邮件失败!!!";
    }
} 

3.3.2 添加访问接口

/**
* 发送模板邮件
*
* @param messageInfo 邮件信息
* @return
*/
@PostMapping("sendTemplateMail")
public String sendTemplateMail(MessageInfo messageInfo) {
    MailUtil mailUtil = SpringUtils.getBean(MailUtil.class);
    // 发送Html模板邮件
    return mailUtil.sendTemplateMail(messageInfo.getReceiver(), messageInfo.getSubject(), messageInfo.getContent(),
                                     messageInfo.getFromName(), messageInfo.getReceiverName());
} 

3.3.3 测试接口

  

4 第二种方式可以发送复杂的邮件(支持一对多发送邮件)

4.1 发送复杂邮件

4.1.1 创建 MailUtils 工具类,添加代码

package com.liyh;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import java.util.Date;
import java.util.Properties;

/**
 * 统一邮件发送工具类
 *
 * @author Liyh
 * @date 2022/03/28
 */

@Component
public class MailUtils {

    /**
     * 从配置文件中注入是否需要身份验证
     */
    @Value("${spring.mail.properties.mail.smtp.auth}")
    private String auth;

    /**
     * 从配置文件中注入邮箱类型
     */
    @Value("${spring.mail.host}")
    private String emailHost;

    /**
     * 从配置文件中注入发件人
     */
    @Value("${spring.mail.username}")
    private String fromEmail;

    /**
     * 从配置文件中注入授权码
     */
    @Value("${spring.mail.password}")
    private String password;

    /**
     * 发送复杂邮件
     *
     * @param receivers  收件人
     * @param subject   邮件标题
     * @param content   邮件内容
     * @param imgPath   图片路径
     * @param filePath1 文件路径
     * @param filePath2 文件路径
     */
    public String sendComplexMail(String receivers, String subject, String content, String imgPath, String filePath1, String filePath2) {
        try {
            Properties props = new Properties();
            // 表示SMTP发送邮件,需要进行身份验证
            props.put("mail.smtp.auth", auth);
            props.put("mail.smtp.host", emailHost);
            // 发件人的账号
            props.put("mail.user", fromEmail);
            // 访问SMTP服务时需要提供的密码
            props.put("mail.password", password);

            // 1.Session对象.连接(与邮箱服务器连接)
            Session session = Session.getInstance(props, new Authenticator() {
                protected PasswordAuthentication getPasswordAuthentication() {
                    return new PasswordAuthentication(fromEmail, password);
                }
            });

            // 2.构建邮件信息
            Message message = new MimeMessage(session);
            // 发件人邮箱
            message.setFrom(new InternetAddress(fromEmail));

            // Message.RecipientType.TO:消息接受者
            // Message.RecipientType.CC:消息抄送者
            // Message.RecipientType.BCC:匿名抄送接收者(其他接受者看不到这个接受者的姓名和地址)

            // 判断接收人个数
            if (receivers != null && receivers != "") {
                String[] receiverArray = receivers.split(",");
                if (receiverArray.length == 1) {
                    // 一对一发送邮件
                    message.setRecipient(MimeMessage.RecipientType.TO, new InternetAddress(receiverArray[0]));
                } else {
                    // 一对多发送邮件
                    // 构建一个群发地址数组
                    String[] receiverArry = receivers.split(",");
                    InternetAddress[] adr = new InternetAddress[receiverArry.length];
                    for (int i = 0; i < receiverArry.length; i++) {
                        adr[i] = new InternetAddress(receiverArry[i]);
                    }
                    // Message的setRecipients方法支持群发。。注意:setRecipients方法是复数和点 到点不一样
                    message.setRecipients(Message.RecipientType.TO, adr);
                }
            }

            // 发送日期
            message.setSentDate(new Date());
            // 设置标题
            message.setSubject(subject);

            // 3.准备邮件内容
            // 3.1.准备图片数据
            MimeBodyPart image = new MimeBodyPart();
            FileDataSource imageSource = new FileDataSource(imgPath);
            DataHandler handler = new DataHandler(imageSource);
            image.setDataHandler(handler);
            image.setFileName(imageSource.getName());
            // 创建图片的一个表示用于显示在邮件中显示
            image.setContentID(imageSource.getName());

            // 3.2准备本文本数据
            MimeBodyPart text = new MimeBodyPart();
            text.setContent("<img src='cid:" + image.getContentID() + "'/>" + "<h2>" + content + "</h2>", "text/html;charset=utf-8");

            // 3.3.准备附件数据
            MimeBodyPart appendix1 = new MimeBodyPart();
            FileDataSource fileSource1 = new FileDataSource(filePath1);
            appendix1.setDataHandler(new DataHandler(fileSource1));
            appendix1.setFileName(fileSource1.getName());

            MimeBodyPart appendix2 = new MimeBodyPart();
            FileDataSource fileSource2= new FileDataSource(filePath2);
            appendix2.setDataHandler(new DataHandler(fileSource2));
            appendix2.setFileName(fileSource2.getName());

            // 3.4.拼装邮件正文
            MimeMultipart mimeMultipart = new MimeMultipart();
            mimeMultipart.addBodyPart(image);
            mimeMultipart.addBodyPart(text);
            // 文本和图片内嵌成功
            mimeMultipart.setSubType("related");

            // 3.5.将拼装好的正文内容设置为主体
            MimeBodyPart contentText = new MimeBodyPart();
            contentText.setContent(mimeMultipart);

            // 3.6.拼接附件
            MimeMultipart allFile = new MimeMultipart();
            // 附件
            allFile.addBodyPart(image);
            allFile.addBodyPart(appendix1);
            allFile.addBodyPart(appendix2);
            // 正文
            allFile.addBodyPart(contentText);
            // 正文和附件都存在邮件中,所有类型设置为mixed
            allFile.setSubType("mixed");

            // 3.7.放到Message消息中
            message.setContent(allFile);

            // 4.发送邮件信息
            Transport.send(message);
            return "发送复杂邮件成功";
        } catch (MessagingException e) {
            e.printStackTrace();
            return "发送复杂邮件失败!!!";
        }
    }

}

4.1.2 添加访问接口

/**
* 发送复杂邮件
*
* @param messageInfo 邮件信息
*/
@PostMapping("sendComplexMail")
public String sendComplexMail(MessageInfo messageInfo) {
    MailUtils mailUtils = SpringUtils.getBean(MailUtils.class);
    return mailUtils.sendComplexMail(messageInfo.getReceivers(), messageInfo.getSubject(), messageInfo.getContent(),
                                     messageInfo.getImgPath(), messageInfo.getFilePath1(), messageInfo.getFilePath2());
}

4.1.3 测试接口

 

 

4.2 完整工具类代码

4.2.1 SendMailController

查看代码
 package com.liyh;

import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

/**
 * 发送邮件接口
 */
@RestController
@RequestMapping("/mail")
public class SendMailController {

    /**
     * 发送文本邮件
     *
     * @param messageInfo 邮件信息
     */
    @PostMapping("sendSimpleMail")
    public String sendSimpleMail(MessageInfo messageInfo) {
        MailUtil mailUtil = SpringUtils.getBean(MailUtil.class);
        return mailUtil.sendSimpleMail(messageInfo.getReceiver(), messageInfo.getSubject(), messageInfo.getContent());
    }

    /**
     * 发送带附件的邮件
     *
     * @param messageInfo 邮件信息
     * @param multipartFile 上传的文件
     */
    @PostMapping("sendAttachmentsMail")
    public String sendAttachmentsMail(MessageInfo messageInfo, MultipartFile multipartFile) {
        MailUtil mailUtil = SpringUtils.getBean(MailUtil.class);
        // 发送带附件的邮件( 路径中的 \ 通常需要使用 \\, 如果是 / 就不需要使用转义了, \ 常用于本地,而/ 常用于网络连接地址 )
        // D:\nacos1.2.1\bin\logs\access_log.2022-03-22.log
        // C:/Users/Administrator/Pictures/1.jpg
        return mailUtil.sendAttachmentsMail(messageInfo.getReceiver(), messageInfo.getSubject(), messageInfo.getContent(),
                messageInfo.getFilePath1(), messageInfo.getImgPath(), multipartFile);
    }

    /**
     * 发送模板邮件
     *
     * @param messageInfo 邮件信息
     * @return
     */
    @PostMapping("sendTemplateMail")
    public String sendTemplateMail(MessageInfo messageInfo) {
        MailUtil mailUtil = SpringUtils.getBean(MailUtil.class);
        // 发送Html模板邮件
        return mailUtil.sendTemplateMail(messageInfo.getReceiver(), messageInfo.getSubject(), messageInfo.getContent(),
                messageInfo.getFromName(), messageInfo.getReceiverName());
    }

    /**
     * 发送复杂邮件
     *
     * @param messageInfo 邮件信息
     */
    @PostMapping("sendComplexMail")
    public String sendComplexMail(MessageInfo messageInfo) {
        MailUtils mailUtils = SpringUtils.getBean(MailUtils.class);
        return mailUtils.sendComplexMail(messageInfo.getReceivers(), messageInfo.getSubject(), messageInfo.getContent(),
                messageInfo.getImgPath(), messageInfo.getFilePath1(), messageInfo.getFilePath2());
    }
}

4.2.2 MailUtil

查看代码
 package com.liyh;

import freemarker.template.Template;
import freemarker.template.TemplateException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.FileSystemResource;
import org.springframework.mail.MailException;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Component;
import org.springframework.ui.freemarker.FreeMarkerTemplateUtils;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;

import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Component
public class MailUtil {

    /**
     * 从配置文件中注入发件人的姓名
     */
    @Value("${spring.mail.username}")
    private String fromEmail;

    /**
     * Spring官方提供的集成邮件服务的实现类,目前是Java后端发送邮件和集成邮件服务的主流工具。
     */
    @Autowired
    private JavaMailSender mailSender;

    @Autowired
    private FreeMarkerConfigurer freeMarkerConfigurer;

    /**
     * 发送文本邮件
     *
     * @param receiver 收件人
     * @param subject  邮件标题
     * @param content  邮件内容
     */
    public String sendSimpleMail(String receiver, String subject, String content) {
        try {
            SimpleMailMessage message = new SimpleMailMessage();
            // 发件人
            message.setFrom(fromEmail);
            // 收件人
            message.setTo(receiver);
            // 邮件标题
            message.setSubject(subject);
            // 邮件内容
            message.setText(content);

            mailSender.send(message);
            return "发送文本邮件成功";
        } catch (MailException e) {
            e.printStackTrace();
            return "发送文本邮件失败!!!";
        }
    }

    /**
     * 发送html邮件
     *
     * @param receiver 收件人
     * @param subject  邮件标题
     * @param content  邮件内容
     */
    public String sendHtmlMail(String receiver, String subject, String content) {
        try {
            // 注意这里使用的是MimeMessage
            MimeMessage message = mailSender.createMimeMessage();
            MimeMessageHelper helper = new MimeMessageHelper(message, true);
            // 发件人
            helper.setFrom(fromEmail);
            // 收件人
            helper.setTo(receiver);
            // 邮件标题
            helper.setSubject(subject);
            // 邮件内容,第二个参数:格式是否为html
            helper.setText(content, true);
            mailSender.send(message);
            return "发送html邮件成功";
        } catch (MessagingException e) {
            e.printStackTrace();
            return "发送html邮件失败!!!";
        }
    }

    /**
     * 发送带附件的邮件
     *
     * @param receiver      收件人
     * @param subject       邮件标题
     * @param content       邮件内容
     * @param filePath      文件路径
     * @param imgPath       图片路径
     * @param multipartFile 上传的文件
     */
    public String sendAttachmentsMail(String receiver, String subject, String content, String filePath, String imgPath, MultipartFile multipartFile) {
        try {
            MimeMessage message = mailSender.createMimeMessage();
            // 要带附件第二个参数设为true
            MimeMessageHelper helper = new MimeMessageHelper(message, true);
            // 发件人
            helper.setFrom(fromEmail);
            // 收件人
            helper.setTo(receiver);
            // 邮件标题
            helper.setSubject(subject);
            // 邮件内容,第二个参数:格式是否为html
            helper.setText(content, true);

            // 添加文件附件1
            FileSystemResource file = new FileSystemResource(new File(filePath));
            helper.addAttachment(file.getFilename(), file);

            // 添加文件附件2
            FileSystemResource files = new FileSystemResource(multipartFileToFile(multipartFile));
            helper.addAttachment(files.getFilename(), files);

            // 添加图片附件
            FileSystemResource image = new FileSystemResource(new File(imgPath));
            helper.addAttachment(image.getFilename(), image);

            mailSender.send(message);
            return "发送带附件的邮件成功";
        } catch (MessagingException e) {
            e.printStackTrace();
            return "发送带附件的邮件失败!!!";
        }

    }

    /**
     * 发送模板邮件
     *
     * @param receiver     收件人
     * @param subject      邮件标题
     * @param content      邮件内容
     * @param fromName     发件人姓名
     * @param receiverName 收件人姓名
     * @return
     */
    public String sendTemplateMail(String receiver, String subject, String content, String fromName, String receiverName) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        // 获得模板
        Template template = null;
        try {
            template = freeMarkerConfigurer.getConfiguration().getTemplate("message.ftl");
        } catch (IOException e) {
            e.printStackTrace();
            return "获取模板失败!!!";
        }
        // 使用Map作为数据模型,定义属性和值
        Map<String, Object> model = new HashMap<>();
        model.put("fromName", fromName);
        model.put("receiverName", receiverName);
        model.put("content", content);
        model.put("sendTime", simpleDateFormat.format(new Date()));

        // 传入数据模型到模板,替代模板中的占位符,并将模板转化为html字符串
        String templateHtml = null;
        try {
            templateHtml = FreeMarkerTemplateUtils.processTemplateIntoString(template, model);
        } catch (IOException e) {
            e.printStackTrace();
            return "转换模板失败!!!";
        } catch (TemplateException e) {
            e.printStackTrace();
            return "转换模板失败!!!";
        }

        // 该方法本质上还是发送html邮件,调用之前发送html邮件的方法
        return this.sendHtmlMail(receiver, subject, templateHtml);
    }

    /**
     * 把 multiFile 转换为 file
     *
     * @param multiFile
     * @return
     */
    private File multipartFileToFile(MultipartFile multiFile) {
        // 获取文件名
        String fileName = multiFile.getOriginalFilename();
        // 获取文件后缀
        String prefix = fileName.substring(fileName.lastIndexOf("."));
        // 若需要防止生成的临时文件重复,可以在文件名后添加随机码
        try {
            File file = File.createTempFile(fileName, prefix);
            multiFile.transferTo(file);
            return file;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }


}

MailUtil

4.2.3 MailUtils

查看代码
 package com.liyh;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import java.util.Date;
import java.util.Properties;

/**
 * 统一邮件发送工具类
 *
 * @author Liyh
 * @date 2022/03/28
 */

@Component
public class MailUtils {

    /**
     * 从配置文件中注入是否需要身份验证
     */
    @Value("${spring.mail.properties.mail.smtp.auth}")
    private String auth;

    /**
     * 从配置文件中注入邮箱类型
     */
    @Value("${spring.mail.host}")
    private String emailHost;

    /**
     * 从配置文件中注入发件人
     */
    @Value("${spring.mail.username}")
    private String fromEmail;

    /**
     * 从配置文件中注入授权码
     */
    @Value("${spring.mail.password}")
    private String password;

    /**
     * 发送复杂邮件
     *
     * @param receivers  收件人
     * @param subject   邮件标题
     * @param content   邮件内容
     * @param imgPath   图片路径
     * @param filePath1 文件路径
     * @param filePath2 文件路径
     */
    public String sendComplexMail(String receivers, String subject, String content, String imgPath, String filePath1, String filePath2) {
        try {
            Properties props = new Properties();
            // 表示SMTP发送邮件,需要进行身份验证
            props.put("mail.smtp.auth", auth);
            props.put("mail.smtp.host", emailHost);
            // 发件人的账号
            props.put("mail.user", fromEmail);
            // 访问SMTP服务时需要提供的密码
            props.put("mail.password", password);

            // 1.Session对象.连接(与邮箱服务器连接)
            Session session = Session.getInstance(props, new Authenticator() {
                protected PasswordAuthentication getPasswordAuthentication() {
                    return new PasswordAuthentication(fromEmail, password);
                }
            });

            // 2.构建邮件信息
            Message message = new MimeMessage(session);
            // 发件人邮箱
            message.setFrom(new InternetAddress(fromEmail));

            // Message.RecipientType.TO:消息接受者
            // Message.RecipientType.CC:消息抄送者
            // Message.RecipientType.BCC:匿名抄送接收者(其他接受者看不到这个接受者的姓名和地址)

            // 判断接收人个数
            if (receivers != null && receivers != "") {
                String[] receiverArray = receivers.split(",");
                if (receiverArray.length == 1) {
                    // 一对一发送邮件
                    message.setRecipient(MimeMessage.RecipientType.TO, new InternetAddress(receiverArray[0]));
                } else {
                    // 一对多发送邮件
                    // 构建一个群发地址数组
                    String[] receiverArry = receivers.split(",");
                    InternetAddress[] adr = new InternetAddress[receiverArry.length];
                    for (int i = 0; i < receiverArry.length; i++) {
                        adr[i] = new InternetAddress(receiverArry[i]);
                    }
                    // Message的setRecipients方法支持群发。。注意:setRecipients方法是复数和点 到点不一样
                    message.setRecipients(Message.RecipientType.TO, adr);
                }
            }

            // 发送日期
            message.setSentDate(new Date());
            // 设置标题
            message.setSubject(subject);

            // 3.准备邮件内容
            // 3.1.准备图片数据
            MimeBodyPart image = new MimeBodyPart();
            FileDataSource imageSource = new FileDataSource(imgPath);
            DataHandler handler = new DataHandler(imageSource);
            image.setDataHandler(handler);
            image.setFileName(imageSource.getName());
            // 创建图片的一个表示用于显示在邮件中显示
            image.setContentID(imageSource.getName());

            // 3.2准备本文本数据
            MimeBodyPart text = new MimeBodyPart();
            text.setContent("<img src='cid:" + image.getContentID() + "'/>" + "<h2>" + content + "</h2>", "text/html;charset=utf-8");

            // 3.3.准备附件数据
            MimeBodyPart appendix1 = new MimeBodyPart();
            FileDataSource fileSource1 = new FileDataSource(filePath1);
            appendix1.setDataHandler(new DataHandler(fileSource1));
            appendix1.setFileName(fileSource1.getName());

            MimeBodyPart appendix2 = new MimeBodyPart();
            FileDataSource fileSource2= new FileDataSource(filePath2);
            appendix2.setDataHandler(new DataHandler(fileSource2));
            appendix2.setFileName(fileSource2.getName());

            // 3.4.拼装邮件正文
            MimeMultipart mimeMultipart = new MimeMultipart();
            mimeMultipart.addBodyPart(image);
            mimeMultipart.addBodyPart(text);
            // 文本和图片内嵌成功
            mimeMultipart.setSubType("related");

            // 3.5.将拼装好的正文内容设置为主体
            MimeBodyPart contentText = new MimeBodyPart();
            contentText.setContent(mimeMultipart);

            // 3.6.拼接附件
            MimeMultipart allFile = new MimeMultipart();
            // 附件
            allFile.addBodyPart(image);
            allFile.addBodyPart(appendix1);
            allFile.addBodyPart(appendix2);
            // 正文
            allFile.addBodyPart(contentText);
            // 正文和附件都存在邮件中,所有类型设置为mixed
            allFile.setSubType("mixed");

            // 3.7.放到Message消息中
            message.setContent(allFile);

            // 4.发送邮件信息
            Transport.send(message);
            return "发送复杂邮件成功";
        } catch (MessagingException e) {
            e.printStackTrace();
            return "发送复杂邮件失败!!!";
        }
    }

}

MailUtils

4.3 差不多包含了发送邮件的所有格式,需要的小伙伴可以根据需求修改,项目Gitee地址:SpringBoot-Email

posted @ 2022-04-02 12:37  helloliyh  阅读(3109)  评论(0编辑  收藏  举报