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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM