最近上課時,用到了JavaMail。JavaMail可以使用POP3協議接受郵件,可用來實現郵件發佈文章功能。那麼具體該怎麼做呢?這就必須先要明白帶附件的郵件的格式。當收到郵件後進行解析,我們可以看到如下的郵件代碼(注意爲了便於閱讀,已經將分隔符替換爲比較容易閱讀的格式):
Received: from 127.0.0.1 by FMS4711; Fri, 25 Jul 2008 13:02:36 +0800 Content-Type: multipart/mixed; This is a multi-part message in MIME format. --===========分割一============ --===========分割2================= Body --===========分割2================= <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> --===========分割2=================-- --===========分割一============ /9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0a --===========分割一============ OAAAAPgb7GHGsCG8a8W48hC9ihdb8CcIlHlKXcYwNP+8dPRB30zrsI2K4TPJP0gYLB3Cua0JRtBL --===========分割一============-- |
<?xml:namespace prefix = o />
它對應JavaMail的Message對象,一個Message對象又會有多個子對象如MultiPart對象,更特殊的是整個郵件內容爲一個大的MultiPart,然而郵件的正文則在嵌套的一個子MultiPart中,如果不瞭解這種組織結構,就可能無法正確獲得郵件的正文。此結構如下圖所示:
郵件Message
|
有了這些資料,我們就可以來解析郵件了,代碼如下:
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Properties;import javax.mail.Address;
import javax.mail.BodyPart;
import javax.mail.FetchProfile;
import javax.mail.Flags;
import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.NoSuchProviderException;
import javax.mail.Part;
import javax.mail.Session;
import javax.mail.Store;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMultipart;/**
* 郵件接受測試
*
*/
public class POP3MailReceiverTest {public POP3MailReceiverTest() {
try {
// 1. 設置連接信息, 生成一個 Session
Properties props = new Properties();
props.put("mail.transport.protocol", "pop3");// POP3 收信協議
props.put("mail.pop.port", "110");
// props.put("mail.debug", "true");// 調試Session session = Session.getInstance(props);
// 2. 獲取 Store 並連接到服務器
Store store = session.getStore("pop3");
store.connect("localhost", "[email protected]", "1234");
// 3. 通過 Store 打開默認目錄 Folder
Folder folder = store.getDefaultFolder();// 默認父目錄
if (folder == null) {System.out.println("服務器不可用");
return;
// System.exit(1);
}// System.out.println("默認信箱名:" + folder.getName());
//
// Folder[] folders = folder.list();// 默認目錄列表
//
// System.out.println("默認目錄下的子目錄數: " + folders.length);Folder popFolder = folder.getFolder("INBOX");// 獲取收件箱
popFolder.open(Folder.READ_WRITE);// 可讀郵件,可以刪郵件的模式打開目錄
// 4. 列出來收件箱 下所有郵件
Message[] messages = popFolder.getMessages();
// 取出來郵件數
int msgCount = popFolder.getMessageCount();
System.out.println("共有郵件: " + msgCount + "封");// FetchProfile fProfile = new FetchProfile();// 選擇郵件的下載模式,
// 根據網速選擇不同的模式
// fProfile.add(FetchProfile.Item.ENVELOPE);
// folder.fetch(messages, fProfile);// 選擇性的下載郵件// 5. 循環處理每個郵件並實現郵件轉爲新聞的功能
for (int i = 0; i < msgCount; i++) {
Message msg = messages[i];// 單個郵件
// 發件人信息
Address[] froms = msg.getFrom();
if(froms != null) {
System.out.println("發件人信息:" + froms[0]);
InternetAddress addr = (InternetAddress)froms[0];
System.out.println("發件人地址:" + addr.getAddress());
System.out.println("發件人顯示名:" + addr.getPersonal());
}
News news = new News();// 生成新聞對象
System.out.println("郵件主題:" + msg.getSubject());
news.setTitle(msg.getSubject());// getContent() 是獲取包裹內容, Part 相當於外包裝
Multipart multipart = (Multipart) msg.getContent();// 獲取郵件的內容, 就一個大包裹,
// MultiPart
// 包含所有郵件內容(正文+附件)
System.out.println("郵件共有" + multipart.getCount() + "部分組成");// 依次處理各個部分
for (int j = 0, n = multipart.getCount(); j < n; j++) {
System.out.println("處理第" + j + "部分");
Part part = multipart.getBodyPart(j);//解包, 取出 MultiPart的各個部分, 每部分可能是郵件內容,
// 也可能是另一個小包裹(MultipPart)// 判斷此包裹內容是不是一個小包裹, 一般這一部分是 正文 Content-Type: multipart/alternative
if (part.getContent() instanceof Multipart) {
Multipart p = (Multipart) part.getContent();// 轉成小包裹
System.out.println("小包裹中有" + p.getCount() + "部分");
// 列出小包裹中所有內容
for (int k = 0; k < p.getCount(); k++) {
System.out.println("小包裹內容:" + p.getBodyPart(k).getContent());
System.out.println("內容類型:"
+ p.getBodyPart(k).getContentType());
if(p.getBodyPart(k).getContentType().startsWith("text/plain")) {
// 處理文本正文
news.setBody(p.getBodyPart(k).getContent() + "");
} else {
// 處理 HTML 正文
news.setBody(p.getBodyPart(k).getContent() + "");
}
}
}// Content-Disposition: attachment; filename="String2Java.jpg"
String disposition = part.getDisposition();// 處理是否爲附件信息
if (disposition != null) {System.out.println("發現附件: " + part.getFileName());
System.out.println("內容類型: " + part.getContentType());
System.out.println("附件內容:" + part.getContent());
java.io.InputStream in = part.getInputStream();// 打開附件的輸入流
// 讀取附件字節並存儲到文件中
java.io.FileOutputStream out = new FileOutputStream(part.getFileName());
int data;
while((data = in.read()) != -1) {
out.write(data);
}
in.close();
out.close();
}
}
// }
// TODO newsDAO.save(news); // 將郵件所攜帶的信息作爲新聞存儲起來// 6. 刪除單個郵件, 標記一下郵件需要刪除, 不會真正執行刪除操作
// msg.setFlag(Flags.Flag.DELETED, true);
}// 7. 關閉 Folder 會真正刪除郵件, false 不刪除
popFolder.close(true);
// 8. 關閉 store, 斷開網絡連接
store.close();
} catch (NoSuchProviderException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}/**
* @param args
*/
public static void main(String[] args) {
new POP3MailReceiverTest();}
}