?郵件列表服務經常用于為工作組提供基于email的討論環境,訂閱者通過它討論共同感興趣的問題。


   本文提供的示例程序ListServer是一個簡單的郵件列表轉發服務器:它從指定帳號讀取新郵件并發送給所有訂閱者。Java Mail API不僅使得實現其基本功能相當簡單(使用缺省的POP3和SMTP),而且保證了程序易于支持任何可能遇到的系統環境。


   運行該程序需要包含以下支持文件:Java Mail (mail.jar)、JAF(activation.jar)以及缺省的POP3支持(pop3.jar),如下面DOS批命令文件所示(這些JAR文件可以從Sun的Java Mail主頁下載,參見相關資源):


   @echo off


   PATH .;d:\jdk1.1\bin


   set CLASSPATH=.;d:\jdk1.1\lib\classes.zip;activation.jar;mail.jar;pop3.jar


   java ListServer %1 %2 %3 %4 %5 %6 %7 %8 %9


   程序啟動后先由main()過程讀取命令行參數,如郵件服務器、郵件帳號、更新周期等。接下來創建ListServer實例,最后進入“讀取新郵件并轉發給訂閱者/等待直到下一次檢查時間到來”無限循環。ListServer的核心功能(即讀取和轉發所有新郵件)在process()過程實現,其主要操作過程為:


   ◆獲取javax.mail.Session實例,并進而獲得javax.mail.Store實例。


   ◆利用javax.mail.Store實例獲得缺省收件箱(INBOX)javax.mail.Folder實例。


   ◆使用javax.mail.Folder對象提取新郵件,存儲為javax.mail.Message對象數組。


   ◆創建javax.mail.FetchProfile以(潛在地)優化對特定郵件組成成分的提取。


   請注意此處javax.mail.FetchProfile類的應用。FetchProfile類提供郵件協議提供者特有可選參數,其目的是更有效地實現郵件組成成分的預提取。Java Mail API鼓勵延遲提取郵件成分——即僅在真正需要的時候才提取。這不僅有利于改善系統的響應時間,某些操作(如顯示郵件標題列表)也能夠從中得到好處。下面代碼說明了FetchProfile的基本用法:


   // 提取所有郵件的屬性和標記

Message[] messages = folder.getMessages();

FetchProfile fp = new FetchProfile();

fp.add(FetchProfile.Item.ENVELOPE);

fp.add(FetchProfile.Item.FLAGS);

fp.add("X-Mailer");

folder.fetch(messages, fp);



   sendMsg()過程由processMsg()調用,負責分析指定收件并將它轉發給所有訂閱者。它首先獲得缺省Session實例,然后創建javax.mail.Transport對象發送消息:


   // 設置屬性并獲得缺省進程實例

Properties props = new Properties();

props.put("mail.smtp.host", _smtpHost);

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

......

// 發送消息

Transport transport = session.getTransport(SMTP_MAIL);

transport.connect(_smtpHost, _user, _password);

transport.sendMessage(newMessage, _toList);



   郵件字段(如收件人、發件人、郵件主題和日期等)的設置方法如下:


   // 創建新郵件 Address replyToList[] = { new InternetAddress(replyTo) };

Message newMessage = new MimeMessage(session);

if (_fromName != null)

newMessage.setFrom(new InternetAddress(from,

_fromName + " / " + replyTo));

else

newMessage.setFrom(new InternetAddress(from));

newMessage.setReplyTo(replyToList);

newMessage.setRecipients(Message.RecipientType.BCC, _toList);

newMessage.setSubject(subject);

newMessage.setSentDate(sentDate);



   填寫郵件內容應該區分其類型(純文本和復合內容使用不同方法):


   // 填寫郵件內容 Object content = message.getContent(); //原郵件內容

String debugText = "主題: " + subject + ", 發送日期: " + sentDate;

if (content instanceof Multipart)

{

debugMsg("轉發復合內容郵件 (" + debugText + ")");

newMessage.setContent((Multipart)message.getContent());

}

else

{

debugMsg("轉發純文本郵件 (" + debugText + ")");

newMessage.setText((String)content);

}




   可以看到,javax.mail.internet.MimeMessage內容讀取例程getContent()只需要一次調用就可以讀取復雜的分級復合郵件。