|
||||||||||||||||||||||||
JavaMail API是一種可選的、能用于讀取、編寫和發(fā)送電子消息的包(標(biāo)準(zhǔn)擴(kuò)展)。您可使用這種包創(chuàng)建郵件用戶代理(Mail User Agent ,MUA)類型的程序,它類似于Eudora、Pine及Microsoft Outlook這些郵件程序。其主要目的不是像發(fā)送郵件或其他郵件傳輸代理(Mail Transfer Agent,MTA)類型的程序那樣用于傳輸、發(fā)送和轉(zhuǎn)發(fā)消息。換句話說,用戶可以與MUA類型的程序交互,以閱讀和撰寫電子郵件。MUA依靠MTA處理實(shí)際的發(fā)送任務(wù)。 JavaMail API的設(shè)計(jì)是,為收發(fā)信息提供與協(xié)議無關(guān)的訪問。方式是把該API劃分成兩個(gè)部分: · 該API的第一個(gè)部分是本課程的重點(diǎn)?;旧鲜侨绾伟l(fā)送和接收獨(dú)立于提供程序/協(xié)議的消息。 · 第二個(gè)部分則使用特定的協(xié)議語言,如:SMTP、POP、IMAP和NNTP。如果要讓JavaMail API與服務(wù)器通信,就需要為之提供協(xié)議。由于Sun公司對(duì)特定協(xié)議提供程序有充分的介紹,用戶可以免費(fèi)獲取,所以本課程沒有介紹創(chuàng)建特定協(xié)議提供程序的內(nèi)容。 在學(xué)習(xí)JavaMail API的深層知識(shí)之前,讓我們回過頭來看一看在該API中使用的協(xié)議,本質(zhì)上有4種人們常用的協(xié)議: · SMTP 您還需要了解NNTP及其他一些協(xié)議。理解這些協(xié)議的基本原理有助于您理解如何使用JavaMail API。而該API的設(shè)計(jì)要與協(xié)議無關(guān),所以不能克服這些基礎(chǔ)協(xié)議的限制。如果選用的協(xié)議不支持某種功能,那么JavaMail API也無法在其上添加這種功能。(正如您一會(huì)兒就會(huì)看到的,在操作POP協(xié)議時(shí),常常會(huì)碰到這種問題)。 SMTP 簡(jiǎn)單郵件傳輸協(xié)議(SMTP)是用于傳送電子郵件的機(jī)制。在JavaMail API環(huán)境中,您的基于JavaMail的程序?qū)⑴c您公司或Internet服務(wù)提供商(ISP)的SMTP服務(wù)器通信。該SMTP服務(wù)器將會(huì)把消息轉(zhuǎn)發(fā)給用作接收消息的SMTP服務(wù)器,最后用戶可通過POP或IMAP協(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中定義的。POP是Internet上的大多數(shù)人用來接收郵件的機(jī)制。它為每個(gè)用戶的每個(gè)郵箱定義支持,這是它所做的全部工作,也是大多數(shù)問題的根源。在使用POP協(xié)議時(shí),人們熟悉的很多功能,如查看收到了多少新郵件消息的功能,POP根本不支持。這些功能都內(nèi)置到諸如Eudora或 Microsoft Outlook之類的郵件程序中,能為您記住接收的上一封郵件,以及計(jì)算有多少新郵件這類信息。因此,使用JavaMail API時(shí),如果想獲取這類信息,將需要由自己進(jìn)行計(jì)算。 IMAP IMAP是用于接收消息的更加高級(jí)的協(xié)議,它是在RFC 2060中定義的。IMAP的含義是“Internet消息訪問協(xié)議”,當(dāng)前版本是第4版,也稱作IMAP4。使用IMAP時(shí),您的郵件服務(wù)器必須支持該協(xié)議。您不能只是簡(jiǎn)單地把程序轉(zhuǎn)變?yōu)橹С諭MAP,而不是支持POP,就指望能支持IMAP中的一切。假定您的郵件服務(wù)器支持IMAP,那么基于 JavaMail的程序就可利用在服務(wù)器上擁有多個(gè)文件夾的用戶,并且這些文件夾可以被多個(gè)用戶共享的功能。 由于IMAP協(xié)議具有更高級(jí)的功能,您也許會(huì)想IMAP應(yīng)該被每一個(gè)人使用,但事實(shí)不是這樣。因?yàn)镮MAP會(huì)加重郵件服務(wù)器的負(fù)荷,它需要服務(wù)器接收新消息,發(fā)送消息給請(qǐng)求的用戶,并在多個(gè)文件夾中為每個(gè)用戶維護(hù)這些消息。而這要集中備份,因而長(zhǎng)期下去用戶的文件夾會(huì)變得越來越大,當(dāng)磁盤空間用光了時(shí),每個(gè)人都會(huì)遭受損失。而使用POP協(xié)議時(shí),已保存消息可以解除服務(wù)器的重負(fù)。 MIME MIME的含義是“多用途的網(wǎng)際郵件擴(kuò)充協(xié)議”。它不是一種郵件傳輸協(xié)議,相反,它定義傳輸?shù)膬?nèi)容:消息的格式、附件等。許多文檔都定義了MIME協(xié)議,包含:RFC 822、RFC 2045、RFC 2046和RFC 2047。作為JavaMail API的用戶,一般不需要擔(dān)心這些格式。但是,這些格式確實(shí)存在,并為您的程序所用。 NNP和其他協(xié)議 由于JavaMail API分開了提供程序和其他部分,所以您可以輕松地為附加協(xié)議添加支持。Sun公司提供第3方提供程序清單,這些提供程序要利用 Sun公司不支持的少見的協(xié)議。在這份清單中,您將會(huì)看到對(duì)NNTP(網(wǎng)絡(luò)新聞傳輸協(xié)議)[新聞組]、S/MIME(安全多用途的網(wǎng)際郵件擴(kuò)充協(xié)議)及其他協(xié)議的提供支持的第3方提供程序。 目前有兩種版本的JavaMail API最常用:1.2和1.1.3。本課程中的所有例子都適用于這兩種版本。其中JavaMail API 1.2是最新的,而JavaMail API 1.1.3中包含了Java 2企業(yè)版(J2EE)平臺(tái)1.2.1版,所以它仍然很常用。使用JavaMail API的版本會(huì)對(duì)您的下載和安裝產(chǎn)生一些影響。這兩種版本的JavaMail API都能與JDK 1.1.6、Java 2標(biāo)準(zhǔn)版(J2SE)平臺(tái)1.2.x和1.3.x協(xié)同工作。 注意:在安裝了Sun公司的JavaMail工具后,會(huì)在演示目錄下看到許多示例程序。 安裝JavaMail 1.2 要使用JavaMail 1.2 API,可以下載JavaMail 1.2工具,然后解壓縮javamail-1_2.zip文件,并把mail.jar文件添加到典型安裝路徑下。JavaMail 1.2工具帶有SMTP、IMAP4和POP3提供程序以及核心類。 安裝完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工具帶有SMTP和IMAP4提供程序以及核心類。 如果您想用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 Framework(JavaBeans激活框架),這種框架提供了對(duì)輸入任意數(shù)據(jù)塊的支持,并能相應(yīng)地對(duì)其進(jìn)行處理??瓷先バЧ孟癫惶?,但該框架是在當(dāng)今的許多瀏覽器和郵件工具中可以找到的基本MIME類型支持。下載該框架后,解壓縮jaf1_0_1.zip文件,并將activation.jar 文件添加到典型安裝路徑下。 對(duì)于JavaMail 1.2用戶,現(xiàn)在應(yīng)該把mail.jar和activation.jar文件添加到典型安裝路徑下。 對(duì)于JavaMail 1.1.3用戶,現(xiàn)在應(yīng)該把mail.jar、pop3.jar和activation.jar添加到典型安裝路徑下。如果您不打算使用POP3,就不需要把pop3.jar文件添加到典型安裝路徑下。 如果您不想更改安裝路徑環(huán)境變量,可以把JAR文件復(fù)制到Java運(yùn)行時(shí)環(huán)境(JRE)目錄下的lib/ext目錄下。例如,對(duì)于J2SE 1.3版本,Windows平臺(tái)上的默認(rèn)目錄應(yīng)該是C:\jdk1.3\jre\lib\ext。 如果您使用的是J2EE,則在使用基本JavaMail API時(shí),不需要做什么特殊的工作;JavaMail API帶有J2EE類。只要確保j2ee.jar文件位于典型安裝路徑下,并完成了所有的設(shè)置工作。 對(duì)于J2EE 1.2.1,POP3提供程序是單獨(dú)提供的,因此需要下載該提供程序,并按安裝JavaMail 1.1.3的步驟,在J2EE 1.2.1中包含POP3提供程序。J2EE 1.3的用戶會(huì)獲得J2EE和POP3提供程序,因而不需要對(duì)POP3提供程序執(zhí)行獨(dú)立安裝。使用這兩種版本的J2EE用戶,都不需要安裝 JavaBeans Activation Framework。 復(fù)習(xí)核心類 在開始深入研究JavaMail類之前,首先讓用戶瀏覽一下構(gòu)成API的核心類:會(huì)話、消息、地址、驗(yàn)證程序、傳輸,存儲(chǔ)和文件夾。所有這些類都可以在 JavaMail API即javax.mail的頂層包中找到,盡管您將頻繁地發(fā)現(xiàn)您自己使用的子類是在javax.mail.internet包中找到的。 Session類定義了一個(gè)基本的郵件會(huì)話。通過該會(huì)話可讓別的工作順利執(zhí)行。Session對(duì)象利用java.util.Properties對(duì)象獲取諸如郵件服務(wù)器、用戶名、密碼等信息,以及其他可在整個(gè)應(yīng)用程序中共享的信息。 Session類的構(gòu)造器是私有的。您可以獲得一個(gè)可被getDefaultInstance()方法共享的單一的默認(rèn)會(huì)話: Properties props = new Properties(); // fill props with any information Session session = Session.getDefaultInstance(props, null); 或者,您可以用getInstance()方法創(chuàng)建一個(gè)獨(dú)特的會(huì)話: Properties props = new Properties(); // fill props with any information Session session = Session.getInstance(props, null); 這兩種情形下的null參數(shù)都是一種Authenticator對(duì)象,它不是在此時(shí)使用的。詳細(xì)信息請(qǐng)參閱其后的“Autherticator”一節(jié)。 在大多數(shù)情況下,使用共享會(huì)話就足夠了,即使為多個(gè)用戶郵箱處理郵件會(huì)話也是如此。您可以在通信過程的后面一步添加上用戶名和密碼的組合,并保持所有的一切是獨(dú)立的。 一旦創(chuàng)建了自己的Session對(duì)象,就是該去創(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對(duì)象傳遞給MimeMessage構(gòu)造器的方法來創(chuàng)建消息: MimeMessage message = new MimeMessage(session); 一旦創(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"); 對(duì)于純文本消息,setText()方法更常常被用來設(shè)置內(nèi)容。要發(fā)送其他類型的消息,如HTML消息,就要使用setContent方法()?,F(xiàn)在用的更多的是HTML消息。 要設(shè)置主題,可以使用setSubject()方法: message.setSubject("First"); 一旦創(chuàng)建了會(huì)話和消息,并為消息填充了內(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)建地址對(duì)象。除非您的郵件服務(wù)器阻止這樣做,否則要在發(fā)送的消息中注明該消息的發(fā)送者。 一旦創(chuàng)建好了地址,有兩種方法可讓您將地址與消息連接起來。為了鑒別發(fā)送者,您可以使用setFrom()和setReplyTo()方法。 message.setFrom(address) 如果您的消息需要顯示多個(gè)地址來源,則可以使用addFrom()方法: Address address[] = ...; 為了鑒別消息接收者,您可以使用addRecipient()方法。該方法除了需要一個(gè)地址參數(shù)外,還需要一個(gè)Message.RecipientType屬性(消息的接收類型)。 message.addRecipient(type, address) 地址的3種預(yù)定義類型如下: · Message.RecipientType.TO 因此,如果一條消息將發(fā)送給副總統(tǒng),同時(shí)還將發(fā)送該消息的副本給第一夫人,則采用下面的代碼: Address toAddress = new InternetAddress("vice.president@whitehouse.gov"); JavaMail API沒有提供檢查電子郵件地址有效性的機(jī)制。您可以自己編寫支持掃描有效字符(在RFC 822文檔中所定義的)的程序或檢驗(yàn)MX(郵件交換)記錄,這些都超越了JavaMail API的范圍。 與java.net 類一樣,JavaMail API可以利用Authenticator(驗(yàn)證程序)類通過用戶名和密碼來訪問受保護(hù)的資源。對(duì)于JavaMail API來說,這種受保護(hù)的資源是指郵件服務(wù)器。JavaMail的Authenticator類可以在javax.mail包中找到,并有別于同名的 java.net類。當(dāng)JavaMail API在Java 1.1下工作時(shí),JavaMail和java.net不會(huì)共享同一個(gè)Authenticator類名稱,這是因?yàn)镴ava 1.1中不含有java.net。 要使用Authenticator類,您可以使用該抽象類的子類,并通過 getPasswordAuthentication()方法返回一個(gè)PasswordAuthentication實(shí)例。在創(chuàng)建時(shí),您必須用會(huì)話記錄 Authentication類。其后,當(dāng)需要進(jìn)行身份驗(yàn)證時(shí),會(huì)通知您的Authenticator。會(huì)彈出一個(gè)窗口,或從一個(gè)配置文件(盡管不加密就不安全)中讀取用戶名和密碼,并把它們作為一個(gè)PasswordAuthentication對(duì)象返回給調(diào)用程序。 Properties props = new Properties(); 發(fā)送消息的最后一步操作是使用Transport類。該類使用特定于協(xié)議(通常是SMTP)的語言來發(fā)送消息。它是一個(gè)抽象類,其操作與Session類有些相似。您可以通過只調(diào)用靜態(tài)的send()方法來使用該類的默認(rèn)版本: Transport.send(message); 或者,您可以從用于您的協(xié)議的會(huì)話中獲取一個(gè)特定的實(shí)例,然后傳遞用戶名和密碼(不必要時(shí)可以為空)并發(fā)送消息,最后關(guān)閉連接: message.saveChanges(); // implicit with send() Transport transport = session.getTransport("smtp"); 當(dāng)您需要發(fā)送多個(gè)消息時(shí),建議采用后一種方法,因?yàn)樗鼘⒈3窒㈤g活動(dòng)服務(wù)器的連接。而基本的send()機(jī)制會(huì)為每一個(gè)方法調(diào)用都建立一條獨(dú)立的連接。 注意:要查看經(jīng)過郵件服務(wù)器郵件命令,可以用session.setDebug(true)方法設(shè)置調(diào)試標(biāo)志。 使用Session類來獲取消息,開始時(shí)與發(fā)送消息很相似。但是,在獲取會(huì)話后,很有可能使用用戶名和密碼或Authenticator類來連接Store類。與Transport類一樣,您要告訴Store類將使用什么協(xié)議: // Store store = session.getStore("imap"); 在連接Store類后,就可以獲取一個(gè)Folder類,在讀取其中的消息前必須先打開該類。 Folder folder = store.getFolder("INBOX"); 對(duì)于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()方法則還會(huì)輸出報(bào)頭。 System.out.println(((MimeMessage)message).getContent()); 一旦您閱讀完郵件,就可以關(guān)閉對(duì)文件夾和存儲(chǔ)的連接。 folder.close(aBoolean); 傳遞給文件夾的close()方法的布爾變量指定了是否通過清除已刪除的消息來更新文件夾。 繼續(xù)前進(jìn) 實(shí)際上,理解使用這7個(gè)類的方式,是使用JavaMail API處理幾乎所有事情所需要的全部?jī)?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ā)送電子郵件消息涉及到獲取會(huì)話、創(chuàng)建和填充消息并發(fā)送消息這些操作。您可以在獲取Session時(shí),通過為要傳遞的Properties對(duì)象設(shè)置mail.smtp.host屬性來指定您的SMTP服務(wù)器。 String host = ...; 對(duì)于閱讀郵件來說,首先您要獲取一個(gè)會(huì)話,然后獲取并連接到一個(gè)相應(yīng)的用于您的收件箱的存儲(chǔ)上,接著打開相應(yīng)的文件夾,再獲取消息。同時(shí),不要忘記了操作完成后關(guān)閉連接。 String host = ...; 每一條消息執(zhí)行何種操作取決于自己決定。上面的代碼塊只是顯示了消息的發(fā)送者和主題。從技術(shù)上講,發(fā)送者地址列表可以為空,此時(shí)getFrom()[0]調(diào)用會(huì)拋出一個(gè)異常。 為了顯示整條消息,您可以提示用戶在看完消息的發(fā)送者和主題字段后,如果想看到消息的內(nèi)容,可以再調(diào)用消息的writeTo()方法。 BufferedReader reader = new BufferedReader ( 刪除消息涉及到操作與消息關(guān)聯(lián)的標(biāo)志。對(duì)不同的狀態(tài)有不同的標(biāo)志,有些標(biāo)志是系統(tǒng)定義的,有些則是由用戶定義的。預(yù)定義的標(biāo)志都是在內(nèi)部類Flags.Flag中定義的,如下所示: · Flags.Flag.ANSWERED 僅僅因?yàn)闃?biāo)志存在,并不表示標(biāo)志為所有的郵件服務(wù)器/提供程序所支持。例如,除了刪除消息外,POP協(xié)議對(duì)它們都不支持。檢查新郵件不是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); 然后,處理完了所有的消息,請(qǐng)關(guān)閉文件夾,并傳遞true值以擦去刪除的消息。 folder.close(true); 用戶可使用Folder類的expunge()方法來刪除消息。但是,該方法對(duì)Sun公司的POP3提供程序不起作用。其他提供程序或許能也或許不能實(shí)現(xiàn)其功能。它更有可能適用于IMAP提供程序。由于POP只支持對(duì)收件箱的簡(jiǎn)單訪問,使用Sun公司的提供程序時(shí),您將不得不關(guān)閉文件夾以刪除消息。 要移去標(biāo)志,只需傳遞一個(gè)false值給setFlag()方法。要看看是否設(shè)置了某個(gè)標(biāo)志,可以使用isSet()進(jìn)行檢查。 先前學(xué)到的是使用Authenticator類,以在需要時(shí)提示輸入用戶名和密碼,而不是以字符串的形式傳入它們。這里,您將真正看到如何更加充分地使用驗(yàn)證。 不需使用主機(jī)、用戶名和密碼連接到Store,您可以配置Properties帶有主機(jī),并告訴Session關(guān)于您自定義的Authenticator實(shí)例,如下所示: // Setup properties 然后您可以使用Authenticator類的子類,并通過getPasswordAuthentication()方法返回一個(gè) PasswordAuthentication對(duì)象。下面是這種實(shí)現(xiàn)的一個(gè)例子,其中一個(gè)字段同時(shí)適用于兩部分內(nèi)容。它不是一個(gè)Project Swing指南,只是在一個(gè)字段中輸入了兩部分內(nèi)容,它們是用逗號(hào)隔開的。 import javax.mail.*; 由于PopupAuthenticator依賴于Swing,因而將會(huì)啟動(dòng)用于AWT的事件處理線程。這在本質(zhì)上要求您在代碼中添加一個(gè)對(duì)System.exit()的調(diào)用,以終止程序的執(zhí)行。 Message 類包含一個(gè)reply()方法,以用正確的接收者和主題(添加“Re::”,如果沒有的話)配置一條新消息。該方法不會(huì)為消息添加任何內(nèi)容,只是為新的接收者復(fù)制發(fā)送者或回復(fù)到的報(bào)頭。該方法使用一個(gè)布爾型參數(shù),提示是否只回復(fù)給發(fā)送者(false)或回復(fù)給所有人(true)。 MimeMessage reply = (MimeMessage)message.reply(false); 轉(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 操作附件 附件是與郵件消息關(guān)聯(lián)的資源,通常保存在消息之外,如:一個(gè)文本文件,電子表格或圖片。對(duì)于像Eudora和Pine之類的常用郵件程序,您可以通過JavaMail API把資源附加到郵件消息上,并在您接收消息時(shí)獲取附件。 發(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 在消息中包含附件時(shí),如果您的程序是一個(gè)servlet,您的用戶就必須上傳附件,并告訴您要把消息發(fā)送到什么位置。上傳的每一個(gè)文件都可以用一個(gè)表單來處理,該表單是以multipart/表單數(shù)據(jù)(form-data)來編碼的。 <FORM ENCTYPE="multipart/form-data" 注意:消息的大小要受到您的SMTP服務(wù)器的限制,而不是由JavaMail API限制的。如果出現(xiàn)了問題,可以通過設(shè)置ms和mx參數(shù)來考慮增加Java堆區(qū)的空間尺寸。 從消息中取出附件比發(fā)送附件涉及的操作要稍微多一點(diǎn),而MIME沒有簡(jiǎn)單的附件概念。當(dāng)消息帶有附件時(shí),消息的內(nèi)容就是一個(gè)Multipart對(duì)象。然后需要處理各個(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(); (disposition.equals(Part.INLINE))) { saveFile(part.getFileName(), part.getInputStream()); saveFile()方法只用于根據(jù)文件名創(chuàng)建一個(gè)文件,從輸入流中讀取字節(jié),并將它們寫入一個(gè)文件中去。如果文件已存在,將在文件名后添加一個(gè)編號(hào),直到找到一個(gè)不存在的文件為止。 // from saveFile() File file = new File(filename); 上面的代碼介紹了消息的各個(gè)部分被標(biāo)上相應(yīng)的標(biāo)志的一個(gè)最簡(jiǎn)單的例子。要想包含所有的情況,還要對(duì)disposition值為null及消息部分為MIME類型的情況作相應(yīng)處理。 if (disposition == null) { 發(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>" + 在接收端,如果您用JavaMail API獲取消息,在該API中沒有內(nèi)置任何用于以HTML格式顯示消息的功能。JavaMail API只以字節(jié)流的形式來查看消息。要以HTML格式顯示消息,您必須使用Swing JeditorPane或某些第3方HTML閱讀器組件。 if (message.getContentType().equals("text/html")) { 另一方面,如果您的HTML消息中嵌入了作為消息一部分的圖片,并且您想保持消息內(nèi)容的完整,就必須把圖片看作附件,并用特殊的通信標(biāo)識(shí)符URL引用該圖片,該通信標(biāo)識(shí)符引用的是圖片附件的內(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 = ...; JavaMail API包含一種可用于創(chuàng)建SearchTerm(搜索條件)的篩選機(jī)制,它可以在javax.mail.search包中找到。一旦創(chuàng)建了SearchTerm,您就可以詢問某個(gè)文件夾匹配的消息,并檢索出消息對(duì)象數(shù)組: SearchTerm 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)行該查詢,并自動(dòng)刪除任何返回的消息。 SearchTerm st = |
杰森
郵箱:json.shen(at)gmail.com
網(wǎng)站:www.shenjia.org