轉載http://blog.chinaunix.net/uid-192452-id-3861773.html
這個問題出現有一陣子了,因為一直忙于開發,不是很在意。
一位同僚在自己的計算機測試郵件發送程式時,出現
Exception in thread "main" java.lang.NullPointerException
at javax.mail.internet.MimeUtility.getEncoding(MimeUtility.java:226)
at javax.mail.internet.MimeUtility.getEncoding(MimeUtility.java:299)
at javax.mail.internet.MimeBodyPart.updateHeaders(MimeBodyPart.java:1375)
at javax.mail.internet.MimeBodyPart.updateHeaders(MimeBodyPart.java:1021)
at javax.mail.internet.MimeMultipart.updateHeaders(MimeMultipart.java:419)
at javax.mail.internet.MimeBodyPart.updateHeaders(MimeBodyPart.java:1354)
at javax.mail.internet.MimeMessage.updateHeaders(MimeMessage.java:2107)
at javax.mail.internet.MimeMessage.saveChanges(MimeMessage.java:2075)
at javax.mail.Transport.send(Transport.java:123)
對于javamail 我并不陌生,使用已經超過十年。因為時間的匆忙,發現線上上系統不出問題,是以本機的事情,就忽略了,直到有一天必須本機調試,這才硬着頭皮解決問題。
javamail相對簡單,
出現問題是MimeUtility.getEncoding(MimeUtility.java:226)
代碼如下
finally {
// Close the input stream
try {
is.close();
} catch (IOException ioex) { }
}
is類型 InputStream is = null;
is從ds中得來的,
is = ds.getInputStream();
當時沒有想清楚datasource具體來源,主要還是對源碼不熟。片面的認為是使用上出了問題,
MimeBodyPart.java
static void updateHeaders(MimePart part) 中
if (part.getHeader("Content-Transfer-Encoding") == null)
setEncoding(part, MimeUtility.getEncoding(dh));
隻要設定了Content-Transfer-Encoding了,就不會出現問題,
message.setHeader("Content-Transfer-Encoding", "quoted-printable");
最後發現不行。
冷靜的一思考,ds.getInputStream();來源于DataSource,
protected DataSource ds = null;
DataSource 構造了
public synchronized DataHandler getDataHandler()
throws MessagingException {
if (dh == null)
dh = new MimeBodyPart.MimePartDataHandler(
new MimePartDataSource(this));
return dh;
}
protected DataHandler dh;
如此推理,代碼出現在内容上面,使用DataSource的隻有附件
messageBodyPart = new MimeBodyPart();
DataSource source = new FileDataSource(filename);
messageBodyPart.setDataHandler(new DataHandler(source));
messageBodyPart.setFileName(filename);
multipart.addBodyPart(messageBodyPart);
// Put parts in message
message.setContent(multipart);
// Send the message
Transport.send(message);
出現問題的原因,就是附件不存在。
解決問題很簡單,先使用File判斷一下檔案存在不存在,存在後再調用addBodyPart。
或者 source.getOutputStream().close()
sun的工程師處理也很不合理,source.getFile(),傳回File,直接判斷檔案存在不存在,不存在的話,直接抛出FileNotFoundException
異常。
其實最早就可以判斷不是程式問題,因為釋出後不出現問題,肯定是環境有問題。
作為EDM的開發者,看來也得學習一下linux_china,好好看看 javamail api。