第七講:解析郵件內容
一、JavaMail解析郵件內容的流程
二、解析郵件內容
2.1 解析普通郵件內容
如果Message.getContentType方法返回的MIME類型爲"text/*"則表示郵件內容爲文本內容,此時直接調用Message.getContent方法把郵件內容保存了一個String對象中輸出給瀏覽器即可。但是現實郵件中會有HTML格式的郵件內容時,郵件發送程序爲了防止有些郵件閱讀軟件不能顯示處理HTML格式的數據,通常都會用兩類型分別爲"text/plain"和"text/html"的MIME消息封裝HTML代碼。因此對於這兩種類型要通過判斷之後方可顯示。
下面使用例子來進行判斷:
當含有"text/plain"和"text/html"中時使用Message.getContentType返回的類型爲"multipart/alternative"
public class Demo1 extends HttpServlet {
String host = "pop3.163.com";
String protocol = "pop3";
String username = "XXX";
String password = "XXX";
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=gb2312");
PrintWriter out = response.getWriter();
Properties props = new Properties();
props.setProperty("mail.store.protocol", protocol);
props.setProperty("mail.pop3.host", host);
javax.mail.Session session = javax.mail.Session.getInstance(props);
session.setDebug(false);
try {
Store store = session.getStore(protocol);
store.connect(host, username, password);
Folder folder = store.getFolder("inbox");
folder.open(Folder.READ_WRITE);
Message[] msgs = folder.getMessages();
for(int i=0; i< msgs.length; i++){
String from = msgs[i].getFrom()[0].toString();
String subject = msgs[i].getSubject();
out.print("第"+(i+1)+"封郵件<br/>");
out.print("發件人:"+from);
out.print("主題:"+subject);
/**
* 檢查是否是"multipart/alternative"類型,
* 如果是取出其中的"text/html"類型的消息
*/
if(msgs[i].isMimeType("multipart/alternative")){
Multipart mp = (Multipart)msgs[i].getContent();
int bodynum = mp.getCount();
for(int j=0; j<bodynum; j++){
if(mp.getBodyPart(j).isMimeType("text/html")){
String content = (String)mp.getBodyPart(j).getContent();
out.print("郵件內容:"+content+"<br/>");
out.print("-------------------------------<br/>");
}
else{
out.print("不支持的郵件類型<br/>");
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
2.2 解析“multipart/related”類型的郵件郵件類型爲"multipart/related"的郵件正文中包括圖片,聲音等內嵌資源。IE瀏覽器顯示的類型就是"multipart/related",因此可以通過IE瀏覽器顯示郵件中的內容只需要將生成的文件名稱改爲html然後用瀏覽器打開即可。IE瀏覽器作爲郵件數據顯示工具式,不管郵件體中嵌套多少個內嵌資源,程序只需要向IE瀏覽器輸出郵件體中的數據,並告訴瀏覽器以"message/rfc822"的形式進行處理就可以了。那麼IE瀏覽器就會自動解析並且顯示這種形式的郵件數據。
public class Demo2 extends HttpServlet {
String host = "pop3.163.com";
String protocol = "pop3";
String username = "XXX";
String password = "XXX";
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
ServletOutputStream out = response.getOutputStream();
Properties props = new Properties();
props.setProperty("mail.store.protocol", protocol);
props.setProperty("mail.pop3.host", host);
javax.mail.Session session = javax.mail.Session.getInstance(props);
session.setDebug(false);
try {
Store store = session.getStore(protocol);
store.connect(host, username, password);
Folder folder = store.getFolder("inbox");
folder.open(Folder.READ_WRITE);
/**
* 假設取得第一封郵件是"multipart/related"
* 則直接進行處理
*/
Message msg = folder.getMessage(0);
response.setContentType("message/rfc822");
msg.writeTo(System.out);
msg.writeTo(out);
} catch (Exception e) {
e.printStackTrace();
}
}
}
2.3 使用IE解析正文需要注意的問題一個IE瀏覽器只能處理一種數據類型,而我們在解析內嵌資源的郵件時,從郵件中解析出來的郵件頭信息通常是以"text/html"格式向輸出的,而郵件正文是以"message/rfc822"格式向IE瀏覽器輸出的。因此要想在瀏覽器中顯示符合人們閱讀習慣的郵件信息,即在同一個瀏覽器窗口中即顯示郵件頭信息又顯示郵件正文,就需要對瀏覽器窗口進行分幀,每個幀窗口顯示一種格式的郵件數據。
例如下面的jsp文件用於連接郵件服務器並且緩存Folder對象到會話對象Session中,該文件還定義了兩個證窗口分別用來顯示郵件頭和郵件正文。
<%@ page language="java" import="java.util.*" import="javax.mail.*" pageEncoding="ISO-8859-1"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
String host = "pop3.163.com";
String protocol = "pop3";
String username = "XXX";
String password = "XXX";
Properties props = new Properties();
props.setProperty("mail.store.protocol", protocol);
props.setProperty("mail.pop3.host", host);
javax.mail.Session mailSession = javax.mail.Session.getInstance(props);
mailSession.setDebug(true);
try {
Store store = mailSession.getStore(protocol);
store.connect(host, username, password);
Folder folder = store.getFolder("inbox");
folder.open(Folder.READ_WRITE);
session.setAttribute("folder", folder);
} catch (Exception e) {
e.printStackTrace();
}
%>
<frameset>
<frame src="/receivedMail/displayHeader" scrolling="no">
<frame src="/receivedMail/displayContent" scrolling="no">
</frameset>
2.4 解析郵件附件在Web應用中解析包含附件的郵件時,只需要從Message對象中解析出保存附件數據的BodyPart對象,然後從BodyPart對象中得到附件的輸入流、附件的MIME類型和附件的文件名,並且這些信息輸出給IE瀏覽器。瀏覽器收到信息後,會根據數據的MIME類型彈出相應的對話框提示用戶下載或打開附件。
public class Demo3 extends HttpServlet {
String host = "pop3.163.com";
String protocol = "pop3";
String username = "XXX";
String password = "XXX";
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=gb2312");
PrintWriter out = response.getWriter();
Properties props = new Properties();
props.setProperty("mail.store.protocol", protocol);
props.setProperty("mail.pop3.host", host);
javax.mail.Session mailSession = javax.mail.Session.getInstance(props);
mailSession.setDebug(false);
try {
Store store = mailSession.getStore(protocol);
store.connect(host, username, password);
Folder folder = store.getFolder("inbox");
folder.open(Folder.READ_WRITE);
Message msg1 = folder.getMessage(1);
request.getSession().setAttribute("message", msg1);
String from = msg1.getFrom()[0].toString();
String subject = msg1.getSubject();
String sendDate = DateFormat.getInstance().format(msg1.getSentDate());
out.print("發件人:"+from+"<br/>");
out.print("主題:"+subject+"<br/>");
out.print("發件日期:"+sendDate+"<br/>");
Multipart mp = (Multipart)msg1.getContent();
for(int i=0; i<mp.getCount(); i++){
BodyPart bp =mp.getBodyPart(i);
if(bp.getDisposition()!=null){
String fileName = bp.getFileName();
if(fileName.startsWith("=?")){
fileName = MimeUtility.decodeText(fileName); //需要解析中文名稱的文件名(將中文名稱加入郵件時用encodeText)
}
out.print("附件:");
out.print("<a href=\\receivedMail\\HandleAttach?>"+
"bodynum="+ i +"&&filename= " + fileName + "</a><br/>");
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
下面的文件是在用戶點擊上述的連接時就會自動的現在文件:public class HandleAttach extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html");
HttpSession session = request.getSession();
ServletOutputStream out = response.getOutputStream();
int bodynum = Integer.parseInt(request.getParameter("bodynum"));
String fileName = request.getParameter("filename");
Message message = (Message)session.getAttribute("message");
try {
response.setHeader("Content-Disposition", "attachment;filename="+fileName);
Multipart mp = (Multipart)message.getContent();
BodyPart bp = mp.getBodyPart(bodynum);
InputStream is = bp.getInputStream();
int c=0;
if((c = is.read())!= -1){
out.write(c);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}