使用JavaMail收發(fā)郵件

概述

郵件相關(guān)的標(biāo)準(zhǔn)

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

SMTP(Simple Mail Transfer Protocol) :即簡單郵件傳輸協(xié)議,它是一組用于由源地址到目的地址傳送郵件的規(guī)則,由它來控制信件的中轉(zhuǎn)方式。

POP3(Post Office Protocol - Version 3) :即郵局協(xié)議版本 3 ,用于接收電子郵件的標(biāo)準(zhǔn)協(xié)議。

IMAP(Internet Mail Access Protocol) :即 Internet 郵件訪問協(xié)議。是 POP3 的替代協(xié)議。

這三種協(xié)議都有對應(yīng) SSL 加密傳輸?shù)膮f(xié)議,分別是 **SMTPS **, **POP3S **和 **IMAPS **。

MIME(Multipurpose Internet Mail Extensions) :即多用途因特網(wǎng)郵件擴(kuò)展標(biāo)準(zhǔn)。它不是郵件傳輸協(xié)議。但對傳輸內(nèi)容的消息、附件及其它的內(nèi)容定義了格式。

JavaMail 簡介

JavaMail 是由 Sun 發(fā)布的用來處理 email 的 API 。它并沒有包含在 Java SE 中,而是作為 Java EE 的一部分。

mail.jar :此 JAR 文件包含 JavaMail API 和 Sun 提供的 SMTP 、 IMAP 和 POP3 服務(wù)提供程序;

activation.jar :此 JAR 文件包含 JAF API 和 Sun 的實(shí)現(xiàn)。

JavaMail 包中用于處理電子郵件的核心類是: PropertiesSessionMessageAddressAuthenticatorTransportStore 等。

郵件傳輸過程

如上圖,電子郵件的處理步驟如下:

  1. 創(chuàng)建一個(gè) Session 對象。

  2. Session 對象創(chuàng)建一個(gè) Transport 對象 /Store 對象,用來發(fā)送 / 保存郵件。

  3. Transport 對象 /Store 對象連接郵件服務(wù)器。

  4. Transport 對象 /Store 對象創(chuàng)建一個(gè) Message 對象 ( 也就是郵件內(nèi)容 ) 。

  5. Transport 對象發(fā)送郵件; Store 對象獲取郵箱的郵件。

Message 結(jié)構(gòu)

MimeMessage 類:代表整封郵件。

MimeBodyPart 類:代表郵件的一個(gè) MIME 信息。

MimeMultipart 類:代表一個(gè)由多個(gè) MIME 信息組合成的組合 MIME 信息。

使用JavaMail收發(fā)郵件0

JavaMail 的核心類

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

java.util.Properties類(屬性對象)

java.util.Properties 類代表一組屬性集合。

它的每一個(gè)鍵和值都是 String 類型。

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

例: 如下面的代碼封裝了幾個(gè)屬性信息:

Properties prop = new Properties();
prop.setProperty("mail.debug", "true");
prop.setProperty("mail.host", "[email protected]");
prop.setProperty("mail.transport.protocol", "smtp");
prop.setProperty("mail.smtp.auth", "true");

針對不同的的郵件協(xié)議, JavaMail 規(guī)定了服務(wù)提供者必須支持一系列屬性,

下表是一些常見屬性(屬性值都以 String 類型進(jìn)行設(shè)置,屬性類型欄僅表示屬性是如何被解析的):

關(guān)鍵詞 類型 描述
mail.debug boolean debug 開關(guān)。
mail.host String 指定發(fā)送、接收郵件的默認(rèn)郵箱服務(wù)器。
mail.store.protocol String 指定接收郵件的協(xié)議。
mail.transport.protocol String 指定發(fā)送郵件的協(xié)議。
mail.debug.auth boolean debug 輸出中是否包含認(rèn)證命令。默認(rèn)是 false 。

詳情請參考官方 API 文檔:

https://javamail.java.net/nonav/docs/api/

javax.mail.Session類(會(huì)話對象)

Session 表示一個(gè)郵件會(huì)話。

Session 的主要作用包括兩個(gè)方面:

  • 接收各種配置屬性信息:通過 Properties 對象設(shè)置的屬性信息;

  • 初始化 JavaMail 環(huán)境:根據(jù) JavaMail 的配置文件,初始化 JavaMail 環(huán)境,以便通過 Session 對象創(chuàng)建其他重要類的實(shí)例。

JavaMail 在 Jar 包的 META-INF 目錄下,通過以下文件提供了基本配置信息,以便 session 能夠根據(jù)這個(gè)配置文件加載提供者的實(shí)現(xiàn)類:

  • javamail.default.providers

  • javamail.default.address.map

Paste_Image.png

例:

Properties props = new Properties();
props.setProperty("mail.transport.protocol", "smtp");
Session session = Session.getInstance(props);

javax.mail.Transport類(郵件傳輸)

郵件操作只有發(fā)送或接收兩種處理方式。

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

getTransport **: **Session 類中的 getTransport **() **有多個(gè)重載方法,可以用來創(chuàng)建 Transport 對象。

connect **: **如果設(shè)置了認(rèn)證命令—— mail.smtp.auth ,那么使用 Transport 類的 connect 方法連接服務(wù)器時(shí),則必須加上用戶名和密碼。

sendMessage : Transport 類的 sendMessage 方法用來發(fā)送郵件消息。

close : Transport 類的 close 方法用來關(guān)閉和郵件服務(wù)器的連接。

javax.mail.Store 類(郵件存儲 )

getStore :Session 類中的 getStore () 有多個(gè)重載方法,可以用來創(chuàng)建 Store 對象。

connect : 如果設(shè)置了認(rèn)證命令—— mail.smtp.auth ,那么使用 Store 類的 connect 方法連接服務(wù)器時(shí),則必須加上用戶名和密碼。

getFolder:Store 類的 getFolder 方法可以 獲取郵箱內(nèi)的郵件夾 Folder 對象

close : Store 類的 close 方法用來關(guān)閉和郵件服務(wù)器的連接。

javax.mail.Message類(消息對象)

javax.mail.Message 是個(gè)抽象類,只能用子類去實(shí)例化,多數(shù)情況下為 javax.mail.internet.MimeMessage

MimeMessage 代表 MIME 類型的電子郵件消息。

要?jiǎng)?chuàng)建一個(gè) Message ,需要將 Session 對象傳遞給 MimeMessage 構(gòu)造器:

MimeMessage message = new MimeMessage(session);

注意:還存在其它構(gòu)造器,如用按 RFC822 格式的輸入流來創(chuàng)建消息。

setFrom :設(shè)置郵件的發(fā)件人

setRecipient :設(shè)置郵件的發(fā)送人、抄送人、密送人

三種預(yù)定義的地址類型是:

Message.RecipientType.TO :收件人

Message.RecipientType.CC :抄送人

Message.RecipientType.BCC :密送人

setSubject :設(shè)置郵件的主題

setContent :設(shè)置郵件內(nèi)容

setText :如果郵件內(nèi)容是純文本,可以使用此接口設(shè)置文本內(nèi)容。

javax.mail.Address類(地址)

一旦您創(chuàng)建了 Session 和 Message ,并將內(nèi)容填入消息后,就可以用 Address 確定信件地址了。和 Message 一樣, Address 也是個(gè)抽象類。您用的是 javax.mail.internet.InternetAddress 類。

若創(chuàng)建的地址只包含電子郵件地址,只要傳遞電子郵件地址到構(gòu)造器就行了。

例:

Address address = new InternetAddress("[email protected]");

Authenticator類(認(rèn)證者)

與 java.net 類一樣, JavaMail API 也可以利用 Authenticator 通過用戶名和密碼訪問受保護(hù)的資源。對于 JavaMail API 來說,這些資源就是郵件服務(wù)器。Authenticator 在 javax.mail 包中,而且它和 java.net 中同名的類 Authenticator 不同。兩者并不共享同一個(gè) Authenticator ,因?yàn)?JavaMail API 用于 Java 1.1 ,它沒有 java.net 類別。

要使用 Authenticator ,先創(chuàng)建一個(gè)抽象類的子類,并從 getPasswordAuthentication() 方法中返回 PasswordAuthentication 實(shí)例。創(chuàng)建完成后,您必需向 session 注冊 Authenticator 。然后,在需要認(rèn)證的時(shí)候,就會(huì)通知 Authenticator 。您可以彈出窗口,也可以從配置文件中(雖然沒有加密是不安全的)讀取用戶名和密碼,將它們作為 PasswordAuthentication 對象返回給調(diào)用程序。

例:

Properties props = new Properties();
Authenticator auth = new MyAuthenticator();
Session session = Session.getDefaultInstance(props, auth);

實(shí)例

發(fā)送文本郵件

public static void main(String[] args) throws Exception {
    Properties prop = new Properties();
    prop.setProperty("mail.debug", "true");
    prop.setProperty("mail.host", MAIL_SERVER_HOST);
    prop.setProperty("mail.transport.protocol", "smtp");
    prop.setProperty("mail.smtp.auth", "true");

    // 1、創(chuàng)建session
    Session session = Session.getInstance(prop);
    Transport ts = null;

    // 2、通過session得到transport對象
    ts = session.getTransport();

    // 3、連上郵件服務(wù)器
    ts.connect(MAIL_SERVER_HOST, USER, PASSWORD);

    // 4、創(chuàng)建郵件
    MimeMessage message = new MimeMessage(session);

    // 郵件消息頭
    message.setFrom(new InternetAddress(MAIL_FROM)); // 郵件的發(fā)件人
    message.setRecipient(Message.RecipientType.TO, new InternetAddress(MAIL_TO)); // 郵件的收件人
    message.setRecipient(Message.RecipientType.CC, new InternetAddress(MAIL_CC)); // 郵件的抄送人
    message.setRecipient(Message.RecipientType.BCC, new InternetAddress(MAIL_BCC)); // 郵件的密送人
    message.setSubject("測試文本郵件"); // 郵件的標(biāo)題

    // 郵件消息體
    message.setText("天下無雙。");

    // 5、發(fā)送郵件
    ts.sendMessage(message, message.getAllRecipients());
    ts.close();
}

發(fā)送 HTML 格式的郵件

public static void main(String[] args) throws Exception {
    Properties prop = new Properties();
    prop.setProperty("mail.debug", "true");
    prop.setProperty("mail.host", MAIL_SERVER_HOST);
    prop.setProperty("mail.transport.protocol", "smtp");
    prop.setProperty("mail.smtp.auth", "true");

    // 1、創(chuàng)建session
    Session session = Session.getInstance(prop);
    Transport ts = null;

    // 2、通過session得到transport對象
    ts = session.getTransport();

    // 3、連上郵件服務(wù)器
    ts.connect(MAIL_SERVER_HOST, USER, PASSWORD);

    // 4、創(chuàng)建郵件
    MimeMessage message = new MimeMessage(session);

    // 郵件消息頭
    message.setFrom(new InternetAddress(MAIL_FROM)); // 郵件的發(fā)件人
    message.setRecipient(Message.RecipientType.TO, new InternetAddress(MAIL_TO)); // 郵件的收件人
    message.setRecipient(Message.RecipientType.CC, new InternetAddress(MAIL_CC)); // 郵件的抄送人
    message.setRecipient(Message.RecipientType.BCC, new InternetAddress(MAIL_BCC)); // 郵件的密送人
    message.setSubject("測試HTML郵件"); // 郵件的標(biāo)題

    String htmlContent = "<h1>Hello</h1>" + "<p>顯示圖片![](cid:abc.jpg)1.jpg</p>";
    MimeBodyPart text = new MimeBodyPart();
    text.setContent(htmlContent, "text/html;charset=UTF-8");
    MimeBodyPart image = new MimeBodyPart();
    DataHandler dh = new DataHandler(new FileDataSource("D:\\05_Datas\\圖庫\\吉他少年背影.png"));
    image.setDataHandler(dh);
    image.setContentID("abc.jpg");

    // 描述數(shù)據(jù)關(guān)系
    MimeMultipart mm = new MimeMultipart();
    mm.addBodyPart(text);
    mm.addBodyPart(image);
    mm.setSubType("related");
    message.setContent(mm);
    message.saveChanges();

    // 5、發(fā)送郵件
    ts.sendMessage(message, message.getAllRecipients());
    ts.close();
}

發(fā)送帶附件的郵件

public static void main(String[] args) throws Exception {
    Properties prop = new Properties();
    prop.setProperty("mail.debug", "true");
    prop.setProperty("mail.host", MAIL_SERVER_HOST);
    prop.setProperty("mail.transport.protocol", "smtp");
    prop.setProperty("mail.smtp.auth", "true");

    // 1、創(chuàng)建session
    Session session = Session.getInstance(prop);

    // 2、通過session得到transport對象
    Transport ts = session.getTransport();

    // 3、連上郵件服務(wù)器
    ts.connect(MAIL_SERVER_HOST, USER, PASSWORD);

    // 4、創(chuàng)建郵件
    MimeMessage message = new MimeMessage(session);

    // 郵件消息頭
    message.setFrom(new InternetAddress(MAIL_FROM)); // 郵件的發(fā)件人
    message.setRecipient(Message.RecipientType.TO, new InternetAddress(MAIL_TO)); // 郵件的收件人
    message.setRecipient(Message.RecipientType.CC, new InternetAddress(MAIL_CC)); // 郵件的抄送人
    message.setRecipient(Message.RecipientType.BCC, new InternetAddress(MAIL_BCC)); // 郵件的密送人
    message.setSubject("測試帶附件郵件"); // 郵件的標(biāo)題

    MimeBodyPart text = new MimeBodyPart();
    text.setContent("郵件中有兩個(gè)附件。", "text/html;charset=UTF-8");

    // 描述數(shù)據(jù)關(guān)系
    MimeMultipart mm = new MimeMultipart();
    mm.setSubType("related");
    mm.addBodyPart(text);
    String[] files = {
            "D:\\00_Temp\\temp\\1.jpg", "D:\\00_Temp\\temp\\2.png"
    };

    // 添加郵件附件
    for (String filename : files) {
        MimeBodyPart attachPart = new MimeBodyPart();
        attachPart.attachFile(filename);
        mm.addBodyPart(attachPart);
    }

    message.setContent(mm);
    message.saveChanges();

    // 5、發(fā)送郵件
    ts.sendMessage(message, message.getAllRecipients());
    ts.close();
} 

獲取郵箱中的郵件

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

    // 創(chuàng)建一個(gè)有具體連接信息的Properties對象
    Properties prop = new Properties();
    prop.setProperty("mail.debug", "true");
    prop.setProperty("mail.store.protocol", "pop3");
    prop.setProperty("mail.pop3.host", MAIL_SERVER_HOST);

    // 1、創(chuàng)建session
    Session session = Session.getInstance(prop);

    // 2、通過session得到Store對象
    Store store = session.getStore();

    // 3、連上郵件服務(wù)器
    store.connect(MAIL_SERVER_HOST, USER, PASSWORD);

    // 4、獲得郵箱內(nèi)的郵件夾
    Folder folder = store.getFolder("inbox");
    folder.open(Folder.READ_ONLY);

    // 獲得郵件夾Folder內(nèi)的所有郵件Message對象
    Message[] messages = folder.getMessages();
    for (int i = 0; i < messages.length; i++) {
        String subject = messages[i].getSubject();
        String from = (messages[i].getFrom()[0]).toString();
        System.out.println("第 " + (i + 1) + "封郵件的主題:" + subject);
        System.out.println("第 " + (i + 1) + "封郵件的發(fā)件人地址:" + from);
    }

    // 5、關(guān)閉
    folder.close(false);
    store.close();
}

轉(zhuǎn)發(fā)郵件

例:獲取指定郵件夾下的第一封郵件并轉(zhuǎn)發(fā)

 public static void main(String[] args) throws Exception {
    Properties prop = new Properties();
    prop.put("mail.store.protocol", "pop3");
    prop.put("mail.pop3.host", MAIL_SERVER_POP3);
    prop.put("mail.pop3.starttls.enable", "true");
    prop.put("mail.smtp.auth", "true");
    prop.put("mail.smtp.host", MAIL_SERVER_SMTP);

    // 1、創(chuàng)建session
    Session session = Session.getDefaultInstance(prop);

    // 2、讀取郵件夾
    Store store = session.getStore("pop3");
    store.connect(MAIL_SERVER_POP3, USER, PASSWORD);
    Folder folder = store.getFolder("inbox");
    folder.open(Folder.READ_ONLY);

    // 獲取郵件夾中第1封郵件信息
    Message[] messages = folder.getMessages();
    if (messages.length <= 0) {
        return;
    }
    Message message = messages[0];

    // 打印郵件關(guān)鍵信息
    String from = InternetAddress.toString(message.getFrom());
    if (from != null) {
        System.out.println("From: " + from);
    }

    String replyTo = InternetAddress.toString(message.getReplyTo());
    if (replyTo != null) {
        System.out.println("Reply-to: " + replyTo);
    }

    String to = InternetAddress.toString(message.getRecipients(Message.RecipientType.TO));
    if (to != null) {
        System.out.println("To: " + to);
    }

    String subject = message.getSubject();
    if (subject != null) {
        System.out.println("Subject: " + subject);
    }

    Date sent = message.getSentDate();
    if (sent != null) {
        System.out.println("Sent: " + sent);
    }

    // 設(shè)置轉(zhuǎn)發(fā)郵件信息頭
    Message forward = new MimeMessage(session);
    forward.setFrom(new InternetAddress(MAIL_FROM));
    forward.setRecipient(Message.RecipientType.TO, new InternetAddress(MAIL_TO));
    forward.setSubject("Fwd: " + message.getSubject());

    // 設(shè)置轉(zhuǎn)發(fā)郵件內(nèi)容
    MimeBodyPart bodyPart = new MimeBodyPart();
    bodyPart.setContent(message, "message/rfc822");

    Multipart multipart = new MimeMultipart();
    multipart.addBodyPart(bodyPart);
    forward.setContent(multipart);
    forward.saveChanges();

    Transport ts = session.getTransport("smtp");
    ts.connect(USER, PASSWORD);
    ts.sendMessage(forward, forward.getAllRecipients());

    folder.close(false);
    store.close();
    ts.close();
    System.out.println("message forwarded successfully....");
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,698評論 6 539
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,202評論 3 426
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,742評論 0 382
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,580評論 1 316
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 72,297評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,688評論 1 327
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,693評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,875評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,438評論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 41,183評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,384評論 1 372
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,931評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,612評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,022評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,297評論 1 292
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 52,093評論 3 397
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,330評論 2 377

推薦閱讀更多精彩內(nèi)容