JAVA涂鴉
          關(guān)于JAVA的點(diǎn)點(diǎn)滴滴
          posts - 50,  comments - 689,  trackbacks - 0

          聲明,本文轉(zhuǎn)載自 narilee Blog

          JavaMail API
          簡介
          JavaMail API
          是一種可選的、能用于讀取、編寫和發(fā)送電子消息的包(標(biāo)準(zhǔn)擴(kuò)展)。您可使用這種包創(chuàng)建郵件用戶代理(Mail User Agent MUA) 類型的程序,它類似于EudoraPineMicrosoft Outlook這些郵件程序。其主要目的不是像發(fā)送郵件或其他郵件傳輸代理(Mail Transfer AgentMTA)類型的程序那樣用于傳輸、發(fā)送和轉(zhuǎn)發(fā)消息。換句話說,用戶可以與MUA類型的程序交互,以閱讀和撰寫電子郵件。MUA依靠MTA處理 實(shí)際的發(fā)送任務(wù)。
          JavaMail API
          的設(shè)計(jì)是,為收發(fā)信息提供與協(xié)議無關(guān)的訪問。方式是把該API劃分成兩個(gè)部分:
          ·
          API的第一個(gè)部分是本課程的重點(diǎn)。基本上是如何發(fā)送和接收獨(dú)立于提供程序/協(xié)議的消息。
          ·
          第二個(gè)部分則使用特定的協(xié)議語言,如:SMTPPOPIMAPNNTP。如果要讓JavaMail API與服務(wù)器通信,就需要為之提供協(xié)議。由于Sun公司對特定協(xié)議提供程序有充分的介紹,用戶可以免費(fèi)獲取,所以本課程沒有介紹創(chuàng)建特定協(xié)議提供程序的內(nèi)容。
          復(fù)習(xí)相關(guān)協(xié)議
          在學(xué)習(xí)JavaMail API的深層知識之前,讓我們回過頭來看一看在該API中使用的協(xié)議,本質(zhì)上有4種人們常用的協(xié)議:
          · SMTP
          · POP
          · IMAP
          · MIME

          您 還需要了解NNTP及其他一些協(xié)議。理解這些協(xié)議的基本原理有助于您理解如何使用JavaMail API。而該API的設(shè)計(jì)要與協(xié)議無關(guān),所以不能克服這些基礎(chǔ)協(xié)議的限制。如果選用的協(xié)議不支持某種功能,那么JavaMail API也無法在其上添加這種功能。(正如您一會兒就會看到的,在操作POP協(xié)議時(shí),常常會碰到這種問題)。
          SMTP
          簡單郵件傳輸協(xié)議 (SMTP)是用于傳送電子郵件的機(jī)制。在JavaMail API環(huán)境中,您的基于JavaMail的程序?qū)⑴c您公司或Internet服務(wù)提供商(ISP)的SMTP服務(wù)器通信。該SMTP服務(wù)器將會把消息轉(zhuǎn)發(fā) 給用作接收消息的SMTP服務(wù)器,最后用戶可通過POPIMAP協(xié)議獲取該消息。由于支持身份驗(yàn)證,所以不需要SMTP服務(wù)器是一種開放的轉(zhuǎn)發(fā)器,但需 要確保SMTP服務(wù)器配置正確。JavaMail API中沒有集成用于處理諸如配置服務(wù)器以轉(zhuǎn)發(fā)消息或添加/刪除電子郵件帳戶這一類任務(wù)的功能。
          POP
          POP
          的含義是郵局協(xié)議,當(dāng)前的版本為3,也稱作POP3,該協(xié)議是在RFC 1939中定義的。POPInternet上的大多數(shù)人用來接收郵件的機(jī)制。它為每個(gè)用戶的每個(gè)郵箱定義支持,這是它所做的全部工作,也是大多數(shù)問題的 根源。在使用POP協(xié)議時(shí),人們熟悉的很多功能,如查看收到了多少新郵件消息的功能,POP根本不支持。這些功能都內(nèi)置到諸如Eudora Microsoft Outlook之類的郵件程序中,能為您記住接收的上一封郵件,以及計(jì)算有多少新郵件這類信息。因此,使用JavaMail API時(shí),如果想獲取這類信息,將需要由自己進(jìn)行計(jì)算。
          IMAP
          IMAP
          是用于接收消息的更加高級的協(xié)議,它是在RFC 2060中定義的。IMAP的含義是“Internet消息訪問協(xié)議,當(dāng)前版本是第4版,也稱作IMAP4。使用IMAP時(shí),您的郵件服務(wù)器必須支持該 協(xié)議。您不能只是簡單地把程序轉(zhuǎn)變?yōu)橹С?span lang="EN-US">IMAP,而不是支持POP,就指望能支持IMAP中的一切。假定您的郵件服務(wù)器支持IMAP,那么基于 JavaMail的程序就可利用在服務(wù)器上擁有多個(gè)文件夾的用戶,并且這些文件夾可以被多個(gè)用戶共享的功能。
          由于IMAP協(xié)議具有更高級的功能, 您也許會想IMAP應(yīng)該被每一個(gè)人使用,但事實(shí)不是這樣。因?yàn)?span lang="EN-US">IMAP會加重郵件服務(wù)器的負(fù)荷,它需要服務(wù)器接收新消息,發(fā)送消息給請求的用戶,并在多個(gè) 文件夾中為每個(gè)用戶維護(hù)這些消息。而這要集中備份,因而長期下去用戶的文件夾會變得越來越大,當(dāng)磁盤空間用光了時(shí),每個(gè)人都會遭受損失。而使用POP協(xié)議 時(shí),已保存消息可以解除服務(wù)器的重負(fù)。
          MIME
          MIME
          的含義是多用途的網(wǎng)際郵件擴(kuò)充協(xié)議。它不是一種郵件傳輸協(xié)議,相反,它定義傳 輸?shù)膬?nèi)容:消息的格式、附件等。許多文檔都定義了MIME協(xié)議,包含:RFC 822RFC 2045RFC 2046RFC 2047。作為JavaMail API的用戶,一般不需要擔(dān)心這些格式。但是,這些格式確實(shí)存在,并為您的程序所用。
          NNP
          和其他協(xié)議
          由 于JavaMail API分開了提供程序和其他部分,所以您可以輕松地為附加協(xié)議添加支持。Sun公司提供第3方提供程序清單,這些提供程序要利用 Sun公司不支持的少見的協(xié)議。在這份清單中,您將會看到對NNTP(網(wǎng)絡(luò)新聞傳輸協(xié)議)[新聞組]S/MIME(安全多用途的網(wǎng)際郵件擴(kuò)充協(xié)議)及其 他協(xié)議的提供支持的第3方提供程序。
          安裝
          目前有兩種版本的JavaMail API最常用:1.21.1.3。本課程中的所有例子都適用于這兩種版本。其中JavaMail API 1.2是最新的,而JavaMail API 1.1.3中包含了Java 2企業(yè)版(J2EE)平臺1.2.1版,所以它仍然很常用。使用JavaMail API的版本會對您的下載和安裝產(chǎn)生一些影響。這兩種版本的JavaMail API都能與JDK 1.1.6Java 2標(biāo)準(zhǔn)版(J2SE)平臺1.2.x1.3.x協(xié)同工作。
          注意:在安裝了Sun公司的JavaMail工具后,會在演示目錄下看到許多示例程序。
          安裝JavaMail 1.2
          要使用JavaMail 1.2 API,可以下載JavaMail 1.2工具,然后解壓縮javamail-1_2.zip文件,并把mail.jar文件添加到典型安裝路徑下。JavaMail 1.2工具帶有SMTPIMAP4POP3提供程序以及核心類。
          安裝完JavaMail 1.2后,再安裝JavaBeans Activation Framework
          安裝JavaMail 1.1.3
          要 使用JavaMail 1.1.3 API,可以下載JavaMail 1.1.3工具,然后解壓縮javamail1_1_3.zip文件,并把mail.jar文件添加到典型安裝路徑下。JavaMail 1.1.3工具帶有SMTPIMAP4提供程序以及核心類。
          如果您想用JavaMail 1.1.3訪問POP服務(wù)器,需要下載并安裝POP3提供程序。Sun公司擁有一個(gè)獨(dú)立于 JavaMail 工具的提供程序。在下載并解壓縮pop31_1_1.zip文件后,也還需要把pop3.jar添加到典型安裝路徑下。
          安裝完JavaMail 1.1.3后,再安裝JavaBeans Activation Framework
          安裝JavaBeans Activation Framework
          JavaMail API
          的所有版本都需要JavaBeans Activation FrameworkJavaBeans激活框架),這種框架提供了對輸入任意數(shù)據(jù)塊的支持,并能相應(yīng)地對其進(jìn)行處理。看上去效果好像不太好,但該框架是 在當(dāng)今的許多瀏覽器和郵件工具中可以找到的基本MIME類型支持。下載該框架后,解壓縮jaf1_0_1.zip文件,并將activation.jar 文件添加到典型安裝路徑下。
          對于JavaMail 1.2用戶,現(xiàn)在應(yīng)該把mail.jaractivation.jar文件添加到典型安裝路徑下。
          對于JavaMail 1.1.3用戶,現(xiàn)在應(yīng)該把mail.jarpop3.jaractivation.jar添加到典型安裝路徑下。如果您不打算使用POP3,就不需要把pop3.jar文件添加到典型安裝路徑下。
          如果您不想更改安裝路徑環(huán)境變量,可以把JAR文件復(fù)制到Java運(yùn)行時(shí)環(huán)境(JRE)目錄下的lib/ext目錄下。例如,對于J2SE 1.3版本,Windows平臺上的默認(rèn)目錄應(yīng)該是C:\jdk1.3\jre\lib\ext
          使用Java 2企業(yè)版
          如果您使用的是J2EE,則在使用基本JavaMail API時(shí),不需要做什么特殊的工作;JavaMail API帶有J2EE類。只要確保j2ee.jar文件位于典型安裝路徑下,并完成了所有的設(shè)置工作。
          對 于J2EE 1.2.1POP3提供程序是單獨(dú)提供的,因此需要下載該提供程序,并按安裝JavaMail 1.1.3的步驟,在J2EE 1.2.1中包含POP3提供程序。J2EE 1.3的用戶會獲得J2EEPOP3提供程序,因而不需要對POP3提供程序執(zhí)行獨(dú)立安裝。使用這兩種版本的J2EE用戶,都不需要安裝 JavaBeans Activation Framework
          練習(xí)
          設(shè)置您的 JavaMail 環(huán)境。
          復(fù)習(xí)核心類
          在 開始深入研究JavaMail類之前,首先讓用戶瀏覽一下構(gòu)成API的核心類:會話、消息、地址、驗(yàn)證程序、傳輸,存儲和文件夾。所有這些類都可以在 JavaMail APIjavax.mail的頂層包中找到,盡管您將頻繁地發(fā)現(xiàn)您自己使用的子類是在javax.mail.internet包中找到的。
          Session

          Session
          類定義了一個(gè)基本的郵件會話。通過該會話可讓別的工作順利執(zhí)行。Session對象利用java.util.Properties對象獲取諸如郵件服務(wù)器、用戶名、密碼等信息,以及其他可在整個(gè)應(yīng)用程序中共享的信息。
          Session
          類的構(gòu)造器是私有的。您可以獲得一個(gè)可被getDefaultInstance()方法共享的單一的默認(rèn)會話:
          Properties props = new Properties();
          // fill props with any information
          Session session = Session.getDefaultInstance(props, null);
          或者,您可以用getInstance()方法創(chuàng)建一個(gè)獨(dú)特的會話:
          Properties props = new Properties();
          // fill props with any information
          Session session = Session.getInstance(props, null);
          這兩種情形下的null參數(shù)都是一種Authenticator對象,它不是在此時(shí)使用的。詳細(xì)信息請參閱其后的“Autherticator”一節(jié)。
          在大多數(shù)情況下,使用共享會話就足夠了,即使為多個(gè)用戶郵箱處理郵件會話也是如此。您可以在通信過程的后面一步添加上用戶名和密碼的組合,并保持所有的一切是獨(dú)立的。
          Message

          一 旦創(chuàng)建了自己的Session對象,就是該去創(chuàng)建要發(fā)送的消息的時(shí)候了。這時(shí)就要用到消息類型。作為一個(gè)抽象類,您必須操作一個(gè)子類,在大多數(shù)情況下,該 子類是javax.mail.internet.MimeMessage。一個(gè)MimeMessage是一種理解MIME類型和報(bào)頭(在不同的RFC文檔 中均有定義)的消息。消息的報(bào)頭被嚴(yán)格限制成只能使用US-ASCII字符,盡管非ASCII字符可以被編碼到某些報(bào)頭字段中。
          可以通過將Session對象傳遞給MimeMessage構(gòu)造器的方法來創(chuàng)建消息:
          MimeMessage message = new MimeMessage(session);
          注意:還有其他的構(gòu)造器,像用于創(chuàng)建消息的源于RFC822格式化的輸入流的構(gòu)造器。
          一旦創(chuàng)建了消息,就可以設(shè)置其各個(gè)部分,如Message(消息)實(shí)現(xiàn)Part(部分)接口(以MimeMessage實(shí)現(xiàn)MimePart)。設(shè)置內(nèi)容的基本機(jī)制是setContent()方法,它帶有表示內(nèi)容和MIME類型的參數(shù):
          message.setContent("Hello", "text/plain");
          但是,如果正在使用 MimeMessage,并且您的消息是純文本,那么您就可以使用setText()方法。該方法只需要一個(gè)表示實(shí)際內(nèi)容的參數(shù),默認(rèn)的MIME類型為純文本:
          message.setText("Hello");
          對于純文本消息,setText()方法更常常被用來設(shè)置內(nèi)容。要發(fā)送其他類型的消息,如HTML消息,就要使用setContent方法()。現(xiàn)在用的更多的是HTML消息。
          要設(shè)置主題,可以使用setSubject()方法:
          message.setSubject("First");
          Address

          一旦創(chuàng)建了會話和消息,并為消息填充了內(nèi)容,就需要用Address類為您的信件標(biāo)上地址了。同Message類一樣,Address類也是一種抽象類。您可以使用javax.mail.internet.InternetAddress類。
          要?jiǎng)?chuàng)建只帶有電子郵件地址的地址,可以把電子郵件地址傳遞給Address類的構(gòu)造器:
          Address address = new InternetAddress("president@whitehouse.gov");
          如果想讓一個(gè)名字出現(xiàn)在電子郵件地址后,也可以將其傳遞給構(gòu)造器:
          Address address = new InternetAddress("president@whitehouse.gov", "George Bush");
          您要為消息的from(發(fā)送者)字段和to(接收者)字段創(chuàng)建地址對象。除非您的郵件服務(wù)器阻止這樣做,否則要在發(fā)送的消息中注明該消息的發(fā)送者。
          一旦創(chuàng)建好了地址,有兩種方法可讓您將地址與消息連接起來。為了鑒別發(fā)送者,您可以使用setFrom()setReplyTo()方法。
          message.setFrom(address)
          如果您的消息需要顯示多個(gè)地址來源,則可以使用addFrom()方法:
          Address address[] = ...;
          message.addFrom(address);
          為了鑒別消息接收者,您可以使用addRecipient()方法。該方法除了需要一個(gè)地址參數(shù)外,還需要一個(gè)Message.RecipientType屬性(消息的接收類型)。
          message.addRecipient(type, address)
          地址的3種預(yù)定義類型如下:
          · Message.RecipientType.TO
          · Message.RecipientType.CC
          · Message.RecipientType.BCC
          因此,如果一條消息將發(fā)送給副總統(tǒng),同時(shí)還將發(fā)送該消息的副本給第一夫人,則采用下面的代碼:
          Address toAddress = new InternetAddress("vice.president@whitehouse.gov");
          Address ccAddress = new InternetAddress("first.lady@whitehouse.gov");
          message.addRecipient(Message.RecipientType.TO, toAddress);
          message.addRecipient(Message.RecipientType.CC, ccAddress);
          JavaMail API
          沒有提供檢查電子郵件地址有效性的機(jī)制。您可以自己編寫支持掃描有效字符(在RFC 822文檔中所定義的)的程序或檢驗(yàn)MX(郵件交換)記錄,這些都超越了JavaMail API的范圍。
          Authenticator

          java.net 類一樣,JavaMail API可以利用Authenticator(驗(yàn)證程序)類通過用戶名和密碼來訪問受保護(hù)的資源。對于JavaMail API來說,這種受保護(hù)的資源是指郵件服務(wù)器。JavaMailAuthenticator類可以在javax.mail包中找到,并有別于同名的 java.net類。當(dāng)JavaMail APIJava 1.1下工作時(shí),JavaMailjava.net不會共享同一個(gè)Authenticator類名稱,這是因?yàn)?span lang="EN-US">Java 1.1中不含有java.net
          要使用Authenticator類,您可以使用該抽象類的子類,并通過 getPasswordAuthentication()方法返回一個(gè)PasswordAuthentication實(shí)例。在創(chuàng)建時(shí),您必須用會話記錄 Authentication類。其后,當(dāng)需要進(jìn)行身份驗(yàn)證時(shí),會通知您的Authenticator。會彈出一個(gè)窗口,或從一個(gè)配置文件(盡管不加密就 不安全)中讀取用戶名和密碼,并把它們作為一個(gè)PasswordAuthentication對象返回給調(diào)用程序。
          Properties props = new Properties();
          // fill props with any information
          Authenticator auth = new MyAuthenticator();
          Session session = Session.getDefaultInstance(props, auth);
          Transport

          發(fā)送消息的最后一步操作是使用Transport類。該類使用特定于協(xié)議(通常是SMTP)的語言來發(fā)送消息。它是一個(gè)抽象類,其操作與Session類有些相似。您可以通過只調(diào)用靜態(tài)的send()方法來使用該類的默認(rèn)版本:
          Transport.send(message);
          或者,您可以從用于您的協(xié)議的會話中獲取一個(gè)特定的實(shí)例,然后傳遞用戶名和密碼(不必要時(shí)可以為空)并發(fā)送消息,最后關(guān)閉連接:
          message.saveChanges(); // implicit with send()
          Transport transport = session.getTransport("smtp");
          transport.connect(host, username, password);
          transport.sendMessage(message, message.getAllRecipients());
          transport.close();
          當(dāng)您需要發(fā)送多個(gè)消息時(shí),建議采用后一種方法,因?yàn)樗鼘⒈3窒㈤g活動服務(wù)器的連接。而基本的send()機(jī)制會為每一個(gè)方法調(diào)用都建立一條獨(dú)立的連接。
          注意:要查看經(jīng)過郵件服務(wù)器郵件命令,可以用session.setDebug(true)方法設(shè)置調(diào)試標(biāo)志。
          Store
          Folder
          使用Session類來獲取消息,開始時(shí)與發(fā)送消息很相似。但是,在獲取會話后,很有可能使用用戶名和密碼或Authenticator類來連接Store類。與Transport類一樣,您要告訴Store類將使用什么協(xié)議:
          // Store store = session.getStore("imap");
          Store store = session.getStore("pop3");
          store.connect(host, username, password);
          在連接Store類后,就可以獲取一個(gè)Folder類,在讀取其中的消息前必須先打開該類。
          Folder folder = store.getFolder("INBOX");
          folder.open(Folder.READ_ONLY);
          Message message[] = folder.getMessages();
          對于POP3協(xié)議,惟一可用的文件夾是INBOX。如果使用的是IMAP協(xié)議,則可以使用其他的文件夾。
          注意:Sun公司的提供程序本來想提供方便。而Message message[]=folder.getMessages();這條語句卻是一種從服務(wù)器逐條讀取消息的緩慢操作,所以僅當(dāng)您確實(shí)需要獲取消息部分(該內(nèi)容是所檢索消息的內(nèi)容)時(shí)可以使用這條語句。
          一旦讀取消息,就可以使用getContent()方法獲取其內(nèi)容,或使用writeTo()方法將其內(nèi)容寫到一個(gè)流中。getContent()方法只獲取消息內(nèi)容,而writeTo()方法則還會輸出報(bào)頭。
          System.out.println(((MimeMessage)message).getContent());
          一旦您閱讀完郵件,就可以關(guān)閉對文件夾和存儲的連接。
          folder.close(aBoolean);
          store.close();
          傳遞給文件夾的close()方法的布爾變量指定了是否通過清除已刪除的消息來更新文件夾。
          繼續(xù)前進(jìn)
          實(shí) 際上,理解使用這7個(gè)類的方式,是使用JavaMail API處理幾乎所有事情所需要的全部內(nèi)容。用這7個(gè)類以外的方式構(gòu)建的JavaMail API,其大多數(shù)功能都是以幾乎完全相同或特定的方式來執(zhí)行任務(wù)的,就好像內(nèi)容是附件。特定的任務(wù),如:搜索、隔離等將在后面進(jìn)行介紹。
          使用JavaMail API
          您已經(jīng)看到了如何操作JavaMail API的核心部分。在下面幾節(jié)中,您將學(xué)習(xí)如何連接幾個(gè)部分以執(zhí)行特定的任務(wù)。
          發(fā)送消息
          發(fā)送電子郵件消息涉及到獲取會話、創(chuàng)建和填充消息并發(fā)送消息這些操作。您可以在獲取Session時(shí),通過為要傳遞的Properties對象設(shè)置mail.smtp.host屬性來指定您的SMTP服務(wù)器。
          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);
          您應(yīng)該在try-catch塊中編寫代碼,以在創(chuàng)建消息并發(fā)送它時(shí)可以拋出一個(gè)異常。
          練習(xí)
          發(fā)送您的第一個(gè)消息
          獲取消息
          對于閱讀郵件來說,首先您要獲取一個(gè)會話,然后獲取并連接到一個(gè)相應(yīng)的用于您的收件箱的存儲上,接著打開相應(yīng)的文件夾,再獲取消息。同時(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();
          每一條消息執(zhí)行何種操作取決于自己決定。上面的代碼塊只是顯示了消息的發(fā)送者和主題。從技術(shù)上講,發(fā)送者地址列表可以為空,此時(shí)getFrom()[0]調(diào)用會拋出一個(gè)異常。
          為了顯示整條消息,您可以提示用戶在看完消息的發(fā)送者和主題字段后,如果想看到消息的內(nèi)容,可以再調(diào)用消息的writeTo()方法。
          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;
          }
          }
          練習(xí)
          檢查郵件
          刪除消息和標(biāo)志
          刪除消息涉及到操作與消息關(guān)聯(lián)的標(biāo)志。對不同的狀態(tài)有不同的標(biāo)志,有些標(biāo)志是系統(tǒng)定義的,有些則是由用戶定義的。預(yù)定義的標(biāo)志都是在內(nèi)部類Flags.Flag中定義的,如下所示:
          · Flags.Flag.ANSWERED
          · Flags.Flag.DELETED
          · Flags.Flag.DRAFT
          · Flags.Flag.FLAGGED
          · Flags.Flag.RECENT
          · Flags.Flag.SEEN
          · Flags.Flag.USER
          僅 僅因?yàn)闃?biāo)志存在,并不表示標(biāo)志為所有的郵件服務(wù)器/提供程序所支持。例如,除了刪除消息外,POP協(xié)議對它們都不支持。檢查新郵件不是POP的任務(wù),但它 已內(nèi)置到郵件客戶程序中。要搞清楚什么標(biāo)志受到支持,可以使用getPermanentFlags()方法來詢問文件夾。
          要?jiǎng)h除消息,需要為消息設(shè)置DELETE標(biāo)志:
          message.setFlag(Flags.Flag.DELETED, true);
          第一次以READ_WRITE(讀-寫)模式打開文件夾:
          folder.open(Folder.READ_WRITE);
          然后,處理完了所有的消息,請關(guān)閉文件夾,并傳遞true值以擦去刪除的消息。
          folder.close(true);
          用 戶可使用Folder類的expunge()方法來刪除消息。但是,該方法對Sun公司的POP3提供程序不起作用。其他提供程序或許能也或許不能實(shí)現(xiàn)其 功能。它更有可能適用于IMAP提供程序。由于POP只支持對收件箱的簡單訪問,使用Sun公司的提供程序時(shí),您將不得不關(guān)閉文件夾以刪除消息。
          要移去標(biāo)志,只需傳遞一個(gè)false值給setFlag()方法。要看看是否設(shè)置了某個(gè)標(biāo)志,可以使用isSet()進(jìn)行檢查。
          自我驗(yàn)證
          先前學(xué)到的是使用Authenticator類,以在需要時(shí)提示輸入用戶名和密碼,而不是以字符串的形式傳入它們。這里,您將真正看到如何更加充分地使用驗(yàn)證。
          不需使用主機(jī)、用戶名和密碼連接到Store,您可以配置Properties帶有主機(jī),并告訴Session關(guān)于您自定義的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 store
          Store store = session.getStore("pop3");
          store.connect();
          然 后您可以使用Authenticator類的子類,并通過getPasswordAuthentication()方法返回一個(gè) PasswordAuthentication對象。下面是這種實(shí)現(xiàn)的一個(gè)例子,其中一個(gè)字段同時(shí)適用于兩部分內(nèi)容。它不是一個(gè)Project Swing指南,只是在一個(gè)字段中輸入了兩部分內(nèi)容,它們是用逗號隔開的。
          import javax.mail.*;
          import javax.swing.*;
          import java.util.*;
          public class PopupAuthenticator extends Authenticator {
          public PasswordAuthentication getPasswordAuthentication() {
          String username, password;
          String result = JOptionPane.showInputDialog(
          "Enter 'username,password'");
          StringTokenizer st = new StringTokenizer(result, ",");
          username = st.nextToken();
          password = st.nextToken();
          return new PasswordAuthentication(username, password);
          }
          }
          由于PopupAuthenticator依賴于Swing,因而將會啟動用于AWT的事件處理線程。這在本質(zhì)上要求您在代碼中添加一個(gè)對System.exit()的調(diào)用,以終止程序的執(zhí)行。
          回復(fù)消息
          Message
          類包含一個(gè)reply()方法,以用正確的接收者和主題(添加“Re:,如果沒有的話)配置一條新消息。該方法不會為消息添加任何內(nèi)容,只是為新的接 收者復(fù)制發(fā)送者或回復(fù)到的報(bào)頭。該方法使用一個(gè)布爾型參數(shù),提示是否只回復(fù)給發(fā)送者(false)或回復(fù)給所有人(true)
          MimeMessage reply = (MimeMessage)message.reply(false);
          reply.setFrom(new InternetAddress("president@whitehouse.gov"));
          reply.setText("Thanks");
          Transport.send(reply);
          在發(fā)送消息時(shí)要配置回復(fù)到地址,可使用setReplyTo()方法。
          練習(xí)
          回復(fù)郵件
          轉(zhuǎn)發(fā)消息
          轉(zhuǎn)發(fā)消息涉及的內(nèi)容要稍微多一點(diǎn),沒有一個(gè)專門用于轉(zhuǎn)發(fā)消息的方法,您可以通過處理組成消息的各個(gè)部分來創(chuàng)建要轉(zhuǎn)發(fā)的消息。
          一 條郵件消息可由多個(gè)部分組成,每一部分是一個(gè)BodyPart(報(bào)文部分),或更特殊一點(diǎn),在操作MIME消息時(shí)則是MimeBodyPart。不同的報(bào) 文部分組合到一個(gè)稱為Multipart的容器中,或者又更特殊一點(diǎn),是一個(gè)MimeMultipart容器。要轉(zhuǎn)發(fā)消息,您要?jiǎng)?chuàng)建一個(gè)用于消息文本的部 分,和用于要轉(zhuǎn)發(fā)的消息的第二個(gè)部分,并將這兩個(gè)部分組合成一個(gè)multipart(多個(gè)部分)。然后您可以把這個(gè)multipart添加到一個(gè)合適的注 明地址的消息中并發(fā)送它。
          這就是轉(zhuǎn)發(fā)消息的本質(zhì)。要把一條消息的內(nèi)容復(fù)制給另一條消息,只需通過它的DataHandler類復(fù)制即可,它是出自于JavaBeans Activation Framework的一個(gè)類。
          // Create the message to forward
          Message forward = new MimeMessage(session);
          // Fill in header
          forward.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 content
          messageBodyPart = 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);
          操作附件
          附件是與郵件消息關(guān)聯(lián)的資源,通常保存在消息之外,如:一個(gè)文本文件,電子表格或圖片。對于像EudoraPine之類的常用郵件程序,您可以通過JavaMail API把資源附加到郵件消息上,并在您接收消息時(shí)獲取附件。
          發(fā)送附件
          發(fā) 送附件與轉(zhuǎn)發(fā)消息非常相似,您要?jiǎng)?chuàng)建組成完整消息的各個(gè)部分。在創(chuàng)建好第一個(gè)部分即消息文本之后,您添加的用DataHandler類處理的其他部分就是 您的附件,而不是轉(zhuǎn)發(fā)消息中的共享處理程序。當(dāng)您從一個(gè)文件讀取附件時(shí),附件的數(shù)據(jù)資源是FileDataSource;從URL讀取時(shí),則是 URLDataSource。一旦您有了自己的DataSource,在將其通過setDataHandler()方法最終附加到BodyPart上之 前,只需將其傳遞給DataHandler類的構(gòu)造器即可。假定您想保留附件的原始文件名,要做的最后一件事就是用BodyPart類的 setFileName()方法設(shè)置與附件關(guān)聯(lián)的文件名。所有這些操作如下所示:
          // 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 messageBodyPart = 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);
          在消息中包含附件時(shí),如果您的程序是一個(gè)servlet,您的用戶就必須上傳附件,并告訴您要把消息發(fā)送到什么位置。上傳的每一個(gè)文件都可以用一個(gè)表單來處理,該表單是以multipart/表單數(shù)據(jù)(form-data)來編碼的。
          <FORM ENCTYPE="multipart/form-data"
          method=post action="/myservlet">
          <INPUT TYPE="file" NAME="thefile">
          <INPUT TYPE="submit" VALUE="Upload">
          </FORM>
          注意:消息的大小要受到您的SMTP服務(wù)器的限制,而不是由JavaMail API限制的。如果出現(xiàn)了問題,可以通過設(shè)置msmx參數(shù)來考慮增加Java堆區(qū)的空間尺寸。
          練習(xí)
          發(fā)送附件
          獲取附件
          從 消息中取出附件比發(fā)送附件涉及的操作要稍微多一點(diǎn),而MIME沒有簡單的附件概念。當(dāng)消息帶有附件時(shí),消息的內(nèi)容就是一個(gè)Multipart對象。然后需 要處理各個(gè)部分,以獲取主要內(nèi)容和附件。通過part.getDisposition()方法標(biāo)記上Part.ATTACHMENT配置的部分顯然就是附 件。同時(shí),附件也可以不帶有配置(和非文本MIME類型)或Part.INLINE配置。當(dāng)配置是Part.ATTACHMENT Part.INLINE時(shí),您可以脫離該消息部分的內(nèi)容將其保存起來。只需通過getFileName()方法獲取原始文件名,并通過 getInputStream()方法獲取輸入流即可。
          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ù)文件名創(chuàng)建一個(gè)文件,從輸入流中讀取字節(jié),并將它們寫入一個(gè)文件中去。如果文件已存在,將在文件名后添加一個(gè)編號,直到找到一個(gè)不存在的文件為止。
          // from saveFile()
          File file = new File(filename);
          for (int i=0; file.exists(); i++) {
          file = new File(filename+i);
          }
          上面的代碼介紹了消息的各個(gè)部分被標(biāo)上相應(yīng)的標(biāo)志的一個(gè)最簡單的例子。要想包含所有的情況,還要對disposition值為null及消息部分為MIME類型的情況作相應(yīng)處理。
          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, ...
          }
          ...
          }
          處理HTML消息
          發(fā)送基于HTML的消息比發(fā)送純文本消息要稍微復(fù)雜一點(diǎn),盡管它不需要做大量的工作。它全部取決于您特定的需求。
          發(fā)送HTML消息
          如果您所要做的全部工作是發(fā)送一個(gè)等價(jià)的HTML文件作為消息,并讓郵件閱讀者憂心于取出任何嵌入的圖片或相關(guān)片段,那么就可以使用消息的setContent()方法,以字符串形式傳遞消息內(nèi)容,并把內(nèi)容類型設(shè)置為text/html
          String htmlText = "<H1>Hello</H1>" +
          "<img src=\" message.setContent(htmlText, "text/html"));
          在 接收端,如果您用JavaMail API獲取消息,在該API中沒有內(nèi)置任何用于以HTML格式顯示消息的功能。JavaMail API只以字節(jié)流的形式來查看消息。要以HTML格式顯示消息,您必須使用Swing JeditorPane或某些第3HTML閱讀器組件。
          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();
          }
          在消息中包含圖片
          另一方面,如果您的HTML消息中嵌入了作為消息一部分的圖片,并且您想保持消息內(nèi)容的完整,就必須把圖片看作附件,并用特殊的通信標(biāo)識符URL引用該圖片,該通信標(biāo)識符引用的是圖片附件的內(nèi)容ID報(bào)文。
          嵌 入圖片的處理與附加一個(gè)文件到消息上非常相似,惟一的不同之處在于:您必須區(qū)分MimeMultipart中,哪些部分是在構(gòu)造器(或通過 setSubType()方法)通過設(shè)置其子類型而使之相關(guān)的,以及將圖片的內(nèi)容ID報(bào)頭設(shè)置成任意字符串,它將在img標(biāo)記中用作圖片的源路徑。下面顯 示了一個(gè)完整的示例:
          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 message
          message.setContent(multipart);
          練習(xí)
          發(fā)送帶有圖片的 HTML 消息
          SearchTerm搜索
          JavaMail API
          包含一種可用于創(chuàng)建SearchTerm(搜索條件)的篩選機(jī)制,它可以在javax.mail.search包中找到。一旦創(chuàng)建了SearchTerm,您就可以詢問某個(gè)文件夾匹配的消息,并檢索出消息對象數(shù)組:
          SearchTerm st = ...;
          Message[] msgs = folder.search(st);
          22種不同的類可用于幫助創(chuàng)建搜索條件。
          · AND
          條件(AndTerm)
          · OR
          條件(OrTerm)
          · NOT
          條件(NotTerm)
          · SENT DATE
          條件(SentDateTerm)
          · CONTENT
          條件(BodyTerm)
          · HEADER
          條件(FromTerm / FromStringTerm, RecipientTerm / RecipientStringTerm, SubjectTerm, etc.)
          本質(zhì)上,您可以為匹配的消息創(chuàng)建一個(gè)邏輯表達(dá)式,然后進(jìn)行搜索。例如,下面顯示了一條消息的條件搜索示例,該消息帶有(部分帶有)一個(gè)ADV主題字符串,其發(fā)送者字段為
          friend@public.com。您可能考慮定期運(yùn)行該查詢,并自動刪除任何返回的消息。
          SearchTerm st =
          new OrTerm(
          new SubjectTerm("ADV:"),
          new FromStringTerm("friend@public.com"));
          Message[] msgs = folder.search(st);

           

          posted on 2005-12-27 18:49 千山鳥飛絕 閱讀(8573) 評論(2)  編輯  收藏 所屬分類: JavaMail

          FeedBack:
          # re: JavaMail簡易教程[未登錄]
          2009-03-13 08:34 | Wang
          Speaking of George W. Bush:

          George W. Bush is a raging racist.

          George W. Bush committed hate crimes of epic proportions and with the stench of terrorism (indicated in my blog).

          George W. Bush did in fact commit innumerable hate crimes.

          And I do solemnly swear by Almighty God that George W. Bush committed other hate crimes of epic proportions and with the stench of terrorism which I am not at liberty to mention.

          Many people know what Bush did.

          And many people will know what Bush did—even to the end of the world.

          Bush was absolute evil.

          Bush is now like a fugitive from justice.

          Bush is a psychological prisoner.

          Bush has a lot to worry about.

          Bush can technically be prosecuted for hate crimes at any time.

          In any case, Bush will go down in history in infamy.

          Respectfully Submitted by Andrew Yu-Jen Wang
          B.S., Summa Cum Laude, 1996
          Messiah College, Grantham, PA
          Lower Merion High School, Ardmore, PA, 1993

          (I can type 90 words per minute. In only 7 days, posts basically like this post of mine have come into existence—all over the Internet (hundreds of copies). One can go to Google USA right now, type “George W. Bush committed hate crimes of epic proportions and with the stench of terrorism,” hit “Enter,” and find more than 350 copies indicating the content of this post. All in all, there are probably more than 1,000 copies on the Internet indicating the content of this post—it has practically become headline news. One cannot be too dedicated when it comes to anti-Bush activities. As I looked back at my good computer work, I thought how fun and easy it was to do it.)

          “GEORGE W. BUSH IS THE WORST PRESIDENT IN U.S. HISTORY” BLOG OF ANDREW YU-JEN WANG
          _________________
          I am not sure where I had read it before, but anyway, it goes kind of like this: “If only it were possible to ban invention that bottled up memories so they never got stale and faded.” Oh wait—off the top of my head—I think it came from my Lower Merion High School yearbook.  回復(fù)  更多評論
            
          # re: JavaMail簡易教程[未登錄]
          2012-12-14 15:10 | Tom
          測試測試  回復(fù)  更多評論
            

          只有注冊用戶登錄后才能發(fā)表評論。


          網(wǎng)站導(dǎo)航:
           
          正在閱讀:



          <2025年6月>
          25262728293031
          1234567
          891011121314
          15161718192021
          22232425262728
          293012345

          常用鏈接

          留言簿(35)

          隨筆檔案

          文章分類

          文章檔案

          好友的blog

          我的其他blog

          老婆的Blog

          搜索

          •  

          積分與排名

          • 積分 - 776098
          • 排名 - 56

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 双辽市| 逊克县| 昭苏县| 连城县| 莒南县| 咸丰县| 五原县| 黎平县| 九江县| 德昌县| 千阳县| 余姚市| 彭泽县| 竹溪县| 于田县| 时尚| 西乌珠穆沁旗| 胶州市| 黎川县| 湘阴县| 高唐县| 南雄市| 资兴市| 绍兴市| 凌源市| 搜索| 定边县| 松潘县| 宝清县| 河曲县| 延安市| 郸城县| 手机| 河池市| 伊金霍洛旗| 甘肃省| 湾仔区| 盐城市| 枣庄市| 保康县| 涟源市|