程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> VC >> 關於VC++ >> VC++實現Foxmail郵件的批量導出

VC++實現Foxmail郵件的批量導出

編輯:關於VC++

引言

在中國Foxmail早已成為收發郵件的首選軟件,其功能也早已超越Outlook,但是Foxmail也並非盡善盡美,尤其是在對郵件夾內郵件的導出、備份的處理上做的不是太好,只能手工一封一封將信導出,如果信件數目較少這樣處理還可以應付,但如果對於成百上千封郵件仍這樣處理顯然是相當困難的。為此,本文通過對Foxmail郵件夾文件的分析而給出了一種通過程序自動將某個郵件夾中的所有郵件導出到指定文件夾的方法。

Foxmail郵件夾組成分析

為了能編程實現對Foxmail郵件夾的處理,首先要對Foxmail的郵件夾和內部郵件的組成方式及其采取的存放格式有一個清楚的認識。進入到Foxmail的安裝目錄,然後發一封郵件給自己,把信接收後,查看安裝目錄下各個文件的時間屬性,發現只有fmnmtk.dat文件是最新的,但該文件大小遠遠小於所發郵件,因此應當排除。mail文件夾中的子目錄對應Foxmail賬號。進入某個帳號所對應的文件夾,文件夾中的in、out、send和trash等文件分別對應收件夾、發件夾、已發送文件夾和廢件箱。

在明確了郵件夾所對應的存儲文件後,可以通過二進制查看軟件來進一步分析郵件夾的內部結構組成。根據目前的情況可以斷定某個郵件夾內的郵件均存放在同一個文件中,因此本文對郵件夾內郵件的批量導出問題可以轉化為從郵件夾文件中分離出各個郵件並將其輸出到外部文件的問題。這樣,在對郵件夾文件內部結構組成的分析時,只需關心兩封郵件的邊界即可。打開某個郵件夾文件,可以看到開始一段16進制內容為:

10 10 10 10 10 10 10 11 11 11 11 11 11 53 0D 0A 52 65 74 75 72 6E 2D 50 61 74 68 3A 20 3C 7A 68

這裡,開始一段代碼非常規整,因此可以猜測為文件的格式頭或是各個郵件的格式頭,在文件內對前7個10和6個11共13個字符進行搜尋,可以發現存在有許多相同字符,而且搜尋到的字符鄰近幾個字符"53"、"0D"和"0A"也同時出現,其後的字符則不固定,因此可以進一步假定這16個字符為郵件的格式頭而非文件的格式頭(文件格式頭通常只在文件開始處出現一次),再在郵件夾文件中對這16個字符進行搜尋並記錄搜尋到的次數,可以發現正好同郵件夾中的郵件數目相吻合,而且在刪除或增添郵件後,該數目也會相應變化。根據以上情況可以斷定"10 10 10 10 10 10 10 11 11 11 11 11 11 53 0D 0A"是郵件的格式頭,根據此頭可以分離出郵件。

程序的設計實現

在弄清楚Foxmail郵件夾文件的組成結構後,對內部郵件的提取、導出就不是什麼難事了,編程的中心思想是對郵件格式頭的判別,並對位於其後郵件內容數據的文件導出。為此,可以對全部郵件夾文件內容搜尋ASCII碼10(16進制),一旦發現該字符說明其後15個字節有可能是郵件格式頭,然後繼續判斷其後15個字節是否滿足郵件格式頭,一旦某個字節不符合則表明其並非郵件格式頭而不予處理,否則開始將郵件數據寫入導出文件,同時關閉上一封打開過的導出文件:

//從郵件夾文件讀取字符
c = fgetc(fp1);
while (!feof(fp1))
{
  //發現有分隔特征串的開頭字符, 則進入check()函數進行分析
  if (c == 0x10)
   check();
  //生成輸出文件名
  j++;
  filename.Format("%d",j);
  //確定待導出文件的存放路徑
  char exeFullPath[MAX_PATH];
  CString strPath;
  GetModuleFileName(NULL, exeFullPath, MAX_PATH);
  strPath = CString(exeFullPath);
  strPath = strPath.Left(strPath.ReverseFind('\\'));
  strPath = strPath + "\\mail\\" + CString(filename) + ".eml";
  strcpy(fullname, strPath);
  //以寫方式打開導出文件,如果文件不存在則創建之
  fp2 = fopen(fullname, "w");
  //沒有到輸入文件的結尾, 又不是分隔特征串的開頭字符, 則將字符寫入輸出文件
  while (!feof(fp1) && (c = fgetc(fp1)) != 0x10)
   fputc(c, fp2);
}

其中,對於郵件格式頭的判斷是在check()函數中完成的,依次對0x10之後的15個字節進行判斷,一旦發現不是郵件格式頭字符,立即返回,並將其當作郵件內容數據進行處理只有在斷定為郵件格式頭後才將上一封導出文件關閉:

for (int i = 0; i < 6; i++)
{
c = fgetc(fp1);
//不符合分隔特征串,則返回
if(c != 0x10)
return;
}
for (i = 0; i < 6; i++)
{
c = fgetc(fp1);
//不符合分隔特征串,則返回 由此可以斷定郵件夾的內容
if (c != 0x11)
return;
}
if ((c = fgetc(fp1)) == 0x53)
if ((c = fgetc(fp1)) == 0x0D)
if ((c = fgetc(fp1)) == 0x0A)
{
c = fgetc(fp1);
//完全符合特征串,則當前郵件輸出完畢, 關閉輸出文件
fclose(fp2);
}

由於本程序的設計目的在於自動批量導出郵件,因此處理數據量一般是比較大的,為避免程序阻塞,可以將此處理過程放置於線程之中進行。經實驗,由上述程序導出的eml文件可以為OutLook文件識別並打開,達到了預期目的。

小結

本文通過對Foxmail郵件夾的組成結構進行分析而最終實現了對其郵件的批量導出,極大方便了對Foxmail郵件的備份、管理等工作,而且對不同版本的Foxmail均有很好的支持(當前最新版本為4.2,本文方法適用),因此不失為一款實用的郵件輔助管理工具。本文所述代碼在Windows 2000 Professional下由Microsoft Visual C++ 6.0編譯通過。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved