今天同事碰到一個問題,使用JAVA MAIL收取郵件時,如果收件人是個列表,且收件人列表是以分號進行分割的,則JAVA MAIL就會出現異常,不能正常解析,抽空看了一眼,自己寫了個簡單demo,很簡單,例如:
複製代碼代碼如下:
@Test
public void testReceiveMail() {
try {
String host = "pop3.163.com";
Properties pops = new Properties();
pops.put("mail.pop3.host", host);
pops.put("mail.pop.auth", "true");
Session session = Session.getDefaultInstance(pops, null);
Store store = session.getStore("pop3");
//連接郵件伺服器
store.connect(host, "chb_go", "3870359346");
//收取收件匣
Folder inbox = store.getDefaultFolder().getFolder("INBOX");
//只讀足夠了
inbox.open(Folder.READ_ONLY);
//得到所有郵件列表
Message[] msg = inbox.getMessages();
FetchProfile profile = new FetchProfile();
profile.add(FetchProfile.Item.ENVELOPE);
inbox.fetch(msg, profile);
for (int i = 0; i < msg.length; i++) {
System.out.println("============================================= ====");
System.out.println("主題:"+msg[i].getSubject());
InternetAddress[] toAddress = (InternetAddress[]) msg[i].getRecipients(Message.RecipientType.TO);
for(InternetAddress adress:toAddress){
System.out.println(adress.getAddress());
}
}
//關閉開啟的資源
if (inbox != null)
inbox.close(true);
if (store != null)
store.close();
} catch (NoSuchProviderException e) {
e.printStackTrace();
} catch (MessagingException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
很簡單,可以正常收取郵件、正常顯示收件者清單;但是當連接一個內部郵件伺服器,並且收件者是以分號為分隔符號的郵件時,確實無法正常顯示收件者。
找了一下規範,發現FRC 822規定:收件人之間是要求以逗號為分割,看來分號分割不是標準的分隔符,如下:
複製代碼代碼如下:
destination = "To" ":" 1#address ; Primary
/ "Resent-To" ":" 1#address
/ "cc" ":" 1#address ; Secondary
/ "Resent-cc" ":" 1#address
/ "bcc" ":" #address ; Blind carbon
/ "Resent-bcc" ":" #address
而#語法表示一個列表,列表之間的內容以逗號進行分割,例如:
複製代碼代碼如下:
2.7. #RULE: LISTS
A construct "#" is defined, similar to "*", as follows:
<l>#<m>element
indicating at least <l> and at most <m> elements, each separated by one or more commas (","). This makes the usual form of lists very easy; a rule such as '(element *("," element ))' can be shown as "1#element". Wherever this construct is used, null elements are allowed, but do not contribute to the count of elements present. That is, "(element),,(element)" is permitted, but counts as only two elements. Therefore, where at least one eleele- ment is required, at least one non-null element must be present. Default values are 0 and infinity so that "#(element)" allows any number, including zero; "1#element" requires at least one; and "1#2element" allows one or two.
JAVA MAIL嚴格依照RFC 822規範操作,沒有對分號做處理。大多數郵件伺服器都是嚴格遵循RFC 822規範的,例如Lotus Notes、gmail(gmail的收件者是不能輸入分號的,甚至會自動替換成逗號,讚一個);但是,大家也會發現平時發送郵件,常以分號做分割,這是因為微軟的一些郵件工具,如:outlook、outlook Express或是其MAPI,則是以分號為分隔符號的,又因為outlook使用使用者非常廣泛,甚至很多人會認為分號分隔才是規範,強烈鄙視Microsoft!不規範的東西太多了! !
如果夠倒霉,真的碰到了習慣使用分號作為分割符的用戶,而其郵件伺服器又不會自動將分號替換為逗號,那我們只能透過程式做相容了,可以考慮修訂JAVA MAIL源碼,修改
InternetAddress類別的parse方法,這裡源碼就不展現了,大家只需將對於分號的處理修改成和逗號一樣即可(但是分號在FRC 822中也有定義,這麼修改有可能引起隱患,大家慎重) 。