JavaMail常見問題
一般問題
安裝和配置
編程
閱讀郵件——IMAP
發送郵件——SMTP
POP3
servlet 中的 JavaMail
applet 中的 JavaMail
一般問題
問. 什么是 JavaMail API?
答:JavaMail
API 是一組抽象的 API,它可用于構建郵件系統。API 提供了一個平臺無關以及協議無關的框架,用于構建基于 Java
技術的電子郵件客戶端應用程序。JavaMail API 提供了一些工具,用于閱讀和發送電子郵件。服務提供程序實現了特定的一些協議。在
JavaMail API 軟件包中,包括了幾個服務提供程序;另外還有其他的一些服務提供程序可供使用。JavaMail API 是作為 Java
可選包實現的,它可用在 JDK 1.1.6 中,以后還可用在任何操作系統上。JavaMail API 也是 Java 2 Platform, Enterprise Edition (J2EE) 中的必需部分。
問. 我如何獲得 JavaMail API 的實現?
答: Sun 提供了無版權的參考實現(二進制形式),開發人員可以使用和發行。參考實現包括核心的 JavaMail 包 和 IMAP、POP3 和 SMTP 服務提供程序。
問. 我如何發送反饋或評論?
答:發送電子郵件到 javamail@Sun.COM。也可以考慮加入我們的低容量通告郵件列表 (low-volume announce mailing list) javamail-announce@java.sun.com。在我們的 Web 頁 http://java.sun.com/products/javamail 中有關于如何加入的說明。
問. javax.activation 在哪里?
答: javax.activation
是 JavaBeans Activation Framework (JAF) 的一部分。JAF 是 JavaBeans "Glasgow" 規范的一部分(參見 http://java.sun.com/beans/glasgow/jaf.html)。JavaMail API 將 JAF 用于數據內容處理。
問. JavaMail API 需要什么 JDK?
答:JavaMail
API 要求 JDK/JRE 1.1.x 或更高版本。我們已經在 Sun Microsystems JDK 1.1.6 至 JDK 1.1.7
上測試過這個實現,而這些 JDK 運行于 Solaris SPARC、Microsoft Windows 95/NT 和 RedHat
Linux 4.2。我們也已經在 Java 2 SDK, Standard Edition (J2SE SDK) 版本 1.2、1.3 和 1.4 上做過測試,而這些 JDK 運行于 Solaris SPARC。JavaMail API 是 Java 的可選包,它們不是核心 J2SE 的一部分,但在 J2EE 中卻包括了它。參見 http://java.sun.com/j2se,獲取關于 JDK 1.1 和 J2SE 的進一步信息。
問. 從哪里能找到我喜歡的操作系統的 JavaMail 版本?
答:JavaMail 是完全用 Java 編寫的,并將運行在特定的操作系統上,該操作系統支持所需版本的 JDK。對于不同的操作系統,不需要任何特殊的版本。
問. JavaMail API 可以在瀏覽器中工作嗎?
答:在 Netscape 和 Internet Explorer 中,我們已經成功運行過 JavaMail 1.3。
問. 我可以使用 JavaMail 來從 Web 郵件賬戶(比如 Yahoo 或 Hotmail)中閱讀郵件嗎?
答:不
一定。許多基于 Web 的電子郵件服務只提供在瀏覽器中用 HTTP 進行訪問。這些服務不能使用 JavaMail 來訪問。如果服務也提供
POP3 或 IMAP 訪問,可能不可以使用 JavaMail 來訪問它。 聯系你的 Web 電子郵件服務提供商,獲取更詳細的信息。也可參閱 JHTTPMail 項目,獲得 JavaMail 的開放源代碼提供程序,它提供了對 Hotmail 的訪問。另一個有用的工具是 MrPostman——提供到 Hotmail 和 Yahoo! Mail 的 POP3 訪問的代理服務器,這個工具可從如下站點獲得:http://mrbook.org/mrpostman/。
問. 什么是 IMAP?
答:IMAP
是 Internet 消息訪問協議 (Internet Message Access
Protocol)。它是訪問電子郵件消息的一種方法,而這些消息存儲在(可能是共享的)郵件服務器上。換句話說,它允許“客戶端”電子郵件程序訪問遠程
的消息存儲,并且在訪問時,就像它們就在本地一樣。IMAP 由 RFC2060 定義。有關進一步信息,請參閱 http://www.imap.org/。
問. 什么是 SMTP?
答:SMTP
就是簡單郵件傳輸協議 (Simple Mail Transfer Protocol)。它可用于不同郵件主機間 RFC822
樣式的消息的傳輸,以及用于將新消息提交給一臺主機,然后由它來傳送該消息。SMTP 在廣泛使用中(起源于 1982 年),并由 RFC821 定義。
問. 什么是 MIME?
答:MIME 和 RFC822 是一些標準,它們用于描述電子郵件消息,而這些消息是跨 Internet 進行發送的。javax.mail.internet 子包(它是 JavaMail API 的一部分)提供了這兩個包的完整實現。MIME 是由下述 RFC 指定的:RFC2045、RFC2046 和 RFC2047。
問. 什么是 POP3?
答:POP3 是郵局協議 (Post Office Protocol V3)。POP3 是一個非常有限的協議,用于訪問單個郵箱。它在功能上比 IMAP 差了許多。POP3 應用非常廣泛,并由 RFC1939 定義。
問. 對 MAPI、NNTP、Lotus Notes 和其他服務提供程序的支持怎樣?
答:目前我們還沒有計劃實現這些提供程序中的任何一個。不過,JavaMail API 的體系結構提供一些功能,可以容易地插入第三方服務提供程序。我們的希望是第三方將通過編寫針對其他標準和專有協議的提供程序來包括 JavaMail API。 參閱 第三方產品 頁面,獲取這些提供程序的最新列表。
問. 我如何在本地磁盤上存儲郵件消息?
答:“本地存儲提供程序”可用于將郵件消息存儲在本地磁盤中。JavaMail API 不包括這一提供程序,但有幾個提供程序可從第三方獲得,它們針對不同的本地存儲格式,比如 MH 和 Mbox。參閱我們的 第三方產品 頁面,獲取這些提供程序的最新列表。
問. 我可以從哪里找到有關 Sun 協議提供程序的文檔?
答:針對 IMAP、POP3 和 SMTP 的 Sun 協議提供程序支持許多特性,它們不是 JavaMail API 規范的一部分。在 JavaMail 1.3 下載包中包括了這些協議提供程序的文檔,這些文檔是以 javadoc 格式包括的,并位于 docs/javadocs
目錄。針對每個協議提供程序包的包級文檔描述了一些屬性,這些屬性由協議提供程序支持。此外,協議提供程序包括了一些類和方法,應用程序可以使用它們來利用特定于提供程序的特性。注意,這些屬性、類和方法的使用使得程序不可移植;它可能只與 Sun 的 JavaMail API 實現一起工作。
問. JavaMail API 實現是否完全免費?我可以把它與我的產品一起發行嗎?
答:可以。當前版本的 JavaMail API 實現是完全免費的,你可以在產品中包括它。這一版本也包括 IMAP、POP3 和 SMTP 提供程序。請一定閱讀 許可,并保證理解它。JavaBeans Activation Framework 也是在類似的許可下免費使用的。
問. 我可以獲得 JavaMail API 實現的源代碼嗎?
答:在 SCSL 許可下,現在 JavaMail API 參考實現源代碼可作為 J2EE 的一部分獲得。可從 這里 下載它。
問. JavaMail 是否符合 Y2K?
答:是的。 Sun 的 JavaMail 實現是符合 Option-3 Y2K 的。請參看 JavaMail 包中的 NOTES.txt 文件,獲取進一步信息。
問. 我的問題不在這里,我應該在哪里查找?
答:除 JavaMail API 規范和 javadocs 外(可從 我們的 Web 主頁 獲得并且是包括在下載包中的),不要忘記查閱 JavaMail API 包中包括的 README.txt 和 NOTES.txt 文件,獲取其他的重要信息。
javamail-interest mailing list 是另一個信息來源。參閱 我們的 Web 主頁,獲取有關如何訂閱的說明以及指向文檔的鏈接。
Java Developer Connection 維護 JavaMail 論壇,請參閱 http://forum.java.sun.com。注意,JavaMail 團隊管理 javamail-interest 郵件列表,但不管理 JavaMail 論壇。
jGuru 也維護 JavaMail FAQ,可在如下地址找到它:http://www.jguru.com/faq/JavaMail。
安裝和配置
問. 我如何安裝 JavaMail API 實現?
答:解
壓縮分發的 zip 文件,并編輯 CLASSPATH 環境變量以包含 mail.jar 文件,該文件包括在 JavaMail API
分發中。你也需要 JavaBeans Activation Framework(參見下面)的實現。參閱 README
文件(在分發中),獲得其他細節和例子。
問. JavaMail 是否包括所有必要的郵件服務器?
答:不
是,JavaMail API 包不包括任何郵件服務器。為了使用 JavaMail API 包,你將需要訪問 IMAP 或 POP3
郵件服務器(用于閱讀郵件)和/或 SMTP 郵件服務器(用于發送郵件)。這些郵件服務器通常由 Internet
服務提供商提供,或者作為組織網絡基礎結構的一部分。如果你不必訪問這樣的郵件服務器,請往下看。
問. 從哪里可以獲得必要的郵件服務器?
答:Sun Java System Messaging Server 可用于 Solaris 和 Windows 平臺。華盛頓大學的 IMAP 服務器支持多種平臺 (UNIX、32 位 Windows 等)。可從如下地址獲取源代碼:ftp://ftp.cac.washington.edu/imap/imap.tar.Z。其他的許多供應商提供了支持 Internet 標準的郵件服務器。可以從 IMAP Connection 和 Internet Mail Consortium 獲得更多信息。
問. 我應該使用什么主機名、用戶名或密碼?
答:我們不提供郵件服務器讓你使用。你必須使用自己的郵件服務器,或者使用 Internet 服務提供商或你所工作的公司提供的郵件服務器。網絡管理員可能給你一些必要的信息用于配置 JavaMail,以便同郵件服務器一起工作。
問. 我如何配置 JavaMail 通過代理服務器工作?
答:大
多數代理服務器只支持 HTTP 協議。JavaMail 沒有使用 HTTP
協議來閱讀或發送郵件。使用代理服務器的一個主要原因是為了允許企業網絡中的 HTTP 請求通過企業防火墻。防火墻通常會阻止對 Internet
的大多數訪問,但允許來自代理服務器的請求通過。此外,企業網絡內部的郵件服務器將為郵件執行類似的功能,通過 SMTP 接收消息,然后將它們轉發到
Internet 上的最終目的地,以及接收傳入的消息,然后將它們發送到合適的內部郵件服務器。
如果你的代理服務器支持 SOCKS V4 或 V5 協議 (http://www.socks.nec.com/aboutsocks.html, RFC1928),并允許匿名連接,可以告訴 Java 運行時把所有的 TCP socket 直接連接到 SOCKS 服務器。參閱 http://java.sun.com/j2se/1.4/docs/guide/net/properties.html,獲取 socksProxyHost
和 socksProxyPort
屬性的最新文檔。這些是系統級屬性,而不是 JavaMail 會話屬性。當調用應用程序時,它們可以從命令行中設置,例如:java -DsocksProxyHost=myproxy ...
。這個工具可用于指出從 JavaMail 到 SOCKS 代理服務器進行 SMTP、IMAP 和 POP3 通信。注意,設置這些屬性將告訴 所有 TCP socket 連接到 SOCKS 代理,在應用程序的其他方面上,這可能會帶來負面影響。
假如沒有這樣的 SOCKS 服務器,如果想使用 JavaMail 來直接訪問防火墻外部的郵件服務器,那將需要配置防火墻來允許這一訪問。一個簡單的 HTTP 代理 Web 服務器是足夠的。
問. 如何在 Windows NT 中設置 CLASSPATH?
答:詳細說明可從 這里 獲得。
問. 當試圖在 Linux 中運行程序時,得到了非常奇怪的錯誤消息,而且程序運行失敗了。錯誤在哪里?
答:通常,錯誤消息看起來像下面這樣:
Exception in thread "main"
java.lang.VerifyError:(Class:com/sun/mail/pop3/POP3Store,
method: finalize Signature :()V)
Illegal use of nonvirtual function call
問題是由于在 Linux 上,使用的 unzip 命令是有 bug 的版本,這樣解壓縮 JavaMail 下載包時,unzip 命令破壞了 mail.jar 文件。獲取更新版本的 unzip 命令或使用 JDK 的 jar 命令來解壓縮下載包。
問. 在運行于 SecurityManager 下面的應用程序中,我如何使用 JavaMail;我必須授予應用程序和 JavaMail 什么權限?
答:在
具有 SecurityManager 的 JDK 1.2(或更新版本)中,當使用 JavaMail 時,JavaMail 讀取
mail.jar 文件中的配置文件有時會失敗。在從 activation.jar 文件中讀取配置文件時,JavaBeans
Activation Framework 可能也有相同的問題。這些默認配置文件是作為“資源”文件存儲的,并且存儲在 jar 文件的
META-INF 目錄中。
有許多調試技術可用于決定這是否是個問題。設置 Session 屬性“mail.debug”為 true(或調用 session.setDebug(true)
),
將導致 JavaMail 在試圖加載各個配置文件時打印調試消息。形如“DEBUG: can't load default providers
file”(DEBUG: 不能加載默認提供程序文件) 的消息指出這個問題可能存在。同樣,設置 System
屬性“javax.activation.debug”為“true”(例如,通過使用 "java
-Djavax.activation.debug=true ..." 來運行程序),將導致 JAF
在試圖加載各個資源文件時打印調試消息。最后,通過設置 system 屬性“java.security.debug”
為“access:failure”(例如,通過使用“java -Djava.security.debug=access:failure
...”來運行程序),JDK 可以產生有用的調試輸出。
除了讀取配置文件的必要權限外,應用程序(和 JavaMail)也將需要一定的權限才可以連接到它使用的郵件服務器。如果應用程序使用 System 屬性來配置 JavaMail(例如,像許多 JavaMail 演示程序所做的那樣,通過傳遞從 System.getProperties()
中返回的 Properties 對象到 Session 構造函數),它也將需要一定的權限才可以使用 System Properties
對象。另外,應用程序可以使用自己的 Properties 對象,以及確信設置 "mail.from" 屬性 或 "mail.user" 和
"mail.host" 屬性(參見 InternetAddress.getLocalAddress() 方法)。
在
JDK 1.2 SecurityManager 中,為了使應用程序能夠使用 JavaMail,應用程序、JavaMail 和 JAF
將需要某些權限,比如下面的一些權限(一定要使用適當的值替換主機名和路徑名);把這些權限添加到應用程序使用的安全策略文件中。
grant { // following two permissions allow // access to default config files permission java.io.FilePermission "/path/to/mail.jar", "read"; permission java.io.FilePermission "/path/to/activation.jar", "read"; // following to use SMTP permission java.net.SocketPermission "SMTPHOST:25", "connect,resolve"; // following to use IMAP permission java.net.SocketPermission "IMAPHOST:143", "connect,resolve"; // following to use POP3 permission java.net.SocketPermission "POP3HOST:110", "connect,resolve"; // following needed if System.getProperties() is used permission java.util.PropertyPermission "*", "read,write"; };
|
問. 如何配置 Web 服務器來運行 JavaMail 演示 servlet?
答:針對以下 Web 服務器的指導說明可從這里獲得:
問. 當在 servlet 中使用 JavaMail 時,未找到任何的 JavaMail 類。我已經在服務器的 CLASSPATH 中添加了 mail.jar?
答:當改變 CLASSPATH 時,通常有必要完全重啟 Web 服務器。
問. 我的 servlet 可以找到 JavaMail 類,但 JavaMail 抱怨它不能找到針對“smtp”或“imap”的服務提供程序或地址類型“rfc822”。
答:通常這是因為 JavaMail 無法訪問 mail.jar 中的配置文件,而這可能是由于安全權限問題造成的;參見 本條目,獲取更多的細節。也保證你沒有提取 mail.jar 內容;在服務器的 CLASSPATH 中,應該包括未更改的 mail.jar 文件。
問. 在哪里可以找到 jws.jar?我已經安裝了 Java Web Server 2.0,并試圖運行 JavaMailServlet。README 文件指示我在 CLASSPATH 中添加 jws.jar。
答:jws.jar
不再與 Java Web Server 一起發行(在以前版本中,它們是一起發行的),因此不需要在 CLASSPATH 中添加它。只要在
CLASSPATH 中添加 mail.jar 和 activation.jar,然后重啟 Java Web Server。
編程
問. 從哪里可以學習有關 Internet 郵件的基礎知識,它是我高效編寫 JavaMail 程序需要知道的?
答:參見我們的 Web 頁中提及的 參考圖書 中的一本,獲得有關 Internet 電子郵件、MIME、SMTP、IMAP 和 POP3 等的背景信息。
問. 如何調試使用 JavaMail API 的應用程序?
答:可通過在代碼中調用 Session 對象上的 setDebug(true)
方法來打開調試模式。這將造成在控制臺中打印調試消息,包括協議跟蹤信息。如果您認為在 JavaMail 中發現了
bug,就將這個跟蹤及以下信息發送給我們:重生成問題的測試用例、使用的平臺、使用的 JDK 的版本和使用的郵件服務器 (IMAP, SMTP)
的名稱和版本。
問. 如何發送帶有附件的消息?
答:帶有附件的消息采用 MIME 多部分消息來表示,其中第一部分是消息的主體,其他的部分是附件。有大量的例子,它們展示了如何在演示程序中構建這種消息,JavaMail 下載包包含了這些演示程序。
問. 如何閱讀帶有附件的消息并保存附件?
答:如前面描述,在 MIME 中,帶有附件的消息是作為多部分消息表示的。在簡單的例子中,Message
對象的 getContent
方法的結果將是一個 MimeMultipart
對象。多部分對象的第一個主體部分將是消息的主文本。其他的主體部分將是附件。msgshow.java
演示程序展示了如何在消息中遍歷所有的多部分對象,并提取各個主體部分數據。getDisposition
方法將給你一個提示,指出主體部分是否應該內嵌顯示,或者應該將其考慮成附件(但請注意,不是所有的發件人都提供這一信息)。
為了將主體部分中的數據保存到文件(比如),請使用 getInputStream
方法來訪問附件內容,并將數據復制到 FileOutputStream
。
注意,也有一些更復雜的情形也要處理。例如,一些發件人把主體作為純文本和 html 發送。通常,這將作為 multipart/alternative
內容(和 MimeMultipart
對象)出現在簡單的文本主體部分的位置中。經過數字簽名或加密的消息甚至會更復雜。處理所有的這些情形可能具有挑戰性。請參考各種 MIME 規范和我們主頁上列出的其他 參考資料。
問. 什么是“中斷支持”(disconnected support)?
答:支
持中斷操作的郵件客戶端將允許用戶訪問遠程消息存儲(比如
IMAP)中消息,緩存這些消息中的一些消息的(部分)到本地,然后斷開到服務器的連接。當處在斷開連接狀態中,郵件客戶端可以訪問已經緩存的消息,可能
也可以刪除它們或將它們保存到其他文件夾。當郵件客戶端下一次連接到遠程消息存儲時,本地所做變更會與遠程存儲同步。同樣,中斷支持可以允許客戶端在斷開
與服務器連接時“發送”消息,在到服務器的連接可用前,消息會進行排隊。也請參閱 RFC1733。
問. 如何使用 JavaMail API 來支持中斷操作?
答:JavaMail API 規范定義了一些接口,郵件客戶端可以使用這些接口來支持中斷操作。我們的 IMAP 提供程序實現了這些接口(UIDFolder 接口)。
問. 我如何使用 JavaMail API 來發送安全的電子郵件?
答:JavaMail API 目前不支持發送或接收安全電子郵件。JavaMail API 的體系結構使得可以在以后很容易地添加這一支持,我們可以添加支持,第三方也可以添加支持。有關當前電子郵件安全標準(S/MIME 和 PGP)的信息,可以從如下站點找到: http://www.imc.org/smime-pgpmime.html。 請瀏覽我們的 第三方產品 頁,獲取來自其他供應商的解決方案。
問. writeTo() 方法生成了消息文件,但消息中的一些行既不是數據的規范 MIME 表示(即使用 CRLF 來結束行),又沒有使用我的平臺的規范行分隔符(例如 UNIX 上的“\n”)。如果我需要這些表示時,如何獲得它們當中的任何一種表示?
答:不管是哪種情形,你都將需要創建合適的 FilterOutputStream 對象來傳遞給 writeTo()
。FilterOutputStream 將需要接受特定的一些行,它們具有任何常見終止符,然后寫出另外的一些特定行,它們只具有期望的行終止符。下面是這種過濾器的一些例子。NewlineOutputStream
轉換到本地平臺的行終止符,當將消息寫到文件時,它是有用的。CRLFOutputStream
轉換到 MIME 規范 CRLF 終止符,當需要規范 MIME 格式時(比如計算數字簽名),它是有用的。
問. 我可以使用 JavaMail API 來實現郵件服務器嗎?
答:JavaMail
API 設計目的不是幫你實現郵件服務器。但是,對你來說,一些實用工具類,比如 MIME
消息解析類,可能是有用的。通常您會發現,JavaMail API
是在“簡單”而不是在“強有力”方面出錯。對于郵件客戶端,那是合適的,但對于郵件服務器,結果可能是不同的。
問. 我可以使用 JavaMail API 在我的郵件服務器上添加新的用戶賬戶、刪除用戶賬戶或改變用戶賬戶的密碼嗎?
答:JavaMail API 不包括任何工具,用于添加、刪除或修改用戶賬戶。在這一方面是沒有標準的,每個郵件服務器對它的處理是不同的。
問. 為什么 MimeMessage 類沒有實現 Serializable,這樣我就可以將消息序列化到磁盤,并在以后讀回它?
答:JavaMail API 是在現有電子郵件系統上面設計的,并使用了現有的消息格式。對于這樣的一些實現,使用 Java 序列化能力既不是必要的,也不是有用的,因此,不能將它作為 JavaMail API 的目標來考慮。
有關序列化 Message 的困難部分是保留某些指針,它們指向 Folder(文件夾)、Store(存儲)和 Session(會話)。如果只想保存消息的內容,而不是對象本身,消息的 writeTo
方法將為你完成這一切。如果想根據序列化消息創建整個電子郵件系統,您應該能夠編寫 Message 等的子類,并在子類中實現 Serializable。
如果想序列化自己的引用了 MimeMessages的其他對象,那么你的對象的 writeObject
方法可以使用 MimeMessage 的 writeTo
方法,對象的 readObject
方法可以使用 MimeMessage 構造函數,該構造函數會得到 InputStream。在構造 MimeMessage 時,你的類將需要提供一個 Session。
問. 我如何編寫服務提供程序?
答:請閱讀服務提供程序文檔,獲取一些細節信息。通常,如果想編寫 Store 提供程序,那就編寫 javax.mail.Store
和 javax.mail.Folder
的子類,也可能要編寫 javax.mail.Message
及其他一些類的子類。對于 Transport 提供程序,編寫 javax.mail.Transport
的子類,也可能需要編寫 javax.mail.Message
及其他的一些類的子類。然后在 javamail.providers
注冊表中,添加描述提供程序的條目。如果對編寫特別的服務提供程序感興趣,并且它所針對的協議或郵件系統目前沒有得到 JavaMail API 實現的支持,請通過 javamail@Sun.COM 聯系我們。
問. 我在登錄 Microsoft Exchange 服務器時碰到了麻煩,我確信正在使用的用戶名和密碼是正確的,我做錯了什么?
答:當登錄 Exchange 時,需要使用比簡單登錄名更多的用戶名。例如,如果你的電子郵件地址是“J.User@server.com”,Windows NT 登錄名是“juser”,NT 域名是“dom”,而且 Exahange 郵箱名是“Joe User”,那么在使用 JavaMail 登錄時,你將需要使用用戶名 “dom\juser\J.User”。
問. 在發送二進制文件前,我如何編碼它?當收到它時,我又如何解碼它?
答:你不必這樣的做!JavaMail 將自動決定合適的編碼用于消息部分,然后才發送消息。而且當讀取它們時,將自動解碼消息部分。getInputStream
方法將返回解碼數據。
問. 如果我不需要自己編碼和解碼附件,我應該何時使用 MimeUtility 方法?
答:在 JavaMail 沒有自動處理的情況下,MimeUtility
方法是有用的。經常發生的這樣的一種情形是文件名的編碼。基本的 MIME
spec(規范)不允許按某種方式編碼標題參數值(比如文件名參數),該方式與(比如)編碼
Subject(主題)標題相同。這限制了參數值,從而限制了文件名到 ASCII。但一些發件人卻實際使用 MIME 文本編碼來做非 ASCII
文件名的編碼工作。想與這種非標準發件人互操作的應用程序可以使用 encodeText
方法來編碼文件名,然后調用 MimeBodyPart
setFileName
方法,而且可以使用 decodeText
方法來解碼返回的文件名。
問. 盡管 JavaMail 完成了所有的編碼和解碼工作,但我仍需要手動控制一些主體部分的編碼。
答:在少數的場合需要控制編碼,這里有幾個方法來重寫 JavaMail 的默認行為。下面是一個簡單的方法。在創建整個消息后,調用 msg.saveChanges(),
然后使用像 mbp.setHeader("Content-Transfer-Encoding", "base64")
的語句來強制對指定主體部分做 base64 編碼。
另一種辦法是編寫 MimeBodyPart
的子類,并重寫 updateHeaders
方法,讓它首先調用 super.updateHeaders()
,然后像上面那樣設置 Content-Transfer-Encoding
標題。
問. 為什么 JavaMail 沒有在非 ASCII 字符集中正確編碼和解碼文件名?
答:文件名是作為參數存儲在 MIME 標題中的。形如 =?ISO-8859-15?B?5OTkLUluZm8ucGRm?=
的編碼文件名不是 MIME spec(規范)的一部分。形如 =?A?B?C?=
的文件名是一個完全有效的文件名,而不是一個不正確編碼的文件名。JavaMail 沒有編碼和解碼文件名,因為這樣做會違反 MIME 規范。
基本的 MIME 規范不允許編碼參數。RFC 2231 定義了一種新的方式,使得可以在 MIME 標題中包括編碼參數,包括文件名。它與下面的事實方式不兼容:許多應用程序非法編碼文件名。支持 RFC 2231 將不允許 JavaMail 與這些現有的程序互操作。據我所知,很少現有的程序支持 RFC 2231。
如果你選擇違反 MIME 規范是為了與其他也違反了 MIME的程序互操作,那么 JavaMail 會給您所有需要的工具來完成這件事。
編碼文件名的解決方法是簡單的:
mbp.setFileName(MimeUtility.encodeText(filename));
解碼文件名的解決方法同樣簡單:
String filename = MimeUtility.decodeText(part.getFileName());