Spring 郵件發(fā)送詳細(xì)流程

Spring 郵件發(fā)送

主要內(nèi)容

JavaMail 概述

? JavaMail,顧名思義,提供給開發(fā)者處理電子郵件相關(guān)的編程接口。JavaMail 是由 Sun 定義的一套收發(fā)電子郵件的 API,它可以方便地執(zhí)行一些常用的郵件傳輸,不同的廠商可以提供自己的實現(xiàn)類。但它并沒有包含在 JDK 中,而是作為 JavaEE 的一部分。

? 廠商所提供的 JavaMail 服務(wù)程序可以有選擇地實現(xiàn)某些郵件協(xié)議,常見的郵件協(xié)議包括:

  • SMTP:簡單郵件傳輸協(xié)議,用于發(fā)送電子郵件的傳輸協(xié)議;
  • POP3:用于接收電子郵件的標(biāo)準(zhǔn)協(xié)議;
  • IMAP:互聯(lián)網(wǎng)消息協(xié)議,是 POP3 的替代協(xié)議。

? 這三種協(xié)議都有對應(yīng) SSL 加密傳輸?shù)膮f(xié)議,分別是 SMTPS,POP3S 和 IMAPS。除 JavaMail 服務(wù)提供程序之外, JavaMail 還需要 JAF(JavaBeans Activation Framework)來處理不是純文本的郵件內(nèi)容,這包括 MIME(多用途互聯(lián)網(wǎng)郵件擴展)、URL 頁面和文件附件等內(nèi)容。另外,JavaMail 依賴 JAF(JavaBeans Activation Framework),JAF 在 Java6 之后已經(jīng)合并到 JDK 中,而 JDK5 之前需要另外下載 JAF 的類庫。

在這里插入圖片描述

協(xié)議介紹

? 在研究 JavaMail API 的細(xì)則之前,首先需要對于 API 用到的協(xié)議有個認(rèn)識。對于 java mail 來說用到的協(xié)議有常見的幾種: SMTP、POP、IMAP、MIME

SMTP

? 簡單郵件傳輸協(xié)議(Simple Mail Transfer Protocol,SMTP)由 RFC 821 定義。它定義了發(fā)送電子郵件的機制。在 JavaMail API 環(huán)境中,您基于 JavaMail 的程序?qū)⒑湍墓净蛞蛱鼐W(wǎng)服務(wù)供應(yīng)商的(Internet Service
Provider's,ISP's)SMTP 服務(wù)器通信。SMTP 服務(wù)器會中轉(zhuǎn)消息給接收方 SMTP 服務(wù)器以便最終讓用戶經(jīng)由 POP 或 IMAP 獲得。


在這里插入圖片描述

POP

? POP 代表郵局協(xié)議(Post Office Protocol)。目前用的是版本 3,也稱 POP3,RFC 1939 定義了這個協(xié)議。POP 是一種機制,因特網(wǎng)上大多數(shù)人用它得到郵件。它規(guī)定每個用戶一個郵箱的支持。這就是它所能做的,而這也造成了許多混淆。使用 POP3 時,用戶熟悉的許多性能并不是由 POP 協(xié)議支持的,如查看有幾封新郵件消息這一性能。這些性能內(nèi)建于如 Eudora 或 Microsoft Outlook 之類的程序中,它們能記住一些事,諸如最近一次收到的郵件,還能計算出有多少是新的。所以當(dāng)使用 JavaMail API 時,如果您想要這類信息,您就必須自己算。

IMAP

? IMAP 是更高級的用于接收消息的協(xié)議。在 RFC 2060 中被定義,IMAP 代表因特網(wǎng)消息訪問協(xié)議(Internet Message Access Protocol),目前用的是版本 4,也稱 IMAP4。在用到 IMAP 時,郵件服務(wù)器必需支持這個協(xié)議。不能僅僅把使用 POP 的程序用于 IMAP,并指望它支持 IMAP 所有性能。假設(shè)郵件服務(wù)器支持 IMAP,基于 JavaMail 的程序可以利用這種情況 — 用戶在服務(wù)器上有多個文件夾(folder),并且這些文件夾可以被多個用戶共享。因為有這一更高級的性能,您也許會認(rèn)為所有用戶都會使用 IMAP。事實并不是這樣。要求服務(wù)器接收新消息,在用戶請求時發(fā)送到用戶手中,還要在每個用戶的多個文件夾中維護消息。這樣雖然能將消息集中備份,但隨著用戶長期的郵件夾越來越大,到磁盤空間耗盡時,每個用戶都會受到損失。使用 POP,就能卸載郵件服務(wù)器上保存的消息了。

MIME

? MIME 代表多用途因特網(wǎng)郵件擴展標(biāo)準(zhǔn)(Multipurpose Internet Mail Extensions)。它不是郵件傳輸協(xié)議。但對傳輸內(nèi)容的消息、附件及其它的內(nèi)容定義了格式。這里有很多不同的有效文檔:RFC 822、RFC 2045、RFC
2046 和 RFC 2047。作為一個 JavaMail API 的用戶,您通常不必對這些格式操心。無論如何,一定存在這些格式而且程序會用到它。

JavaMail 的關(guān)鍵對象

? JavaMail 對收發(fā)郵件進(jìn)行了高級的抽象,形成了一些關(guān)鍵的的接口和類,它們構(gòu)成了程序的基礎(chǔ),下面我們分別來了解一下這些最常見的對象。

Properties 屬性對象

? 由于 JavaMail 需要和郵件服務(wù)器進(jìn)行通信,這就要求程序提供許多諸如服務(wù)器地址、端口、用戶名、密碼等信息,JavaMail 通過 Properties 對象封裝這些屬性信息。如下面的代碼封裝了兩個屬性信息:

Properties props = new Properties();
props.put("mail.smtp.host", "smtp.sina.com.cn");
props.put("mail.smtp.auth", "true");

? 針對不同的的郵件協(xié)議,JavaMail 規(guī)定了服務(wù)提供者必須支持一系列屬性,下表是針對 SMTP 協(xié)議的一些常見屬性(屬性值都以 String 類型進(jìn)行設(shè)置,屬性類型欄僅表示屬性是如何被解析的):

屬性名 類型 說明
mail.smtp.host String SMTP 服務(wù)器地址,如smtp.sina.com.cn
mail.smtp.port int SMTP 服務(wù)器端口號,默認(rèn)為 25
mail.smtp.auth boolean SMTP 服務(wù)器是否需要用戶認(rèn)證,默認(rèn)為 false
mail.smtp.user String SMTP 默認(rèn)的登陸用戶名
mail.smtp.from String 默認(rèn)的郵件發(fā)送源地址
mail.smtp.socketFactory.class String socket 工廠類類名
通過設(shè)置該屬性可以覆蓋提供者默認(rèn)的實現(xiàn),必須實現(xiàn)javax.NET.SocketFactory接口
mail.smtp.socketFactory.port int 指定 socket 工廠類所用的端口號
如果沒有規(guī)定,則使用默認(rèn)的端口號
mail.smtp.socketFactory.fallback boolean 設(shè)置為 true 時,當(dāng)使用指定的socket 類創(chuàng)建 socket 失敗后,將使用 Java.net.Socket 創(chuàng)建socket,默認(rèn)為 true
mail.smtp.timeout int I/O 連接超時時間,單位為毫秒,默認(rèn)為永不超時

? 其他幾個協(xié)議也有類似的一系列屬性,如 POP3 的 mail.pop3.host、mail.pop3.port 以及IMAP 的 mail.imap.host、mail.imap.host 等。

Session 會話對象

? Session 是一個很容易被誤解的類,這歸咎于混淆視聽的類名。千萬不要以為這里的 Session 像 HttpSession 一樣代表真實的交互會話,但創(chuàng)建 Session 對象時,并沒有對應(yīng)的物理連接,它只不過是一對配置信息的集合。

? Session 的主要作用,包括兩個方面:

  1. 接收各種配置屬性信息:通過 Properties 對象設(shè)置的屬性信息;
  2. 初始化 JavaMail 環(huán)境:根據(jù) JavaMail 的配置文件,初始化 JavaMail 環(huán)境,以便通過 Session 對象創(chuàng)建其他重要類的實例。

Transport 和 Store 傳輸和存儲

? 郵件操作只有發(fā)送或接收兩種處理方式,JavaMail 將這兩種不同操作描述為傳輸(javax.mail.Transport)和存儲(javax.mail.Store),傳輸對應(yīng)郵件的發(fā)送,而存儲對應(yīng)郵件的接收。

Message 消息對象

? 一旦獲得 Session 對象,就可以繼續(xù)創(chuàng)建要發(fā)送的消息。這由 Message 類來完成。因為 Message 是個抽象類,您必需用一個子類,多數(shù)情況下為 javax.mail.internet.MimeMessage。MimeMessage 是個能理解 MIME 類型和頭的電子郵件消息,正如不同 RFC 中所定義的。雖然在某些頭部域非 ASCII 字符也能被譯碼,但 Message 頭只能被限制為用 US-ASCII 字符。

Address 地址

? 一旦您創(chuàng)建了 Session 和 Message,并將內(nèi)容填入消息后,就可以用 Address 確定信件地址了。和 Message 一樣,Address 也是個抽象類。您用的是 javax.mail.internet.InternetAddress 類。若創(chuàng)建的地址只包含電子郵件地址,只要傳遞電子郵件地址到構(gòu)造器就行了。

Authenticator 認(rèn)證者

? 與 java 類一樣,JavaMail API 也可以利用 Authenticator 通過用戶名和密碼訪問受保護的資源。對于 JavaMail API 來說,這些資源就是郵件服務(wù)器。JavaMail Authenticator 在 javax.mail 包中,而且它和 java.net 中同名的類 Authenticator 不同。兩者并不共享同一個 Authenticator,因為 JavaMail API 用于 Java 1.1,它沒有 java.net 類別。要使用 Authenticator,先創(chuàng)建一個抽象類的子類,并從 getPasswordAuthentication() 方法中返回 PasswordAuthentication 實例。創(chuàng)建完成后,您必需向 session 注冊 Authenticator。然后,在需要認(rèn)證的時候,就會通知 Authenticator。您可以彈出窗口,也可以從配置文件中(雖然沒有加密是不安全的)讀取用戶名和密碼,將它們作為 PasswordAuthentication 對象返回給調(diào)用程序。

Java Mail 環(huán)境準(zhǔn)備

設(shè)置郵箱服務(wù)

這里是以163郵箱為例

[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-OYChfhWu-1607915338270)(/mail-02.png)]

注冊 163 郵箱,登錄 163 郵箱后,設(shè)置郵箱賬戶開通 smtp 服務(wù)

[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-Efjzgo4T-1607915338273)(/mail-03.png)]

[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-Tc8dkcZH-1607915338278)(/mail-04.png)]

? 需要根據(jù)注冊時的手機號發(fā)送的驗證碼來開通獲取郵箱客戶端授權(quán)碼。開通成功后,會顯示個人授權(quán)訪問碼,該授權(quán)碼是后面通過 Java mail 發(fā)送郵件的認(rèn)證密碼,非常重要。

添加依賴

創(chuàng)建 Maven 項目,在 pom.xml 配置文件中添加 mail 的所需的依賴

<!-- Java Mail -->
<dependency>
    <groupId>com.sun.mail</groupId>
    <artifactId>javax.mail</artifactId>
    <version>1.6.2</version>
</dependency>
<dependency>
    <groupId>javax.mail</groupId>
    <artifactId>javax.mail-api</artifactId>
    <version>1.6.2</version>
</dependency>

Java Mail 發(fā)送郵件

發(fā)送普通文本的郵件

package com.xxxx.mail;

import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.mail.*;
import javax.mail.internet.*;
import java.io.UnsupportedEncodingException;
import java.util.Date;
import java.util.Properties;

/**
 * 發(fā)送普通文本的郵件
 */
public class MailTest01 {

    public static void main(String[] args) throws Exception {

        // 定義郵箱服務(wù)器配置
        Properties prop = new Properties();
        // 設(shè)置郵件服務(wù)器主機名 (163 郵件服務(wù)器地址:"mail.smtp.host"  "smtp.163.com")
        prop.setProperty("mail.smtp.host", "smtp.163.com");
        // 設(shè)置郵件服務(wù)器的端口
        prop.setProperty("mail.smtp.port", "25");
        // 設(shè)置郵件服務(wù)器認(rèn)證屬性 (設(shè)置為true表示發(fā)送服務(wù)器需要身份驗證)
        prop.setProperty("mail.smtp.auth", "true");
        // 某些郵箱服務(wù)器要求 SMTP 連接需要使用 SSL 安全認(rèn)證
        // prop.setProperty("mail.smtp.port", "465");
        // prop.setProperty("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
        // prop.setProperty("mail.smtp.socketFactory.fallback", "false");
        // prop.setProperty("mail.smtp.socketFactory.port", "465");

        // 使用JavaMail發(fā)送郵件的5個步驟
        // 1. 創(chuàng)建session
        Session session = Session.getInstance(prop);
        // 開啟Session的debug模式,這樣就可以查看到程序發(fā)送Email的運行狀態(tài)
        session.setDebug(true);
        // 2. 通過session得到transport對象
        Transport ts = session.getTransport();
        // 3. 使用郵箱的用戶名和密碼連上郵件服務(wù)器(用戶名只需寫@前面的即可,密碼是指授權(quán)碼)
        ts.connect("smtp.163.com", "用戶名", "密碼");
        // 4. 創(chuàng)建郵件
        // 發(fā)送普通文本的郵件
        Message message = createSimpleTxtMail(session);
        
        // 5. 發(fā)送郵件
        ts.sendMessage(message, message.getAllRecipients());
        // 關(guān)閉transport對象
        ts.close();

    }

    /**
     * 普通文本郵件
     *      創(chuàng)建一封只包含文本的郵件
     * @param session
     * @return
     */
    public static MimeMessage createSimpleTxtMail(Session session) throws MessagingException {
        // 創(chuàng)建郵件對象
        MimeMessage message = new MimeMessage(session);
        // 設(shè)置郵件的發(fā)件人的郵箱地址
        message.setFrom(new InternetAddress("發(fā)件人的郵箱地址"));
        // 設(shè)置郵件的收件人的郵箱地址 (現(xiàn)在發(fā)件人和收件人是一樣的,那就是自己給自己發(fā))
        message.setRecipient(Message.RecipientType.TO, new InternetAddress("收件人的郵箱地址"));

        // 發(fā)送給多個收件人
        // message.setRecipients(Message.RecipientType.TO, new InternetAddress[] {});
        // Cc: 抄送(可選)
        // message.setRecipient(MimeMessage.RecipientType.CC, new InternetAddress(""));
        // Bcc: 密送(可選)
        // message.setRecipient(MimeMessage.RecipientType.BCC, new InternetAddress(""));

        // 郵件的主題
        message.setSubject("測試文本郵件");
        // 設(shè)置發(fā)送日期
        message.setSentDate(new Date());
        // 郵件的文本內(nèi)容 (setText():純文本內(nèi)容)
        message.setText("你好,這是一封測試郵件!");

        // 返回創(chuàng)建好的郵件對象
        return message;
    }
}

效果如下:

[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-48AWqKi4-1607915338282)(/mail-05.png)]

發(fā)送HTML內(nèi)容的郵件

package com.xxxx.mail;

import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Transport;
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;

/**
 * 發(fā)送HTML內(nèi)容的郵件
 */
public class MailTest02 {

    public static void main(String[] args) throws Exception {

        // 定義郵箱服務(wù)器配置
        Properties prop = new Properties();
        // 設(shè)置郵件服務(wù)器主機名 (163 郵件服務(wù)器地址:"mail.smtp.host"  "smtp.163.com")
        prop.setProperty("mail.smtp.host", "smtp.163.com");
        // 設(shè)置郵件服務(wù)器的端口
        prop.setProperty("mail.smtp.port", "25");
        // 設(shè)置郵件服務(wù)器認(rèn)證屬性 (設(shè)置為true表示發(fā)送服務(wù)器需要身份驗證)
        prop.setProperty("mail.smtp.auth", "true");

        // 使用JavaMail發(fā)送郵件的5個步驟
        // 1. 創(chuàng)建session
        Session session = Session.getInstance(prop);
        // 開啟Session的debug模式,這樣就可以查看到程序發(fā)送Email的運行狀態(tài)
        session.setDebug(true);
        // 2. 通過session得到transport對象
        Transport ts = session.getTransport();
        // 3. 使用郵箱的用戶名和密碼連上郵件服務(wù)器(用戶名只需寫@前面的即可,密碼是指授權(quán)碼)
        ts.connect("smtp.163.com", "用戶名", "密碼");
        // 4. 創(chuàng)建郵件
        // 發(fā)送HTML內(nèi)容的郵件
        Message message = createHtmlMail(session);
       
        // 5. 發(fā)送郵件
        ts.sendMessage(message, message.getAllRecipients());
        // 關(guān)閉transport對象
        ts.close();

    }

    /**
     * HTML內(nèi)容郵件
     *      創(chuàng)建一封包含html內(nèi)容的郵件
     */
    public static MimeMessage createHtmlMail(Session session) throws Exception {

        // 創(chuàng)建郵件對象
        MimeMessage message = new MimeMessage(session);
        // 設(shè)置郵件的發(fā)件人的郵箱地址
        message.setFrom(new InternetAddress("發(fā)件人的郵箱地址"));
        // 設(shè)置郵件的收件人的郵箱地址 (現(xiàn)在發(fā)件人和收件人是一樣的,那就是自己給自己發(fā))
        message.setRecipient(Message.RecipientType.TO, new InternetAddress("收件人的郵箱地址"));
        // 郵件的主題
        message.setSubject("測試HTML郵件");
        // 設(shè)置發(fā)送日期
        message.setSentDate(new Date());

        // 準(zhǔn)備郵件數(shù)據(jù)
        /**
         * Message表示一個郵件,messgaes.getContent()返回一個Multipart對象。
         * 一個Multipart對象包含一個或多個BodyPart對象,來組成郵件的正文部分(包括附件)。
         */
        // 創(chuàng)建多媒體對象
        MimeMultipart multipart = new MimeMultipart();

        // 創(chuàng)建郵件體對象
        MimeBodyPart bodyPart = new MimeBodyPart();
        // 設(shè)置HTML內(nèi)容
        StringBuffer sb = new StringBuffer();
        sb.append("<html><body><a );
        bodyPart.setContent(sb.toString(), "text/html;charset=UTF-8");

        // 將bodyPart對象設(shè)置到multipart對象中
        multipart.addBodyPart(bodyPart);
        // 將multipart對象設(shè)置到message對象中 (setContent():)
        message.setContent(multipart);

        // 返回創(chuàng)建好的郵件對象
        return message;
    }   
}

效果如下:

[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-A6auqgwb-1607915338284)(/mail-06.png)]

發(fā)送包含附件的郵件

package com.xxxx.mail;

import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Transport;
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;

/**
 * 發(fā)送包含附件的郵件
 */
public class MailTest03 {

    public static void main(String[] args) throws Exception {

        // 定義郵箱服務(wù)器配置
        Properties prop = new Properties();
        // 設(shè)置郵件服務(wù)器主機名 (163 郵件服務(wù)器地址:"mail.smtp.host"  "smtp.163.com")
        prop.setProperty("mail.smtp.host", "smtp.163.com");
        // 設(shè)置郵件服務(wù)器的端口
        prop.setProperty("mail.smtp.port", "25");
        // 設(shè)置郵件服務(wù)器認(rèn)證屬性 (設(shè)置為true表示發(fā)送服務(wù)器需要身份驗證)
        prop.setProperty("mail.smtp.auth", "true");

        // 使用JavaMail發(fā)送郵件的5個步驟
        // 1. 創(chuàng)建session
        Session session = Session.getInstance(prop);
        // 開啟Session的debug模式,這樣就可以查看到程序發(fā)送Email的運行狀態(tài)
        session.setDebug(true);
        // 2. 通過session得到transport對象
        Transport ts = session.getTransport();
        // 3. 使用郵箱的用戶名和密碼連上郵件服務(wù)器(用戶名只需寫@前面的即可,密碼是指授權(quán)碼)
        ts.connect("smtp.163.com", "用戶名", "密碼");
        // 4. 創(chuàng)建郵件
        // 發(fā)送包含附件的郵件
        Message message = createAttachMail(session);
        
        // 5. 發(fā)送郵件
        ts.sendMessage(message, message.getAllRecipients());
        // 關(guān)閉transport對象
        ts.close();

    }

    /**
     * 包含附件的郵件
     *      創(chuàng)建一封包含附件的郵件
     * @param session
     * @return
     * @throws MessagingException
     */
    public static MimeMessage createAttachMail(Session session) throws MessagingException {
        // 創(chuàng)建郵件對象
        MimeMessage message = new MimeMessage(session);
        // 設(shè)置郵件的發(fā)件人的郵箱地址
        message.setFrom(new InternetAddress("發(fā)件人的郵箱地址"));
        // 設(shè)置郵件的收件人的郵箱地址 (現(xiàn)在發(fā)件人和收件人是一樣的,那就是自己給自己發(fā))
        message.setRecipient(Message.RecipientType.TO, new InternetAddress("收件人的郵箱地址"));
        // 郵件的主題
        message.setSubject("測試包含附件的郵件");
        // 設(shè)置發(fā)送日期
        message.setSentDate(new Date());


        // 創(chuàng)建郵件正文
        MimeBodyPart bodyPart = new MimeBodyPart();
        bodyPart.setContent("使用JavaMail創(chuàng)建的帶附件的郵件", "text/html;charset=UTF-8");

        // 創(chuàng)建附件
        MimeBodyPart attachPart = new MimeBodyPart();
        // 本地文件
        DataHandler dh = new DataHandler(new FileDataSource("C:\\work\\郵件附件.txt"));
        attachPart.setDataHandler(dh);
        // 附件名
        attachPart.setFileName(dh.getName());

        // 創(chuàng)建容器描述數(shù)據(jù)關(guān)系
        MimeMultipart multipart = new MimeMultipart();
        // 添加正文
        multipart.addBodyPart(bodyPart);
        // 添加附件
        multipart.addBodyPart(attachPart);
        // 如果在郵件中要添加附件,設(shè)置為mixed;。
        multipart.setSubType("mixed");

        // 設(shè)置郵件的內(nèi)容
        message.setContent(multipart);

        // 返回創(chuàng)建好的郵件對象
        return message;
    }
}

效果如下:

[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-8xFx9IR8-1607915338286)(/mail-07.png)]

Java Mail 郵件發(fā)送封裝

創(chuàng)建郵件發(fā)送信息類

package com.xxxx.mail;

import java.util.List;

/**
 * 郵件發(fā)送信息類
 *   定義發(fā)送郵件時 郵件服務(wù)器 端口 發(fā)送方用戶名 密碼等字段
 */
public class MailSendInfo {

    private String serverHost; // 服務(wù)器主機
    private String serverPort; // 服務(wù)器端口

    private String fromAddress;// 發(fā)送方郵箱地址
    private List<String> toAddress; // 接收方郵箱地址

    private String userName; // 郵件服務(wù)器用戶名
    private String userPwd; // 郵件服務(wù)器密碼(授權(quán)密碼)

    private String subject; // 郵件主題
    private String content; // 郵件內(nèi)容

    private Boolean flag = true; // 是否需要身份認(rèn)證

    private List<String> attachFileNames; // 附件文件名


    public Boolean getFlag() {
        return flag;
    }
    public void setFlag(Boolean flag) {
        this.flag = flag;
    }
    public String getServerHost() {
        return serverHost;
    }
    public void setServerHost(String serverHost) {
        this.serverHost = serverHost;
    }
    public String getServerPort() {
        return serverPort;
    }
    public void setServerPort(String serverPort) {
        this.serverPort = serverPort;
    }
    public String getFromAddress() {
        return fromAddress;
    }
    public void setFromAddress(String fromAddress) {
        this.fromAddress = fromAddress;
    }
    public List<String> getToAddress() {
        return toAddress;
    }
    public void setToAddress(List<String> toAddress) {
        this.toAddress = toAddress;
    }
    public String getUserName() {
        return userName;
    }
    public void setUserName(String userName) {
        this.userName = userName;
    }
    public String getUserPwd() {
        return userPwd;
    }
    public void setUserPwd(String userPwd) {
        this.userPwd = userPwd;
    }
    public String getSubject() {
        return subject;
    }
    public void setSubject(String subject) {
        this.subject = subject;
    }
    public String getContent() {
        return content;
    }
    public void setContent(String content) {
        this.content = content;
    }
    public List<String> getAttachFileNames() {
        return attachFileNames;
    }
    public void setAttachFileNames(List<String> attachFileNames) {
        this.attachFileNames = attachFileNames;
    }
}

創(chuàng)建認(rèn)證類

package com.xxxx.mail;

import javax.mail.Authenticator;
import javax.mail.PasswordAuthentication;

/**
 * 認(rèn)證類
 */
public class MyAuthenticator extends Authenticator {

    private String userName; // 郵箱
    private String userPwd; // 密碼(授權(quán)碼)
    public MyAuthenticator(String userName, String userPwd) {
        this.userName = userName;
        this.userPwd = userPwd;
    }

    /**
     * 郵件服務(wù)器發(fā)送郵件時,進(jìn)行身份驗證
     * @return
     */
    @Override
    protected PasswordAuthentication getPasswordAuthentication() {
        return new PasswordAuthentication(userName, userPwd);
    }
}

創(chuàng)建郵件發(fā)送器

package com.xxxx.mail;

import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.mail.*;
import javax.mail.internet.*;
import java.io.File;
import java.util.Date;
import java.util.List;
import java.util.Properties;

public class MailSender {

    public void sendMail(MailSendInfo mailSendInfo){
        Message message = null;
        Session session = null;
        try {
            // 定義郵箱服務(wù)器配置
            Properties props = new Properties();
            // 163 郵件服務(wù)器地址
            props.put("mail.smtp.host", mailSendInfo.getServerHost());
            // 163 郵件服務(wù)器端口
            props.put("mail.smtp.port",mailSendInfo.getServerPort());
            // 163 郵件服務(wù)器認(rèn)證屬性
            props.put("mail.smtp.auth", mailSendInfo.getFlag());
            // 身份認(rèn)證類
            MyAuthenticator authenticator = new MyAuthenticator(mailSendInfo.getUserName(), mailSendInfo.getUserPwd());
            // 創(chuàng)建session
            session = Session.getDefaultInstance(props, authenticator);
            // 開啟Session的debug模式,這樣就可以查看到程序發(fā)送Email的運行狀態(tài)
            session.setDebug(true);
            // 創(chuàng)建message郵件對象
            message = new MimeMessage(session);
            // 設(shè)置發(fā)送方的郵箱地址
            Address from = new InternetAddress(mailSendInfo.getFromAddress());
            message.setFrom(from);
            // 設(shè)置發(fā)送時間
            message.setSentDate(new Date());

            // 判斷接收方的郵箱地址
            if(null != mailSendInfo.getToAddress() && mailSendInfo.getToAddress().size() > 0){
                // 定義數(shù)組
                Address[] addresses = new Address[mailSendInfo.getToAddress().size()];
                // 循環(huán)獲取接收方的郵箱地址,并設(shè)置到對應(yīng)的address數(shù)組中
                for(int i = 0; i < mailSendInfo.getToAddress().size(); i++){
                    Address address = new InternetAddress(mailSendInfo.getToAddress().get(i));
                    addresses[i] = address;
                }
                // 設(shè)置接收方的郵箱地址
                message.setRecipients(Message.RecipientType.TO, addresses);
                // 設(shè)置郵件主題
                message.setSubject(mailSendInfo.getSubject());

                // 創(chuàng)建多媒體對象容器
                Multipart multipart = new MimeMultipart();

                // 創(chuàng)建正文內(nèi)容
                BodyPart bodyPart =new MimeBodyPart();
                bodyPart.setContent(mailSendInfo.getContent(),"text/html;charset=utf-8");
                // 添加正文 (將正文內(nèi)容設(shè)置到多媒體對象容器中)
                multipart.addBodyPart(bodyPart);

                // 獲取所有的附件內(nèi)容
                List<String> files = mailSendInfo.getAttachFileNames();
                // 判斷是否包含附件內(nèi)容
                if(null != files && files.size() > 0){
                    for(int i = 0; i < files.size(); i++){
                        // 獲取對應(yīng)的附件對象
                        File tempFile = new File(files.get(i));
                        // 判斷附件是否存在
                        if(tempFile.exists()){
                            // 如果附件存在,創(chuàng)建附件對象
                            BodyPart attachPart = new MimeBodyPart();
                            attachPart.setDataHandler(new DataHandler(new FileDataSource(tempFile)));
                            // 設(shè)置文件名 (解決附件名亂碼)
                            attachPart.setFileName(MimeUtility.encodeText(tempFile.getName()));
                            // 添加附件 (將附件內(nèi)容添加到多媒體對象容器中)
                            multipart.addBodyPart(attachPart);
                        }
                    }
                }

                // 設(shè)置郵件內(nèi)容
                message.setContent(multipart);
                // 發(fā)送郵件
                Transport.send(message);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

郵件發(fā)送測試

發(fā)送HTML內(nèi)容的郵件
/**
  * 發(fā)送HTML內(nèi)容的郵件
  */
public static void testHtmlMail() {
    MailSendInfo mailSendInfo = new MailSendInfo();
    mailSendInfo.setServerHost("smtp.163.com");
    mailSendInfo.setServerPort("25");
    mailSendInfo.setUserName("郵箱用戶名");
    mailSendInfo.setUserPwd("密碼(授權(quán)碼)");
    mailSendInfo.setSubject("郵件封裝");
    mailSendInfo.setFromAddress("發(fā)件人的郵箱地址");
    mailSendInfo.setContent("<h2>這是封裝后發(fā)送的郵件</h2>");
    List<String> users = new ArrayList<>();
    users.add("收件人的郵箱地址");
    mailSendInfo.setToAddress(users);
    MailSender mailSender=new MailSender();
    mailSender.sendMail(mailSendInfo);
}

效果如下:

[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-UDUgii3O-1607915338289)(/mail-08.png)]

發(fā)送包含附件的郵件
/**
  * 發(fā)送包含附件的郵件
  */
public static void testAttachMail() {
    MailSendInfo mailSendInfo = new MailSendInfo();
    mailSendInfo.setServerHost("smtp.163.com");
    mailSendInfo.setServerPort("25");
    mailSendInfo.setUserName("用戶名");
    mailSendInfo.setUserPwd("密碼(授權(quán)碼)");
    mailSendInfo.setSubject("郵件封裝");
    mailSendInfo.setFromAddress("發(fā)件人的郵箱地址");
    mailSendInfo.setContent("<h2>包含附件的郵件</h2>");
    List<String> users = new ArrayList<>();
    users.add("收件人的郵箱地址");
    mailSendInfo.setToAddress(users);

    // 添加附件
    List<String> files=new ArrayList<String>();
    files.add("C:\\work\\郵件附件.txt");
    files.add("C:\\work\\名單.xlsx");
    mailSendInfo.setAttachFileNames(files);
    MailSender mailSender=new MailSender();
    mailSender.sendMail(mailSendInfo);
}

效果如下:

[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-l9NKzd5z-1607915338291)(/mail-09.png)]

使用 Spring API 實現(xiàn)郵件發(fā)送

環(huán)境準(zhǔn)備

創(chuàng)建 Maven 項目,在 pom.xml 文件中添加依賴

<!-- spring核心 jar 依賴 -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.2.4.RELEASE</version>
</dependency>
<!--spring 上下文環(huán)境 支持-->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context-support</artifactId>
    <version>5.2.4.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-test</artifactId>
    <version>5.2.4.RELEASE</version>
    <scope>test</scope>
</dependency>
<!-- Java Mail坐標(biāo)依賴 -->
<dependency>
    <groupId>com.sun.mail</groupId>
    <artifactId>javax.mail</artifactId>
    <version>1.6.2</version>
</dependency>

配置郵件發(fā)送 bean

在 spring.xml 配置文件中設(shè)置郵件發(fā)送對應(yīng)的bean標(biāo)簽

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd">

    <!-- 開啟自動化掃描  -->
    <context:component-scan base-package="com.xxxx"/>

    <!-- 郵件發(fā)送器(提供了郵件發(fā)送接口、透明創(chuàng)建Java Mail的MimeMessage、及郵件發(fā)送的配置) -->
    <bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
        <property name="host" value="smtp.163.com" />
        <property name="port" value="25" />
        <property name="defaultEncoding" value="utf-8"></property>
        <property name="username" value="用戶名"></property>
        <property name="password" value="密碼"></property>
    </bean>

    <!-- 普通文本郵件對象 -->
    <bean id="templateMessage" class="org.springframework.mail.SimpleMailMessage">
        <property name="from" value="發(fā)件人的郵箱地址" />
        <property name="subject" value="spring_mail" />
    </bean>

</beans>

定義接口與實現(xiàn)類

定義接口

package com.xxxx.springMail;

/**
 * 定義接口
 */
public interface OrderManager {
    void placeOrder();
}

定義實現(xiàn)類

package com.xxxx.springMail;

import org.springframework.mail.MailException;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;

@Service
public class SimpleOrderManager implements OrderManager {

    @Resource
    private JavaMailSenderImpl mailSender;
    @Resource
    private SimpleMailMessage templateMessage;

    @Override
    public void placeOrder() {
        // 獲取郵件對象
        SimpleMailMessage msg = new SimpleMailMessage(this.templateMessage);
        // 設(shè)置郵件收件人的郵箱地址
        msg.setTo("收件人的郵箱地址");
        // 設(shè)置郵件內(nèi)容
        msg.setText("Hello Spring Mail");
        try{
            // 發(fā)送郵件
            this.mailSender.send(msg);
        } catch (MailException ex) {
            System.err.println(ex.getMessage());
        }
    }
}

郵件發(fā)送測試

/**
  *  發(fā)送郵件
  * @param args
  */
public static void main(String[] args) {
    ApplicationContext ac=new ClassPathXmlApplicationContext("spring.xml");
    SimpleOrderManager simpleOrderManager = 
        (SimpleOrderManager) ac.getBean("simpleOrderManager");
    simpleOrderManager.placeOrder();
}

發(fā)送附件

/**
  *  發(fā)送包含附件的郵件
  * @param args
  * @throws MessagingException
  */
public static void main(String[] args) throws MessagingException {
    ApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml");
    JavaMailSender mailSender= (JavaMailSender) ac.getBean("mailSender");
    MimeMessage message= mailSender.createMimeMessage();
    message.setSubject("spring_mail"); // 郵件主題
    // 創(chuàng)建帶有附件的消息幫組類
    MimeMessageHelper helper = new MimeMessageHelper(message,true,"utf-8");
    helper.setTo(new InternetAddress("收件人的郵箱地址"));//設(shè)置接收人
    helper.setText("Thank you for ordering!"); // 郵件內(nèi)容
    helper.setFrom("發(fā)件人的郵箱地址"); // 發(fā)件人
    // 設(shè)置附件
    File file = new File("C:\\work\\郵件附件.txt");
    // 添加附件
    helper.addAttachment(file.getName(), file);
    // 發(fā)送郵件
    mailSender.send(message);
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容