使用 C# 讀取 Outlook .msg 檔
0 |
先前分享過透過 EWS 從 Exchange 收信接任務執行作業的定期排程,最近生出小副本。程式需從 Mail 取出 HTML 解析,因格式並不統一,解析邏輯需要有點彈性,以便從不同格式中取出所需資訊(類似爬網頁,考驗 HtmlAgilityPack 跟 Regular Expression 技巧)。為了確保解析結果正確,我需要大量樣本在每次調整後重新驗證,以免為了改 A 把 B 弄壞。現成樣本好找,使用者 Outlook 收件匣由就有一大堆實例,最笨但有效的做法是請使用者一封封轉寄到 Exchange 信箱,再跑程式收下來。不過,能自動化處理的事搞成手工藝不是我的風格。Outlook 裡的郵件拖到桌面或檔案總管會自動轉存成 .msg 檔,請使用者將樣本 Mail 存成 .msg 再壓成 ZIP 檔一次寄給我,不需做苦工,剩下我來處理。
嘴上說得豪氣,我知道 .msg 可以用 Outlook 開啟,但要怎麼用程式讀取呀?以前沒玩過,直覺肯定有解,爬文也真找到不少選項:
- 有不少 MSG to HTML 的線上轉換服務,例如:ZAMZAR、ACONVERT.COM... 等等。寫程式操作網頁介面不是難事,但上傳到第三方服務有機密外流風險,母湯啊母湯。
- 商業元件: Aspose.Email for .NET、MailBee.NET Outlook Converter
- 開源程式庫:MSGReader
- 看 .msg 規格自己寫:MS-OXMSG: Outlook Item (.msg) File Format (我沒瘋,謝謝!)
- 使用 Outlook API
由於屬一次性工作又在我的個人電腦執行就好,不想花時間研究新東西,我的電腦有現成的 Outlook,用 Outlook 解決最快。
第一步是在專案加入 COM 參照 - Microsoft Outlook 16.0 Object Library:
程式挺簡單,參考 MS Docs 上的範例,檢查 Outlook 是否已在執行中,若是就用現成的,否則 new Microsoft.Office.Interop.Outlook.Application() 建一個新的。 Application.Session 有個 OpenSharedItem() 方法,可用來開啟 .ics ( iCalendar 日曆數據交換約會資料)、.vcf (連絡人資訊) 或 .msg (電子郵件)。用 OpenSharedItem(.msg 路徑) 開啟 .msg 檔再轉型為 Microsoft.Office.Interop.Outlook.MailItem,接下來即可從 HtmlBody 屬性取得郵件 HTML 內容:
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using Outlook = Microsoft.Office.Interop.Outlook;
namespace MiscTools
{
/// <summary>
/// 從 Outloook 郵件 .msg 檔擷取 HTML 內容
/// </summary>
public static class MsgHtmlExtrator
{
public static Dictionary<string, string> ConvToHtmls(string[] msgFilePaths)
{
//若 Outlook 已開啟,用現成的 Instance,否則新建
var existing = Process.GetProcessesByName("OUTLOOK").Any();
Outlook.Application outlookApp =
existing ?
Marshal.GetActiveObject("Outlook.Application") as Outlook.Application:
new Outlook.Application();
var result = new Dictionary<string, string>();
foreach (var msgFilePath in msgFilePaths)
{
var mail = (Outlook.MailItem)outlookApp.Session.OpenSharedItem(msgFilePath);
result.Add(msgFilePath, mail.HTMLBody);
}
if (!existing) outlookApp.Quit();
return result;
}
public static string ConvToHtml(string msgFilePath)
{
return ConvToHtmls(new string[] { msgFilePath }).First().Value;
}
}
}
由於啟動與執行 Outlook 成本較高,大量轉換時會採取一次傳入所有 .msg 路徑批次處理後傳回的策略,以減少資源損耗。搞定收工~
Example of reading HTML from Outlook .msg file with Outlook API.
Comments
Be the first to post a comment