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

Spring 郵件發(fā)送

主要內容

JavaMail 概述

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

? 廠商所提供的 JavaMail 服務程序可以有選擇地實現某些郵件協議回懦,常見的郵件協議包括:

  • SMTP:簡單郵件傳輸協議,用于發(fā)送電子郵件的傳輸協議次企;
  • POP3:用于接收電子郵件的標準協議怯晕;
  • IMAP:互聯網消息協議,是 POP3 的替代協議缸棵。

? 這三種協議都有對應 SSL 加密傳輸的協議舟茶,分別是 SMTPS,POP3S 和 IMAPS。除 JavaMail 服務提供程序之外吧凉, JavaMail 還需要 JAF(JavaBeans Activation Framework)來處理不是純文本的郵件內容隧出,這包括 MIME(多用途互聯網郵件擴展)、URL 頁面和文件附件等內容阀捅。另外胀瞪,JavaMail 依賴 JAF(JavaBeans Activation Framework),JAF 在 Java6 之后已經合并到 JDK 中饲鄙,而 JDK5 之前需要另外下載 JAF 的類庫凄诞。

在這里插入圖片描述

協議介紹

? 在研究 JavaMail API 的細則之前,首先需要對于 API 用到的協議有個認識傍妒。對于 java mail 來說用到的協議有常見的幾種: SMTP幔摸、POP、IMAP颤练、MIME

SMTP

? 簡單郵件傳輸協議(Simple Mail Transfer Protocol既忆,SMTP)由 RFC 821 定義。它定義了發(fā)送電子郵件的機制嗦玖。在 JavaMail API 環(huán)境中患雇,您基于 JavaMail 的程序將和您的公司或因特網服務供應商的(Internet Service
Provider's,ISP's)SMTP 服務器通信宇挫。SMTP 服務器會中轉消息給接收方 SMTP 服務器以便最終讓用戶經由 POP 或 IMAP 獲得苛吱。


在這里插入圖片描述

POP

? POP 代表郵局協議(Post Office Protocol)。目前用的是版本 3器瘪,也稱 POP3翠储,RFC 1939 定義了這個協議。POP 是一種機制橡疼,因特網上大多數人用它得到郵件援所。它規(guī)定每個用戶一個郵箱的支持。這就是它所能做的欣除,而這也造成了許多混淆住拭。使用 POP3 時,用戶熟悉的許多性能并不是由 POP 協議支持的历帚,如查看有幾封新郵件消息這一性能滔岳。這些性能內建于如 Eudora 或 Microsoft Outlook 之類的程序中,它們能記住一些事挽牢,諸如最近一次收到的郵件谱煤,還能計算出有多少是新的。所以當使用 JavaMail API 時卓研,如果您想要這類信息趴俘,您就必須自己算睹簇。

IMAP

? IMAP 是更高級的用于接收消息的協議。在 RFC 2060 中被定義寥闪,IMAP 代表因特網消息訪問協議(Internet Message Access Protocol)太惠,目前用的是版本 4,也稱 IMAP4疲憋。在用到 IMAP 時凿渊,郵件服務器必需支持這個協議。不能僅僅把使用 POP 的程序用于 IMAP缚柳,并指望它支持 IMAP 所有性能埃脏。假設郵件服務器支持 IMAP,基于 JavaMail 的程序可以利用這種情況 — 用戶在服務器上有多個文件夾(folder)秋忙,并且這些文件夾可以被多個用戶共享彩掐。因為有這一更高級的性能,您也許會認為所有用戶都會使用 IMAP灰追。事實并不是這樣堵幽。要求服務器接收新消息,在用戶請求時發(fā)送到用戶手中弹澎,還要在每個用戶的多個文件夾中維護消息朴下。這樣雖然能將消息集中備份,但隨著用戶長期的郵件夾越來越大苦蒿,到磁盤空間耗盡時殴胧,每個用戶都會受到損失。使用 POP佩迟,就能卸載郵件服務器上保存的消息了团滥。

MIME

? MIME 代表多用途因特網郵件擴展標準(Multipurpose Internet Mail Extensions)。它不是郵件傳輸協議报强。但對傳輸內容的消息惫撰、附件及其它的內容定義了格式。這里有很多不同的有效文檔:RFC 822躺涝、RFC 2045、RFC
2046 和 RFC 2047扼雏。作為一個 JavaMail API 的用戶坚嗜,您通常不必對這些格式操心。無論如何诗充,一定存在這些格式而且程序會用到它苍蔬。

JavaMail 的關鍵對象

? JavaMail 對收發(fā)郵件進行了高級的抽象,形成了一些關鍵的的接口和類蝴蜓,它們構成了程序的基礎碟绑,下面我們分別來了解一下這些最常見的對象俺猿。

Properties 屬性對象

? 由于 JavaMail 需要和郵件服務器進行通信,這就要求程序提供許多諸如服務器地址格仲、端口押袍、用戶名、密碼等信息凯肋,JavaMail 通過 Properties 對象封裝這些屬性信息谊惭。如下面的代碼封裝了兩個屬性信息:

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

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

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

? 其他幾個協議也有類似的一系列屬性放案,如 POP3 的 mail.pop3.host姚建、mail.pop3.port 以及IMAP 的 mail.imap.host、mail.imap.host 等吱殉。

Session 會話對象

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

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

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

Transport 和 Store 傳輸和存儲

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

Message 消息對象

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

Address 地址

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

Authenticator 認證者

? 與 java 類一樣嫩海,JavaMail API 也可以利用 Authenticator 通過用戶名和密碼訪問受保護的資源冬殃。對于 JavaMail API 來說,這些資源就是郵件服務器叁怪。JavaMail Authenticator 在 javax.mail 包中审葬,而且它和 java.net 中同名的類 Authenticator 不同。兩者并不共享同一個 Authenticator奕谭,因為 JavaMail API 用于 Java 1.1涣觉,它沒有 java.net 類別。要使用 Authenticator血柳,先創(chuàng)建一個抽象類的子類官册,并從 getPasswordAuthentication() 方法中返回 PasswordAuthentication 實例。創(chuàng)建完成后难捌,您必需向 session 注冊 Authenticator膝宁。然后,在需要認證的時候根吁,就會通知 Authenticator昆汹。您可以彈出窗口,也可以從配置文件中(雖然沒有加密是不安全的)讀取用戶名和密碼婴栽,將它們作為 PasswordAuthentication 對象返回給調用程序。

Java Mail 環(huán)境準備

設置郵箱服務

這里是以163郵箱為例

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

注冊 163 郵箱辈末,登錄 163 郵箱后愚争,設置郵箱賬戶開通 smtp 服務

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

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

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

添加依賴

創(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 {

        // 定義郵箱服務器配置
        Properties prop = new Properties();
        // 設置郵件服務器主機名 (163 郵件服務器地址:"mail.smtp.host"  "smtp.163.com")
        prop.setProperty("mail.smtp.host", "smtp.163.com");
        // 設置郵件服務器的端口
        prop.setProperty("mail.smtp.port", "25");
        // 設置郵件服務器認證屬性 (設置為true表示發(fā)送服務器需要身份驗證)
        prop.setProperty("mail.smtp.auth", "true");
        // 某些郵箱服務器要求 SMTP 連接需要使用 SSL 安全認證
        // 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. 使用郵箱的用戶名和密碼連上郵件服務器(用戶名只需寫@前面的即可,密碼是指授權碼)
        ts.connect("smtp.163.com", "用戶名", "密碼");
        // 4. 創(chuàng)建郵件
        // 發(fā)送普通文本的郵件
        Message message = createSimpleTxtMail(session);
        
        // 5. 發(fā)送郵件
        ts.sendMessage(message, message.getAllRecipients());
        // 關閉transport對象
        ts.close();

    }

    /**
     * 普通文本郵件
     *      創(chuàng)建一封只包含文本的郵件
     * @param session
     * @return
     */
    public static MimeMessage createSimpleTxtMail(Session session) throws MessagingException {
        // 創(chuàng)建郵件對象
        MimeMessage message = new MimeMessage(session);
        // 設置郵件的發(fā)件人的郵箱地址
        message.setFrom(new InternetAddress("發(fā)件人的郵箱地址"));
        // 設置郵件的收件人的郵箱地址 (現在發(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("測試文本郵件");
        // 設置發(fā)送日期
        message.setSentDate(new Date());
        // 郵件的文本內容 (setText():純文本內容)
        message.setText("你好,這是一封測試郵件中狂!");

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

效果如下:

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

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

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內容的郵件
 */
public class MailTest02 {

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

        // 定義郵箱服務器配置
        Properties prop = new Properties();
        // 設置郵件服務器主機名 (163 郵件服務器地址:"mail.smtp.host"  "smtp.163.com")
        prop.setProperty("mail.smtp.host", "smtp.163.com");
        // 設置郵件服務器的端口
        prop.setProperty("mail.smtp.port", "25");
        // 設置郵件服務器認證屬性 (設置為true表示發(fā)送服務器需要身份驗證)
        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. 使用郵箱的用戶名和密碼連上郵件服務器(用戶名只需寫@前面的即可,密碼是指授權碼)
        ts.connect("smtp.163.com", "用戶名", "密碼");
        // 4. 創(chuàng)建郵件
        // 發(fā)送HTML內容的郵件
        Message message = createHtmlMail(session);
       
        // 5. 發(fā)送郵件
        ts.sendMessage(message, message.getAllRecipients());
        // 關閉transport對象
        ts.close();

    }

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

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

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

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

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

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

效果如下:

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(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 {

        // 定義郵箱服務器配置
        Properties prop = new Properties();
        // 設置郵件服務器主機名 (163 郵件服務器地址:"mail.smtp.host"  "smtp.163.com")
        prop.setProperty("mail.smtp.host", "smtp.163.com");
        // 設置郵件服務器的端口
        prop.setProperty("mail.smtp.port", "25");
        // 設置郵件服務器認證屬性 (設置為true表示發(fā)送服務器需要身份驗證)
        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. 使用郵箱的用戶名和密碼連上郵件服務器(用戶名只需寫@前面的即可内边,密碼是指授權碼)
        ts.connect("smtp.163.com", "用戶名", "密碼");
        // 4. 創(chuàng)建郵件
        // 發(fā)送包含附件的郵件
        Message message = createAttachMail(session);
        
        // 5. 發(fā)送郵件
        ts.sendMessage(message, message.getAllRecipients());
        // 關閉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);
        // 設置郵件的發(fā)件人的郵箱地址
        message.setFrom(new InternetAddress("發(fā)件人的郵箱地址"));
        // 設置郵件的收件人的郵箱地址 (現在發(fā)件人和收件人是一樣的,那就是自己給自己發(fā))
        message.setRecipient(Message.RecipientType.TO, new InternetAddress("收件人的郵箱地址"));
        // 郵件的主題
        message.setSubject("測試包含附件的郵件");
        // 設置發(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)建容器描述數據關系
        MimeMultipart multipart = new MimeMultipart();
        // 添加正文
        multipart.addBodyPart(bodyPart);
        // 添加附件
        multipart.addBodyPart(attachPart);
        // 如果在郵件中要添加附件待锈,設置為mixed漠其;。
        multipart.setSubType("mixed");

        // 設置郵件的內容
        message.setContent(multipart);

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

效果如下:

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

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

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

package com.xxxx.mail;

import java.util.List;

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

    private String serverHost; // 服務器主機
    private String serverPort; // 服務器端口

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

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

    private String subject; // 郵件主題
    private String content; // 郵件內容

    private Boolean flag = true; // 是否需要身份認證

    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)建認證類

package com.xxxx.mail;

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

/**
 * 認證類
 */
public class MyAuthenticator extends Authenticator {

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

    /**
     * 郵件服務器發(fā)送郵件時炉擅,進行身份驗證
     * @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 {
            // 定義郵箱服務器配置
            Properties props = new Properties();
            // 163 郵件服務器地址
            props.put("mail.smtp.host", mailSendInfo.getServerHost());
            // 163 郵件服務器端口
            props.put("mail.smtp.port",mailSendInfo.getServerPort());
            // 163 郵件服務器認證屬性
            props.put("mail.smtp.auth", mailSendInfo.getFlag());
            // 身份認證類
            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);
            // 設置發(fā)送方的郵箱地址
            Address from = new InternetAddress(mailSendInfo.getFromAddress());
            message.setFrom(from);
            // 設置發(fā)送時間
            message.setSentDate(new Date());

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

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

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

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

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

郵件發(fā)送測試

發(fā)送HTML內容的郵件
/**
  * 發(fā)送HTML內容的郵件
  */
public static void testHtmlMail() {
    MailSendInfo mailSendInfo = new MailSendInfo();
    mailSendInfo.setServerHost("smtp.163.com");
    mailSendInfo.setServerPort("25");
    mailSendInfo.setUserName("郵箱用戶名");
    mailSendInfo.setUserPwd("密碼(授權碼)");
    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);
}

效果如下:

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(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("密碼(授權碼)");
    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);
}

效果如下:

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

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

環(huá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坐標依賴 -->
<dependency>
    <groupId>com.sun.mail</groupId>
    <artifactId>javax.mail</artifactId>
    <version>1.6.2</version>
</dependency>

配置郵件發(fā)送 bean

在 spring.xml 配置文件中設置郵件發(fā)送對應的bean標簽

<?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>

定義接口與實現類

定義接口

package com.xxxx.springMail;

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

定義實現類

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);
        // 設置郵件收件人的郵箱地址
        msg.setTo("收件人的郵箱地址");
        // 設置郵件內容
        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("收件人的郵箱地址"));//設置接收人
    helper.setText("Thank you for ordering!"); // 郵件內容
    helper.setFrom("發(fā)件人的郵箱地址"); // 發(fā)件人
    // 設置附件
    File file = new File("C:\\work\\郵件附件.txt");
    // 添加附件
    helper.addAttachment(file.getName(), file);
    // 發(fā)送郵件
    mailSender.send(message);
}
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末颠印,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子抹竹,更是在濱河造成了極大的恐慌线罕,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件窃判,死亡現場離奇詭異钞楼,居然都是意外死亡,警方通過查閱死者的電腦和手機袄琳,發(fā)現死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進店門询件,熙熙樓的掌柜王于貴愁眉苦臉地迎上來燃乍,“玉大人,你說我怎么就攤上這事宛琅】绦罚” “怎么了?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵嘿辟,是天一觀的道長舆瘪。 經常有香客問我,道長红伦,這世上最難降的妖魔是什么英古? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮色建,結果婚禮上哺呜,老公的妹妹穿的比我還像新娘。我一直安慰自己箕戳,他們只是感情好某残,可當我...
    茶點故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著陵吸,像睡著了一般玻墅。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上壮虫,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天澳厢,我揣著相機與錄音,去河邊找鬼囚似。 笑死剩拢,一個胖子當著我的面吹牛,可吹牛的內容都是我干的饶唤。 我是一名探鬼主播徐伐,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼募狂!你這毒婦竟也來了办素?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤祸穷,失蹤者是張志新(化名)和其女友劉穎性穿,沒想到半個月后,有當地人在樹林里發(fā)現了一具尸體雷滚,經...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡需曾,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片胯舷。...
    茶點故事閱讀 39,785評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡刻蚯,死狀恐怖,靈堂內的尸體忽然破棺而出桑嘶,到底是詐尸還是另有隱情,我是刑警寧澤躬充,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布逃顶,位于F島的核電站,受9級特大地震影響充甚,放射性物質發(fā)生泄漏以政。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一盈蛮、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧技矮,春花似錦抖誉、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至驻襟,卻和暖如春夺艰,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背沉衣。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工郁副, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人厢蒜。 一個月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓霞势,卻偏偏與公主長得像,于是被迫代替她去往敵國和親斑鸦。 傳聞我的和親對象是個殘疾皇子愕贡,可洞房花燭夜當晚...
    茶點故事閱讀 44,713評論 2 354

推薦閱讀更多精彩內容