import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.Part;
import javax.mail.internet.MimeUtility;
import org.apache.log4j.Logger;
import common.Constants;
/**
* 這是一個解析郵件的工具類,不負責回顯工作,與表示層無關<br>
* 主要的方法是:
* <ul>
* <li>判斷一個郵件體是否附件</li>
* <li>判斷一封郵件是否含有附件</li>
* <li>解析郵件的正文</li>
* </ul>
*
* @author M.Liang Liu
* @date 2007年5月25日16:08:40
*/
public class LmlMessage {
/**
* 得到郵件正文內容 郵件的正文可能是多種類型:
* <ul>
* <li> text/plain </li>
* <li> text/html</li>
* <li> multipart/alternative</li>
* <li> multipart/related:內有內嵌的文件,噢噢~</li>
* <li> mutilpart/* </li>
* <li> message/rfc822 </li>
* </ul>
*
* @param msg:待解析正文的郵件對象或郵件體(郵件的一部分)對象
* @author M.Liang Liu
* @version 1.0
* @since 1.6
* @return 根據郵件類型返回不同的郵件正文
*/
public static String getBody(Part part, String userName) {
Logger logger = Logger.getLogger("LmlMessage.java");
StringBuffer sb = new StringBuffer();
sb.append(new String(""));
try {
logger.debug("The type of the part is:" + part.getContentType());
/**
* 純文本或者html格式的,可以直接解析掉
*/
if (part.isMimeType("text/plain") || part.isMimeType("text/html")) {
sb.append(part.getContent());
} else if (part.isMimeType("multipart/*")) {
/**
* 可供選擇的,一般情況下第一個是plain,第二個是html格式的
*/
if (part.isMimeType("multipart/alternative")) {
Multipart mp = (Multipart) part.getContent();
int index = 0;// 兼容不正確的格式,返回第一個部分
if (mp.getCount() > 1)
index = 1;// 第2個部分爲html格式的哦~
logger.debug("Now will choose the index(start from 0):"
+ index);
/**
* 已經根據情況進行了判斷,就算不符合標準格式也不怕了.
*/
Part tmp = mp.getBodyPart(index);
sb.append(tmp.getContent());
} else if (part.isMimeType("multipart/related")) {
/**
* related格式的,那麼第一個部分包含了body,裏面含有內嵌的內容的鏈接.
*/
Multipart mp = (Multipart) part.getContent();
Part tmp = mp.getBodyPart(0);
String body = LmlMessage.getBody(tmp, userName);
int count = mp.getCount();
/**
* 要把那些可能的內嵌對象都先讀出來放在服務器上,然後在替換相對地址爲絕對地址
*/
for (int k = 1; count > 1 && k < count; k++) {
Part att = mp.getBodyPart(k);
String attname = att.getFileName();
attname = MimeUtility.decodeText(attname);
try {
File attFile = new File(
Constants.tomcat_AttHome_Key, userName
.concat(attname));
FileOutputStream fileoutput = new FileOutputStream(
attFile);
InputStream is = att.getInputStream();
BufferedOutputStream outs = new BufferedOutputStream(
fileoutput);
byte b[] = new byte[att.getSize()];
is.read(b);
outs.write(b);
outs.close();
} catch (Exception e) {
logger
.error("Error occurred when to get the photos from server");
}
String Content_ID[] = att.getHeader("Content-ID");
if (Content_ID != null && Content_ID.length > 0) {
String cid_name = Content_ID[0].replaceAll("<", "")
.replaceAll(">", "");
body = body.replaceAll("cid:" + cid_name,
Constants.server_attHome_Key.concat("/")
.concat(userName.concat(attname)));
}
}
sb.append(body);
return sb.toString();
} else {
/**
* 其他multipart/*格式的如mixed格式,那麼第一個部分包含了body,用遞歸解析第一個部分就可以了
*/
Multipart mp = (Multipart) part.getContent();
Part tmp = mp.getBodyPart(0);
return LmlMessage.getBody(tmp, userName);
}
} else if (part.isMimeType("message/rfc822")) {
return LmlMessage
.getBody((Message) part.getContent(), userName);
} else {
/**
* 否則的話,死馬當成活馬醫,直接解析第一部分,嗚嗚~
*/
Object obj = part.getContent();
if (obj instanceof String) {
sb.append(obj);
} else {
Multipart mp = (Multipart) obj;
Part tmp = mp.getBodyPart(0);
return LmlMessage.getBody(tmp, userName);
}
}
} catch (Exception e) {
return "解析正文錯誤!";
}
return sb.toString();
}
public static String getBody(Message msg, String userName) {
return LmlMessage.getBody((Part) msg, userName);
}
/**
* 判斷一封郵件是否含有附件<br>
* 首先要滿足:msg的mimetype是multipart/*類型的,然後要有某bodyPart的disposition是attachment
*
* @param msg:要判斷是否含有附件的郵件
* @author M.Liang Liu
* @version 1.0
* @see public static boolean isAttachment(Part part)
* @return true:含有附件<br>
* false:不含有附件
*/
public static boolean hasAttachment(Message msg) {
Part part = (Part) msg;
try {
if (part.isMimeType("multipart/*")) {
Multipart mp = (Multipart) part.getContent();
int count = mp.getCount();
for (int i = 0; i < count; i++) {
Part tmp = mp.getBodyPart(i);
if (LmlMessage.isAttachment(tmp))
return true;
}
}
} catch (Exception e) {
return false;
}
return false;
}
/**
* 判斷一個郵件體是否是附件<br>
* 核心代碼主要是解析其頭部的disposition,一般設置了是disposition是attachment的纔是附件
*
* @author M.Liang Liu
* @version 1.0
* @return:如果是附件的話,那麼返回true;<br>
* 否則/異常false;
*/
public static boolean isAttachment(Part part) {
try {
String disposition = part.getDisposition();
if ((disposition != null)
&& ((disposition.equals(Part.ATTACHMENT)) || (disposition
.equals(Part.INLINE))))
return true;
} catch (Exception e) {
/**
* 上面的方法只是適合於附件不是中文,或者中文名較短的情況,<br>
* 附件中文名過長時就不能用了,因爲javamail Api中的part.getDisposition()根本就不能得到正確的數據了<br>
* 捕獲異常後,分別再詳細判斷處理
*/
String contentType = "";
try {
contentType = part.getContentType();
} catch (MessagingException e1) {
return false;
}
if (contentType.startsWith("application/octet-stream"))
return true;
return false;
}
return false;
}
}