1. 程式人生 > 其它 >SpringBoot整合郵箱傳送郵件

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: [email protected]
    # 授權碼(自己郵箱的授權碼)
    password: AWYCRGDVOAUHTVOC
    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;
    }

}

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 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.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 "傳送複雜郵件失敗!!!";
        }
    }

}
MailUtils

 

4.3 差不多包含了傳送郵件的所有格式,需要的小夥伴可以根據需求修改,專案Gitee地址:SpringBoot-Email