<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    posts - 40, comments - 58, trackbacks - 0, articles - 0
      BlogJava :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理

    JavaMail API 簡(jiǎn)介

    Posted on 2008-07-01 13:42 Astro.Qi 閱讀(560) 評(píng)論(1)  編輯  收藏 所屬分類: Java
    1.介紹:

    Java Mail API的開(kāi)發(fā)是SUN為Java開(kāi)發(fā)者提供公用API框架的持續(xù)努力的良好例證。提倡公用框架,反對(duì)受限于供應(yīng)商的解決方案,充分預(yù)示著一個(gè)日益開(kāi)放的開(kāi)發(fā)環(huán)境的建立。
    Java Mail API的結(jié)構(gòu)本身證明了它的開(kāi)發(fā)者的基本目標(biāo)之一--軟件開(kāi)發(fā)的工作量應(yīng)該取決于應(yīng)用程序本身的復(fù)雜程度以及開(kāi)發(fā)者所要求的控制程度。換句話說(shuō),Java Mail API盡可能地保持簡(jiǎn)單。乍看起來(lái),JavaMail API所擁有的類總數(shù)以及類之間的關(guān)系可能讓人誤解為要花費(fèi)漫長(zhǎng)的學(xué)習(xí)時(shí)間。實(shí)際上,一旦正式開(kāi)始使用,你就會(huì)發(fā)現(xiàn)該API不失為在應(yīng)用程序中加入健壯的郵件/通訊支持的簡(jiǎn)單工具。

    在我們步入JavaMail API之前,先看一下API所涉及的協(xié)議。以下便是大家日常所知、所樂(lè)于使用的4大信息傳輸協(xié)議:SMTP POP IMAP MIME NNTP。
    當(dāng)然,上面的4個(gè)協(xié)議,并不是全部,還有NNTP和其它一些協(xié)議可用于傳輸信息,但是由于不常用到,所以本文便不提及了。理解這4個(gè)基本的協(xié)議有助于我們更好的使用JavaMail API。然而JavaMail API是被設(shè)計(jì)為與協(xié)議無(wú)關(guān)的,目前我們并不能克服這些協(xié)議的束縛。確切的說(shuō),如果我們使用的功能并不被我們選擇的協(xié)議支持,那么JavaMail API并不可能如魔術(shù)師一樣神奇的賦予我們這種能力。

    1.SMTP
    簡(jiǎn)單郵件傳輸協(xié)議定義了遞送郵件的機(jī)制。在下文中,我們將使用基于Java-Mail的程序與公司或者ISP的SMTP服務(wù)器進(jìn)行通訊。這個(gè)SMTP服務(wù)器將郵件轉(zhuǎn)發(fā)到接收者的SMTP服務(wù)器,直至最后被接收者通過(guò)POP或者IMAP協(xié)議獲取。這并不需要SMTP服務(wù)器使用支持授權(quán)的郵件轉(zhuǎn)發(fā),但是卻的確要注意SMTP服務(wù)器的正確設(shè)置(SMTP服務(wù)器的設(shè)置與JavaMail API無(wú)關(guān))。

    2.POP
    POP 是一種郵局協(xié)議,目前為第3個(gè)版本,即眾所周知的POP3。POP定義了一種用戶如何獲得郵件的機(jī)制。它規(guī)定了每個(gè)用戶使用一個(gè)單獨(dú)的郵箱。大多數(shù)人在使用POP時(shí)所熟悉的功能并非都被支持,例如查看郵箱中的新郵件數(shù)量。而這個(gè)功能是微軟的Outlook內(nèi)建的,那么就說(shuō)明微軟Outlook之類的郵件客戶端軟件是通過(guò)查詢最近收到的郵件來(lái)計(jì)算新郵件的數(shù)量來(lái)實(shí)現(xiàn)前面所說(shuō)的功能。因此在我們使用JavaMail API時(shí)需要注意,當(dāng)需要獲得如前面所講的新郵件數(shù)量之類的信息時(shí),我們不得不自己進(jìn)行計(jì)算。

    3.IMAP
    IMAP 使用在接收信息的高級(jí)協(xié)議,目前版本為第4版,所以也被稱為IMAP4。需要注意的是在使用IMAP時(shí),郵件服務(wù)器必須支持該協(xié)議。從這個(gè)方面講,我們并不能完全使用IMAP來(lái)替代POP,不能期待IMAP在任何地方都被支持。假如郵件服務(wù)器支持IMAP,那么我們的郵件程序?qū)⒛軌蚓哂幸韵卤籌MAP所支持的特性:每個(gè)用戶在服務(wù)器上可具有多個(gè)目錄,這些目錄能在多個(gè)用戶之間共享。
    其與POP相比高級(jí)之處顯而易見(jiàn),但是在嘗試采取IMAP時(shí),我們認(rèn)識(shí)到它并不是十分完美的:由于IMAP需要從其它服務(wù)器上接收新信息,將這些信息遞送給用戶,維護(hù)每個(gè)用戶的多個(gè)目錄,這都為郵件服務(wù)器帶來(lái)了高負(fù)載。并且IMAP與POP的一個(gè)不同之處是POP用戶在接收郵件時(shí)將從郵件服務(wù)器上下載郵件,而IMAP允許用戶直接訪問(wèn)郵件目錄,所以在郵件服務(wù)器進(jìn)行備份作業(yè)時(shí),由于每個(gè)長(zhǎng)期使用此郵件系統(tǒng)的用戶所用的郵件目錄會(huì)占有很大的空間,這將直接導(dǎo)致郵件服務(wù)器上磁盤空間暴漲。

    4.MIME
    MIME 并不是用于傳送郵件的協(xié)議,它作為多用途郵件的擴(kuò)展定義了郵件內(nèi)容的格式:信息格式、附件格式等等。一些RFC標(biāo)準(zhǔn)都涉及了MIME:RFC 822, RFC 2045, RFC 2046, RFC 2047,有興趣的Matrixer可以閱讀一下。而作為JavaMail API的開(kāi)發(fā)者,我們并不需關(guān)心這些格式定義,但是這些格式被用在了程序中。

    5.NNTP和其它的第三方協(xié)議
    正因?yàn)镴avaMail API在設(shè)計(jì)時(shí)考慮到與第三方協(xié)議實(shí)現(xiàn)提供商之間的分離,故我們可以很容易的添加一些第三方協(xié)議。SUN維護(hù)著一個(gè)第三方協(xié)議實(shí)現(xiàn)提供商的列表:http://java.sun.com/products/javamail/Third_Party.html,通過(guò)此列表我們可以找到所需要的而又不被SUN提供支持的第三方協(xié)議:比如NNTP這個(gè)新聞組協(xié)議和S/MIME這個(gè)安全的MIME協(xié)議。


    2.安裝:

    安裝前要確保你的機(jī)子上安裝得有標(biāo)準(zhǔn)版的JDK和Web服務(wù)器,并且已配置好,有關(guān)它們的安裝方法,請(qǐng)參考其它文章(網(wǎng)上到處都有).

    (1).安裝JavaMail API。現(xiàn)在最常用的 JavaMail API 版本是1.3.
    要使用 JavaMail 1.3 API,請(qǐng)下載 JavaMail 1.3 實(shí)現(xiàn),解開(kāi)Javamail-1_3.zip 文件,并將 mail.jar 文件添加到 CLASSPATH 中。除了核心類,隨版本 1.3 實(shí)現(xiàn)一起提供的還有 SMTP、IMAP4 和 POP3 供應(yīng)商。

    (2).JavaBeans Activation Framework(1.0.2版) 的安裝
    JavaMail API 的所有版本都需要 JavaBeans Activation Framework 來(lái)支持任意數(shù)據(jù)塊的輸入及相應(yīng)處理。功能似乎不多,但目前許多瀏覽器和郵件工具中都能找到這種基本的 MIME 型支持。下載完框架后,解開(kāi) jaf1_0_2.zip 文件,并將 activation.jar 文件添加到 CLASSPATH 中。

    注: 如果您使用的JDK是J2EE,就沒(méi)有什么特定的事非要用基本 JavaMail API來(lái)做不可;J2EE 的類就能處理了,因?yàn)樗旧砭桶蠮avaMail API和JAF,您只需要確將 j2ee.jar 文件添加到您的CLASSPATH 中并已全部設(shè)置好。


    3.JavaMail的常用類介紹

    (1) javax.mail.Properties類
    JavaMail需要Properties來(lái)創(chuàng)建一個(gè)session對(duì)象。它將尋找字符串"mail.smtp.host",屬性值就是發(fā)送郵件的主機(jī).

    用法:
    Properties props = new Properties ();
    props.put("mail.smtp.host", "smtp.163.com");//可以換上你的smtp主機(jī)名。


    (2) javax.mail.Session類
    這個(gè)Session類代表JavaMail 中的一個(gè)郵件session. 每一個(gè)基于 JavaMail的應(yīng)用程序至少有一個(gè)session但是可以有任意多的session。 在這個(gè)例子中, Session對(duì)象需要知道用來(lái)處理郵件的SMTP 服務(wù)器。

    用法:
    Session sendMailSession;
    sendMailSession = Session.getInstance(props, null);


    (3) javax.mail.Transport類
    郵件是既可以被發(fā)送也可以被受到。JavaMail使用了兩個(gè)不同的類來(lái)完成這兩個(gè)功能:Transport 和Store. Transport 是用來(lái)發(fā)送信息的,而Store用來(lái)收信。對(duì)于這的教程我們只需要用到Transport對(duì)象。

    用法:
    Transport transport;
    transport = sendMailSession.getTransport("smtp");

    用JavaMail Session對(duì)象的getTransport 方法來(lái)初始化Transport。傳過(guò)去的字符串申明了對(duì)象所要使用的協(xié)議,如"smtp"。這將為我們省了很多時(shí)間。因?yàn)镴avaMail以境內(nèi)置了很多協(xié)議的實(shí)現(xiàn)方法。

    注意: JavaMail并不是絕對(duì)支持每一個(gè)協(xié)議,目前支持IMAP、 SMTP和 POP3.


    (4) javax.mail.MimeMessage類
    Message對(duì)象將存儲(chǔ)我們實(shí)際發(fā)送的電子郵件信息,Message對(duì)象被作為一個(gè)MimeMessage對(duì)象來(lái)創(chuàng)建并且需要知道應(yīng)當(dāng)選擇哪一個(gè)JavaMail session。

    用法:
    Message newMessage = new MimeMessage(sendMailSession);


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

    用法:
    InternetAddress from=new InternetAddress("xxf@cafe.com");


    (6) javax.mail.Store類
    Store類實(shí)現(xiàn)特定郵件協(xié)議上的讀、寫、監(jiān)視、查找等操作。通過(guò)Javax.mail.Store類可以訪問(wèn)Javax.mail.Folder類。

    用法:
    Store store=session.getSorte("pop3");//session為一個(gè)郵件會(huì)話
    store.connect(pop3server,username,password);//通過(guò)你提供的pop3地址,用戶名和密碼登錄你的郵箱


    (7) javax.mail.Folder類
    Folder類用于分級(jí)組織郵件,并提供照J(rèn)avax.mail.Message格式訪問(wèn)email的能力。

    用法:
    Folder folder=store.getFolder("INBOX");
    folder.open(Folder.READ_ONLY);


    (8) javax.mail.Internet.MimeMultpart
    一般保存電子郵件內(nèi)容的容器是Multipart抽象類,它定義了增加和刪除及獲得電子郵件不同部分內(nèi)容的方法.由于Multipart是抽象類,我們必須為它使用一個(gè)具體的子類,JavaMail API提供javax.mail.Internet.MimeMultpart類來(lái)使用MimeMessage對(duì)象.

    用法:
    MimeMultipart multipart=new MimeMultipart();

    注:我們使用MimeMultipart對(duì)象的一個(gè)方法是addBodyPart(),它在我們的電子郵件內(nèi)容里添加BodyPart(BodyPart類在下面緊接著要介紹)對(duì)象.消息可以有很多部分,一個(gè)BodyPart可以代表一個(gè)部分.


    (9) javax.mail.Internet.MimeBodyPart類

    MimeBodyPart是BodyPart具體用于mimeMessage的一個(gè)子類.
    MimeBodyPart對(duì)象代表一個(gè)MimeMessage對(duì)象內(nèi)容的一部分.每個(gè)MimeBodyPart被認(rèn)為有兩部分:
    ⊙一個(gè)MIME類型
    ⊙匹配這個(gè)類型的內(nèi)容

    用法:
    MimeBodyPart mdp=new MimeBodyPart();
    String text="Hello JavaMail!";
    mdp.setContent(text,"text/plain");//定義MIME類型為text/plain,并設(shè)置MimeBodyPart的內(nèi)容.


    (10) javax.activation.DataHandler類(包含在JAF中)
    JavaMail API不限制信息只為文本,任何形式的信息都可能作繭自縛MimeMessage的一部分.除了文本信息,作為文件附件包含在電子郵件信息的一部分是很普遍的.JavaMail API通過(guò)使用DataHandler對(duì)象,提供一個(gè)允許我們包含非文本BodyPart對(duì)象的簡(jiǎn)便方法.

    用法:
    DataHandler dh=new DataHandler(text,type);
    mdp.setDatahandler(dh);//mdp是一個(gè)MimeBodyPart對(duì)象


    (11) javax.activation.FileDataSource類(包含在JAF中)
    一個(gè)FileDataSource對(duì)象可以表示本地文件和服務(wù)器可以直接訪問(wèn)的資源.一個(gè)本地文件可以通過(guò)創(chuàng)建一個(gè)新的MimeBodyPart對(duì)象附在一個(gè)mimeMessage對(duì)象上.

    用法:
    MimeMultipart mm=new MimeMultipart();
    MimeBodyPart mdp=new MimeBodyPart();
    FileDataSource fds=new FileDataSource("c:/exam.txt");
    mdp.setDataHandler(new DataHandler(fds)); //設(shè)置數(shù)據(jù)源
    mm.addBodyPart(mdp); //為當(dāng)前消息MimeMultipart對(duì)象增加MimeBodyPart


    (12) javax.activation.URLDataSource類(包含在JAF中)
    遠(yuǎn)程資源,URL不會(huì)指向它們,由一個(gè)URLDataSource對(duì)象表示.一個(gè)遠(yuǎn)程資源可以通過(guò)創(chuàng)建一個(gè)新mimeBodyPart對(duì)象附在一個(gè)mimeMessage對(duì)象上(同F(xiàn)ileDataSource差不多).

    用法:
    與FileDataSource唯一不同的是數(shù)據(jù)源的設(shè)置:
    URLDataSource uds=new URLDataSource("/JAVA/UploadFiles_6441/200703/20070320105128501.gif");


    4.使用JavaMail API

    在明確了JavaMail API的核心部分如何工作后,本人將帶領(lǐng)大家學(xué)習(xí)一些使用Java Mail API任務(wù)案例。
    1.發(fā)送郵件
    在獲得了Session后,建立并填入郵件信息,然后發(fā)送它到郵件服務(wù)器。這便是使用Java Mail API發(fā)送郵件的過(guò)程,在發(fā)送郵件之前,我們需要設(shè)置SMTP服務(wù)器:通過(guò)設(shè)置Properties的mail.smtp.host屬性。

    String host = ...;
    String from = ...;
    String to = ...;

    // Get system properties
    Properties props = System.getProperties();

    // Setup mail server
    props.put("mail.smtp.host", host);

    // Get session
    Session session = Session.getDefaultInstance(props, null);

    // Define message
    MimeMessage message = new MimeMessage(session);
    message.setFrom(new InternetAddress(from));
    message.addRecipient(Message.RecipientType.TO, new InternetAddress(to));
    message.setSubject("Hello JavaMail");
    message.setText("Welcome to JavaMail");

    // Send message
    Transport.send(message);
    由于建立郵件信息和發(fā)送郵件的過(guò)程中可能會(huì)拋出異常,所以我們需要將上面的代碼放入到try-catch結(jié)構(gòu)塊中。

    2.接收郵件
    為了在讀取郵件,我們獲得了session,并且連接到了郵箱的相應(yīng)store,打開(kāi)相應(yīng)的Folder,然后得到我們想要的郵件,當(dāng)然別忘記了在結(jié)束時(shí)關(guān)閉連接。

    String host = ...;
    String username = ...;
    String password = ...;

    // Create empty properties
    Properties props = new Properties();

    // Get session
    Session session = Session.getDefaultInstance(props, null);

    // Get the store
    Store store = session.getStore("pop3");
    store.connect(host, username, password);

    // Get folder
    Folder folder = store.getFolder("INBOX");
    folder.open(Folder.READ_ONLY);

    // Get directory
    Message message[] = folder.getMessages();
    for (int i=0, n=message.length; i<n; i++) {     
      System.out.println(i + ": " +
      message[i].getFrom()[0] + "\t" + message[i].getSubject());
    }

    // Close connection
    folder.close(false);store.close();

    上面的代碼所作的是從郵箱中讀取每個(gè)郵件,并且顯示郵件的發(fā)信人地址和主題。從技術(shù)角度講,這里存在著一個(gè)異常的可能:當(dāng)發(fā)信人地址為空時(shí),getFrom()[0]將拋出異常。

    下面的代碼片斷有效的說(shuō)明了如何讀取郵件內(nèi)容,在顯示每個(gè)郵件發(fā)信人和主題后,將出現(xiàn)用戶提示從而得到用戶是否讀取該郵件的確認(rèn),如果輸入YES的話,我們可用Message.writeTo(java.io.OutputStream os)方法將郵件內(nèi)容輸出到控制臺(tái)上,關(guān)于 Message.writeTo()的具體用法請(qǐng)看JavaMail API。

    BufferedReader reader = new BufferedReader (new InputStreamReader(System.in));

    // Get directory
    Message message[] = folder.getMessages();
    for (int i=0, n=message.length; i<n; i++) {
      System.out.println(i + ": " + message[i].getFrom()[0] + "\t" + message[i].getSubject());
      System.out.println("Do you want to read message? " + "[YES to read/QUIT to end]"); 
      String line = reader.readLine();
      if ("YES".equals(line)) {
        message[i].writeTo(System.out); 
      } else if ("QUIT".equals(line)) {
        break; 
      }
    }

    3.刪除郵件和標(biāo)志
    設(shè)置與message相關(guān)的Flags是刪除郵件的常用方法。這些Flags表示了一些系統(tǒng)定義和用戶定義的不同狀態(tài)。在Flags類的內(nèi)部類Flag中預(yù)定義了一些標(biāo)志:
    Flags.Flag.ANSWERED
    Flags.Flag.DELETED
    Flags.Flag.DRAFT
    Flags.Flag.FLAGGED
    Flags.Flag.RECENT
    Flags.Flag.SEEN
    Flags.Flag.USER
    但需要在使用時(shí)注意的:標(biāo)志存在并非意味著這個(gè)標(biāo)志被所有的郵件服務(wù)器所支持。例如,對(duì)于刪除郵件的操作,POP協(xié)議不支持上面的任何一個(gè)。所以要確定哪些標(biāo)志是被支持的??通過(guò)訪問(wèn)一個(gè)已經(jīng)打開(kāi)的Folder對(duì)象的getPermanetFlags()方法,它將返回當(dāng)前被支持的Flags類對(duì)象。

    刪除郵件時(shí),我們可以設(shè)置郵件的DELETED標(biāo)志: 
    message.setFlag(Flags.Flag.DELETED, true);

    但是首先要采用READ_WRITE的方式打開(kāi)Folder:
    folder.open(Folder.READ_WRITE);

    在對(duì)郵件進(jìn)行刪除操作后關(guān)閉Folder時(shí),需要傳遞一個(gè)true作為對(duì)刪除郵件的擦除確認(rèn)。
    folder.close(true);

    Folder類中另一種用于刪除郵件的方法expunge()也同樣可刪除郵件,但是它并不為sun提供的POP3實(shí)現(xiàn)支持,而其它第三方提供的POP3實(shí)現(xiàn)支持或者并不支持這種方法。
    另外,介紹一種檢查某個(gè)標(biāo)志是否被設(shè)置的方法:Message.isSet(Flags.Flag flag)方法,其中參數(shù)為被檢查的標(biāo)志。

    4.郵件認(rèn)證
    我們?cè)谇懊嬉呀?jīng)學(xué)會(huì)了如何使用Authenticator類來(lái)代替直接使用用戶名和密碼這兩字符串作為 Session.getDefaultInstance()或者Session.getInstance()方法的參數(shù)。在前面的小試牛刀后,現(xiàn)在我們將

    了解到全面認(rèn)識(shí)一下郵件認(rèn)證。
    我們?cè)诖巳〈酥苯邮褂绵]件服務(wù)器主機(jī)名、用戶名、密碼這三個(gè)字符串作為連接到POP3 Store的方式,使用存儲(chǔ)了郵件服務(wù)器主機(jī)名信息的屬性文件,并在獲得Session時(shí)傳入自定義的Authenticator實(shí)例:

    // Setup properties
    Properties props = System.getProperties();
    props.put("mail.pop3.host", host);

    // Setup authentication, get session
    Authenticator auth = new PopupAuthenticator();
    Session session = Session.getDefaultInstance(props, auth);

    // Get the storeStore store = session.getStore("pop3");
    store.connect();

    PopupAuthenticator 類繼承了抽象類Authenticator,并且通過(guò)重載Authenticator類的getPasswordAuthentication()方法返回PasswordAuthentication類對(duì)象。而getPasswordAuthentication()方法的參數(shù)param是以逗號(hào)分割的用戶名、密碼組成的字符串。

    import javax.mail.*;
    import java.util.*;
    public class PopupAuthenticator extends Authenticator { 
    public PasswordAuthentication getPasswordAuthentication(String param) {
        String username, password;   
        StringTokenizer st = new StringTokenizer(param, ",");
        username = st.nextToken();
        password = st.nextToken();
        return new PasswordAuthentication(username, password);
      }
    }

    5.回復(fù)郵件
    回復(fù)郵件的方法很簡(jiǎn)單:使用Message類的reply()方法,通過(guò)配置回復(fù)郵件的收件人地址和主題(如果沒(méi)有提供主題的話,系統(tǒng)將默認(rèn)將“Re:”作為郵件的主體),這里不需要設(shè)置任何的郵件內(nèi)容,只要復(fù)制發(fā)信人或者reply-to到新的收件人。而reply()方法中的boolean參數(shù)表示是否將郵件回復(fù)給發(fā)送者(參數(shù)值為false),或是恢復(fù)給所有人(參數(shù)值為true)。
    補(bǔ)充一下,reply-to地址需要在發(fā)信時(shí)使用setReplyTo()方法設(shè)置。

    MimeMessage reply = (MimeMessage)message.reply(false);
    reply.setFrom(new InternetAddress("president@whitehouse.gov"));
    reply.setText("Thanks");
    Transport.send(reply);

    6.轉(zhuǎn)發(fā)郵件
    轉(zhuǎn)發(fā)郵件的過(guò)程不如前面的回復(fù)郵件那樣簡(jiǎn)單,它將建立一個(gè)轉(zhuǎn)發(fā)郵件,這并非一個(gè)方法就能做到。
    每個(gè)郵件是由多個(gè)部分組成,每個(gè)部分稱為一個(gè)郵件體部分,是一個(gè)BodyPart類對(duì)象,對(duì)于MIME類型郵件來(lái)講就是MimeBodyPart類對(duì)象。這些郵件體包含在成為Multipart的容器中對(duì)于MIME類型郵件來(lái)講就是MimeMultiPart類對(duì)象。在轉(zhuǎn)發(fā)郵件時(shí),我們建立一個(gè)文字郵件體部分和一個(gè)被轉(zhuǎn)發(fā)的文字郵件體部分,然后將這兩個(gè)郵件體放到一個(gè)Multipart中。說(shuō)明一下,復(fù)制一個(gè)郵件內(nèi)容到另一個(gè)郵件的方法是僅復(fù)制它的 DataHandler(數(shù)據(jù)處理者)即可。這是由JavaBeans Activation Framework定義的一個(gè)類,它提供了對(duì)郵件內(nèi)容的操作命令的訪問(wèn)、管理了郵件內(nèi)容操作,是不同的數(shù)據(jù)源和數(shù)據(jù)格式之間的一致性接口。

    // Create the message to forward
    Message forward = new MimeMessage(session);

    // Fill in headerforward.setSubject("Fwd: " + message.getSubject());
    forward.setFrom(new InternetAddress(from));
    forward.addRecipient(Message.RecipientType.TO,   new InternetAddress(to));

    // Create your new message part
    BodyPart messageBodyPart = new MimeBodyPart();
    messageBodyPart.setText(  "Here you go with the original message:\n\n");

    // Create a multi-part to combine the parts
    Multipart multipart = new MimeMultipart();
    multipart.addBodyPart(messageBodyPart);

    // Create and fill part for the forwarded contentmessage
    BodyPart = new MimeBodyPart();
    messageBodyPart.setDataHandler(message.getDataHandler());

    // Add part to multi part
    multipart.addBodyPart(messageBodyPart);

    // Associate multi-part with message
    forward.setContent(multipart);

    // Send message
    Transport.send(forward);

    7.使用附件
    附件作為與郵件相關(guān)的資源經(jīng)常以文本、表格、圖片等格式出現(xiàn),如流行的郵件客戶端一樣,我們可以用JavaMail API從郵件中獲取附件或是發(fā)送帶有附件的郵件。

    A.發(fā)送帶有附件的郵件
    發(fā)送帶有附件的郵件的過(guò)程有些類似轉(zhuǎn)發(fā)郵件,我們需要建立一個(gè)完整郵件的各個(gè)郵件體部分,在第一個(gè)部分(即我們的郵件內(nèi)容文字)后,增加一個(gè)具有DataHandler的附件而不是在轉(zhuǎn)發(fā)郵件時(shí)那樣復(fù)制第一個(gè)部分的DataHandler。

    如果我們將文件作為附件發(fā)送,那么要建立FileDataSource類型的對(duì)象作為附件數(shù)據(jù)源;如果從URL讀取數(shù)據(jù)作為附件發(fā)送,那么將要建立URLDataSource類型的對(duì)象作為附件數(shù)據(jù)源。

    然后將這個(gè)數(shù)據(jù)源(FileDataSource或是URLDataSource)對(duì)象作為DataHandler類構(gòu)造方法的參數(shù)傳入,從而建立一個(gè)DataHandler對(duì)象作為數(shù)據(jù)源的DataHandler。

    接著將這個(gè)DataHandler設(shè)置為郵件體部分的DataHandler。這樣就完成了郵件體與附件之間的關(guān)聯(lián)工作,下面的工作就是BodyPart的setFileName()方法設(shè)置附件名為原文件名。

    最后將兩個(gè)郵件體放入到Multipart中,設(shè)置郵件內(nèi)容為這個(gè)容器Multipart,發(fā)送郵件。

    // Define message
    Message message = new MimeMessage(session);
    message.setFrom(new InternetAddress(from));
    message.addRecipient(Message.RecipientType.TO, new InternetAddress(to));
    message.setSubject("Hello JavaMail Attachment");

    // Create the message part BodyPart message
    BodyPart = new MimeBodyPart();

    // Fill the message
    messageBodyPart.setText("Pardon Ideas");
    Multipart multipart = new MimeMultipart();
    multipart.addBodyPart(messageBodyPart);

    // Part two is attachment
    messageBodyPart = new MimeBodyPart();
    DataSource source = new FileDataSource(filename);
    messageBodyPart.setDataHandler(new DataHandler(source));
    messageBodyPart.setFileName(filename);
    multipart.addBodyPart(messageBodyPart);

    // Put parts in message
    message.setContent(multipart);

    // Send the message
    Transport.send(message);

    如果我們使用servlet實(shí)現(xiàn)發(fā)送帶有附件的郵件,則必須上傳附件給servlet,這時(shí)需要注意提交頁(yè)面form中對(duì)編碼類型的設(shè)置應(yīng)為multipart/form-data。

    <FORM ENCTYPE="multipart/form-data" method="post" action="/myservlet">
       <INPUT TYPE="file" NAME="thefile">
      <INPUT TYPE="submit" VALUE="Upload">
    </FORM>

    B.讀取郵件中的附件
    讀取郵件中的附件的過(guò)程要比發(fā)送它的過(guò)程復(fù)雜一點(diǎn)。因?yàn)閹в懈郊泥]件是多部分組成的,我們必須處理每一個(gè)部分獲得郵件的內(nèi)容和附件。
    但是如何辨別郵件信息內(nèi)容和附件呢?Sun在Part類(BodyPart類實(shí)現(xiàn)的接口類)中提供了getDisposition()方法讓開(kāi)發(fā)者獲得郵件體部分的部署類型,當(dāng)該部分是附件時(shí),其返回之將是Part.ATTACHMENT。但附件也可以沒(méi)有部署類型的方式存在或者部署類型為 Part.INLINE,無(wú)論部署類型為Part.ATTACHMENT還是Part.INLINE,我們都能把該郵件體部分導(dǎo)出保存。

    Multipart mp = (Multipart)message.getContent();
    for (int i=0, n=multipart.getCount(); i<n; i++) {
      Part part = multipart.getBodyPart(i));
      String disposition = part.getDisposition();
      if ((disposition != null) &&
           ((disposition.equals(Part.ATTACHMENT) ||
            (disposition.equals(Part.INLINE))) {
        saveFile(part.getFileName(), part.getInputStream());
      }
    }

    下列代碼中使用了saveFile方法是自定義的方法,它根據(jù)附件的文件名建立一個(gè)文件,如果本地磁盤上存在名為附件的文件,那么將在文件名后增加數(shù)字表示區(qū)別。然后從郵件體中讀取數(shù)據(jù)寫入到本地文件中(代碼省略)。

    // from saveFile()
    File file = new File(filename);
    for (int i=0; file.exists(); i++) {
      file = new File(filename+i);
    }

    以上是郵件體部分被正確設(shè)置的簡(jiǎn)單例子,如果郵件體部分的部署類型為null,那么我們通過(guò)獲得郵件體部分的MIME類型來(lái)判斷其類型作相應(yīng)的處理,代碼結(jié)構(gòu)框架如下:

    if (disposition == null) {
      // Check if plain 
      MimeBodyPart mbp = (MimeBodyPart)part;
      if (mbp.isMimeType("text/plain")) {
        // Handle plain
      } else {
        // Special non-attachment cases here of
        // image/gif, text/html
        ...
      }
      ...
    }

    8.處理HTML郵件
    前面的例子中發(fā)送的郵件都是以文本為內(nèi)容的(除了附件),下面將介紹如何接收和發(fā)送基于HTML的郵件。
    A.發(fā)送HTML郵件
    假如我們需要發(fā)送一個(gè)HTML文件作為郵件內(nèi)容,并使郵件客戶端在讀取郵件時(shí)獲取相關(guān)的圖片或者文字的話,只要設(shè)置郵件內(nèi)容為html代碼,并設(shè)置內(nèi)容類型為text/html即可:

    String htmlText = "<H1>Hello</H1>" + "<img src=\"http://www.jguru.com/images/logo.gif\">";
    message.setContent(htmlText, "text/html"));

    請(qǐng)注意:這里的圖片并不是在郵件中內(nèi)嵌的,而是在URL中定義的。郵件接收者只有在線時(shí)才能看到。
    在接收郵件時(shí),如果我們使用JavaMail API接收郵件的話是無(wú)法實(shí)現(xiàn)以HTML方式顯示郵件內(nèi)容的。因?yàn)镴avaMail API郵件內(nèi)容視為二進(jìn)制流。所以要顯示HTML內(nèi)容的郵件,我們必須使用JEditorPane或者第三方HTML展現(xiàn)組件。

    以下代碼顯示了如何使用JEditorPane顯示郵件內(nèi)容:
    if (message.getContentType().equals("text/html")) {
      String content = (String)message.getContent();
      JFrame frame = new JFrame();
      JEditorPane text = new JEditorPane("text/html", content);
      text.setEditable(false);
      JScrollPane pane = new JScrollPane(text);
      frame.getContentPane().add(pane);
      frame.setSize(300, 300);
      frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
      frame.show();
    }

    B.在郵件中包含圖片
    如果我們?cè)卩]件中使用HTML作為內(nèi)容,那么最好將HTML中使用的圖片作為郵件的一部分,這樣無(wú)論是否在線都會(huì)正確的顯示HTML中的圖片。處理方法就是將HTML中用到的圖片作為郵件附件并使用特殊的cid URL作為圖片的引用,這個(gè)cid就是對(duì)圖片附件的Content-ID頭的引用。
    處理內(nèi)嵌圖片就像向郵件中添加附件一樣,不同之處在于我們必須通過(guò)設(shè)置圖片附件所在的郵件體部分的header中Content-ID為一個(gè)隨機(jī)字符串,并在HTML中img的src標(biāo)記中設(shè)置為該字符串。這樣就完成了圖片附件與HTML的關(guān)聯(lián)。

    String file = ...;
    // Create the message
    Message message = new MimeMessage(session);

    // Fill its headers
    message.setSubject("Embedded Image");
    message.setFrom(new InternetAddress(from));
    message.addRecipient(Message.RecipientType.TO, new InternetAddress(to));

    // Create your new message part
    BodyPart messageBodyPart = new MimeBodyPart();
    String htmlText = "<H1>Hello</H1>" + "<img src=\"cid:memememe\">";
    messageBodyPart.setContent(htmlText, "text/html");

    // Create a related multi-part to combine the parts
    MimeMultipart multipart = new MimeMultipart("related");
    multipart.addBodyPart(messageBodyPart);

    // Create part for the image
    messageBodyPart = new MimeBodyPart();

    // Fetch the image and associate to part
    DataSource fds = new FileDataSource(file);
    messageBodyPart.setDataHandler(new DataHandler(fds));
    messageBodyPart.setHeader("Content-ID","<memememe>");

    // Add part to multi-part
    multipart.addBodyPart(messageBodyPart);

    // Associate multi-part with
    messagemessage.setContent(multipart);

    9.在郵件中搜索短語(yǔ)
    JavaMail API提供了過(guò)濾器機(jī)制,它被用來(lái)建立搜索短語(yǔ)。這個(gè)短語(yǔ)由javax.mail.search包中的SearchTerm抽象類來(lái)定義,在定義后我們便可以使用Folder的Search()方法在Folder中查找郵件:
    SearchTerm st = ...;Message[] msgs = folder.search(st);
    下面有22個(gè)不同的類(繼承了SearchTerm類)供我們使用:
    AND       terms (class AndTerm)
    OR        terms (class OrTerm)
    NOT       terms (class NotTerm)
    SENT DATE terms (class SentDateTerm)
    CONTENT   terms (class BodyTerm)
    HEADER    terms (FromTerm / FromStringTerm,
                     RecipientTerm / RecipientStringTerm, SubjectTerm, etc.)
    使用這些類定義的斷語(yǔ)集合,我們可以構(gòu)造一個(gè)邏輯表達(dá)式,并在Folder中進(jìn)行搜索。下面是一個(gè)實(shí)例:在Folder中搜索郵件主題含有“ADV”字符串或者發(fā)信人地址為friend@public.com的郵件。

    SearchTerm st = new OrTerm(new SubjectTerm("ADV:"), new FromStringTerm("friend@public.com"));
    Message[] msgs = folder.search(st);

    評(píng)論

    # re: JavaMail API 簡(jiǎn)介  回復(fù)  更多評(píng)論   

    2008-12-25 13:47 by ylan
    這文檔對(duì)我?guī)椭艽螅躋Q聯(lián)系嗎,我的QQ:65710624
    主站蜘蛛池模板: 在线观看永久免费视频网站| 成年女人A毛片免费视频| 吃奶摸下高潮60分钟免费视频| 免费a级毛片无码a∨免费软件 | 亚洲国产精品午夜电影| 亚洲高清视频一视频二视频三| 88av免费观看入口在线| 男女啪啪免费体验区| 在线观看日本亚洲一区| 亚洲av色影在线| 亚洲午夜福利精品久久| 白白国产永久免费视频| 在线观看免费人成视频| 毛片在线播放免费观看| 特级毛片全部免费播放| 亚洲一卡2卡3卡4卡5卡6卡| 亚洲视频在线观看免费视频| 久久伊人久久亚洲综合| 久久精品国产亚洲av麻| 亚洲无线观看国产精品| 亚洲一区二区三区影院 | 美女羞羞免费视频网站| 在线观看国产一区亚洲bd| 亚洲欧美日韩综合久久久久| 久久久国产亚洲精品| 亚洲欧美成aⅴ人在线观看| 亚洲一区在线免费观看| 亚洲美国产亚洲AV| 国产精品亚洲色婷婷99久久精品| 美女视频黄.免费网址| 中文字幕在线视频免费| 97免费人妻无码视频| 国产一精品一AV一免费孕妇| 午夜国产羞羞视频免费网站| 亚洲人成色77777在线观看大| 亚洲国产精品无码成人片久久| 日韩亚洲Av人人夜夜澡人人爽| 亚洲日本在线电影| xxxxxx日本处大片免费看| jjizz全部免费看片| 亚洲av无码成人精品区在线播放 |