blogspot.com-GA4

星期四, 11月 12, 2009

(轉)javaMail編碼

javaMail編碼 2007-03-05 下午 09:15

郵件頭(參見RFC822,RFC2047)只能包含US-ASCII字元。郵件頭中任何包含
非US-ASCII字元的部分必須進行編碼,使其只包含US- ASCII字元。所以使用
java mail發送中文郵件必須經過編碼,否則別人收到你的郵件只能是亂碼一堆。
不過使用java mail 包的解決方法 很簡單,用它自帶的MimeUtility工具中encode
開頭的方法(如encodeText)對中文資訊進行編碼就可以了。

例子:

MimeMessage mimeMsg = new MimeMessage(mailSession);

//讓javamail決定用什?方式來編碼 ,編碼內容的字元集是系統字元集
mimeMsg.setSubject( MimeUtility.encodeText( Subject) );

//使用指定的base64方式編碼,並指定編碼內容的字元集是gb2312

mimeMsg.setSubject( MimeUtility.encodeText( Subject,"gb2312","B"));

通常對郵件頭的編碼方式有2種,一種是base64方式編碼,一種是QP
(quoted-printable)方式編碼,javamail根據具體情況來選擇編碼方式。

如"txt測試”編碼後內容如下:

=?GBK?Q?Txt=B2=E2=CA=D4

裏面有個=?GBK?Q?,GBK表示的是內容的字元集,?Q?表示的是以QP方式編
碼的,後面緊跟的才是編碼後的中文字元。所以用MimeUtility工具編碼後的資
訊裏包含了編碼方式的資訊。

郵件的正文也要進行編碼,但它不能用MimeUtility裏的方法來編碼。郵件正文
的編碼方式的資訊是要放在Content-Transfer- Encoding這個郵件頭參數中的,而
MimeUtility裏面的方法是將編碼方式的資訊放在編碼後的正文內容中。所以如
果你對正文也用 MimeUtility進行處理,那?其他郵件程式就不會正常顯示你編
碼的郵件,因?其他郵件軟體如outlook,foxmail只會根據
Content-Transfer-Encoding這個裏面的資訊來對郵件正文進行解碼。

其實,郵件正文部分的編碼javamail已經自動幫你做了,當你發送郵件的時候,
它會自己決定編碼方式,並把編碼方式的資訊放入Content- Transfer-Encoding這
個郵件頭參數中,然後再發送。所以你所要做的就是直接把郵件正文的內容放入
郵件中就可以了。

對郵件正文的編碼方式比較多,包括了base64和QP方式,還有一些如7bit,8bit
等等,因?javamail自動?郵件正文編碼,所以我就不一一祥敘了。

例子:

//處理郵件正文

MimeBodyPart mbp=new MimeBodyPart();
if ( ContentType() == null || ContentType.equals(""))
mbp.setText( Content );
else
mbp.setContent( Content, Content );

解碼


javamail包中的MimeUtility工具中也提供了對郵件資訊解碼的方法,都是以
decode開頭的一些方法(如decodeText)

例子:

String Subject = mimemsg.getSubject();
String ChSubject = MimeUtility.decodeText(Subject);

對於base64和QP編碼後資訊,decode* 方法能將他們正確的解碼,但是,如果
指定的字元集不對,那?javamail就會出現錯誤,不能正確地將其解碼。

如有的郵件系統將”txt測試”編碼後如下:

=?x-unkown?Q?Txt=B2=E2=CA=D4

這裏指定的字元集是x-unknown,是非明確的字元集,javamail就不能正確的處
理了,但是”測試”這兩個中文字還是按照gbk字元集編碼的,所以你可以手工
的將編碼方式資訊改正確,再用decode*方法來解碼。

例子:

if ( str.indexOf("=?x-unknown?") >=0 ){
str = str.replaceAll("x-unknown","gbk" ); // 將編碼方式的資訊由x-unkown改?
gbk

try{

str = MimeUtility.decodeText( str ); //再重新解碼

}catch( Exception e1){

return str ;

}

decode*方法都是根據在編碼資訊中包含的編碼方式的資訊來解碼,所以decode*
方法對郵件正文解碼是無效的,因?郵件正文中不包含編碼方式的資訊。

同編碼一樣,郵件正文的解碼也是由javamail做了。Javamail根據
Content-Transfer-Encoding裏的資訊,來對郵件的正文解碼。

客戶程式從javamail取得的正文內容字元集?iso-8859-1,所以還要將字元集轉換
一下,例:

String CorrectContent = new String( Content.getbytes("iso-8859-1"),"gb2312");

CorrentContent?正確的郵件正文了

沒有留言: