程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> 關於C# >> 利用C#大幅提高OUTLOOK的郵件搜索能力

利用C#大幅提高OUTLOOK的郵件搜索能力

編輯:關於C#

使用OUTLOOK, 你有沒有遇到過上圖的問題? 多達18419封郵件! 太多了, 每次想找一個郵件都非常 耗時, 想辦法解決這個問題成了一件非常緊迫的事情. 利用MS Search當然可以, 但是它太heavy了, 而 且不支持如邏輯搜索表達式等復雜查找功能, 怎麼辦? 幸運的是我有WEBUS2.0 SDK, 於是我決定自己開 發一個名為Outlook Searcher (Outlook搜索精靈) 的小工具.

Outlook搜索精靈主要包含兩個功能:

1. 讀取Outlook中的郵件信息並創建全文索引;

2. 提供搜索功能, 支持各種復雜的邏輯表達式.

先看看如何讀取Outlook:

引用COM組件:

我這裡引用的是9.4版本. 對應Outlook2010. 然後添加訪問Outlook的代碼:

using Outlook = Microsoft.Office.Interop.Outlook;
    
...
    
Outlook.Application OutlookApp;
Outlook.NameSpace OutlookNS;
Outlook.MAPIFolder Inbox;
Outlook.MAPIFolder Sentbox;
    
...
    
void InitOutlookApp()
{
    if (OutlookApp == null)
    {
        OutlookApp = new Outlook.Application();
        OutlookNS = OutlookApp.GetNamespace("MAPI");
        Inbox = OutlookNS.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox); //獲取默認的收件箱
        Sentbox = OutlookNS.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderSentMail); 

//獲取默認的已發郵件
    }
}

Outlook以Folder的方式來管理收件箱, 發件箱, 已發郵件等. 一般情況下, 我們接收的郵件都在 "收件箱"中, 發出的郵件都在"已發郵件"中, 因此我們從這兩個文件夾中獲取郵 件信息. 為了更加方便使用, 我創建了一個MailInfo類型來存放需要索引的郵件內容:

public class MailInfo
{
    public string EntryId { get; set; }
    public string Folder { get; set; }
    public string From { get; set; }
    public string Subject { get; set; }
    public string ConversationId { get; set; }
    public string Body { get; set; }
    public string To { get; set; }
    public Document ToDoc()
    {
        var doc = new Document();
        doc.Fields.Add(new Field("EntryId", this.EntryId, Webus.Documents.FieldAttributes.None));
        doc.Fields.Add(new Field("Folder", this.Folder, Webus.Documents.FieldAttributes.Index));
        doc.Fields.Add(new Field("From", this.From, Webus.Documents.FieldAttributes.Index));
        doc.Fields.Add(new Field("Subject", this.Subject, Webus.Documents.FieldAttributes.AnalyseIndex));
        doc.Fields.Add(new Field("ConversationId", this.ConversationId, Webus.Documents.FieldAttributes.Index));
        doc.Fields.Add(new Field("Body", this.Body, Webus.Documents.FieldAttributes.AnalyseIndex));
        doc.Fields.Add(new Field("To", this.To, Webus.Documents.FieldAttributes.Index));
        return doc;
    }
    public MailInfo()
    {
    
    }
    public MailInfo(Document doc)
    {
        this.EntryId = doc.GetField("EntryId").Value.ToString();
        this.Folder = doc.GetField("Folder").Value.ToString();
        this.From = doc.GetField("From").Value.ToString();
        this.Subject = doc.GetField("Subject").Value.ToString();
        this.ConversationId = doc.GetField("ConversationId").Value.ToString();
        this.Body = doc.GetField("Body").Value.ToString();
        this.To = doc.GetField("To").Value.ToString();
    }
}

它還兼具了Mapping的功能, 能夠在MailInfo和Webus.Document之間進行轉換. 並且為每個字段都設 定了索引選項. 現在一切就緒, 只欠東風了. 廢話少說, 直接上代碼:

先創建索引對象:

IIndexer IndexAccessor = null;
...
private void frmOutlookSearcher_Load(object sender, EventArgs e)
{
    ...
    this.IndexAccessor = new IndexManager(new MailAnalyzer()); //用MailAnalyzer作為分析器
    this.IndexAccessor.MaxIndexSize = int.MaxValue; //索引大小無限制
    this.IndexAccessor.MinIndexSize = int.MaxValue; //索引大小無限制
    this.IndexAccessor.MergeFactor = int.MaxValue; //不做merge
    ...
}
...
private void IndexProc()
{        
    IndexAccessor.OpenOrNew(AppDomain.CurrentDomain.BaseDirectory + @"Index"); 

//索引數據放在運行目錄的"Index"文件夾裡面
    ...
    //讀取outlook, 添加文檔到索引
    ...

}

再循環讀取郵件並添加索引文檔:

while(...)
{
    //先讀取inbox
    for (; InboxIndx <= Inbox.Items.Count; InboxIndx++)
    {
        ...
        this.InitOutlookApp();
        var item = Inbox.Items[InboxIndx];
        if (item is Outlook.MailItem) //注意, 並非每個inbox的item都是mailItem, 因此要做個類型檢查, 否則程序會掛起, 死在那兒.
        {
            Outlook.MailItem mailItem = item as Outlook.MailItem;
            var mailInfo = new MailInfo()
            {
                EntryId = string.IsNullOrEmpty(mailItem.EntryID) ? string.Empty : mailItem.EntryID,
                From = string.IsNullOrEmpty(mailItem.SenderEmailAddress) ? string.Empty : mailItem.SenderEmailAddress,
                ConversationId = string.IsNullOrEmpty(mailItem.ConversationID) ? string.Empty : mailItem.ConversationID,
                Subject = string.IsNullOrEmpty(mailItem.Subject) ? string.Empty : mailItem.Subject,
                Body = string.IsNullOrEmpty(mailItem.HTMLBody) ? string.Empty : mailItem.HTMLBody,
                Folder = string.IsNullOrEmpty(Inbox.Name) ? string.Empty : Inbox.Name,
                To = string.IsNullOrEmpty(mailItem.To) ? string.Empty : mailItem.To
            };
            IndexAccessor.Add(mailInfo.ToDoc()); //添加文檔到索引
        }
        ...
    }
    ...
    //再讀取sentbox
    for (; SentboxIndex <= Sentbox.Items.Count; SentboxIndex++)
    { ... }
}

最後將IndexProc放到後台線程中運行來提高用戶體驗:

private void frmOutlookSearcher_Load(object sender, EventArgs e)
{
    ...
    this.IndexAccessor = new IndexManager(new MailAnalyzer()); //用MailAnalyzer作為分析器
    this.IndexAccessor.MaxIndexSize = int.MaxValue; //索引大小無限制
    this.IndexAccessor.MinIndexSize = int.MaxValue; //索引大小無限制
    this.IndexAccessor.MergeFactor = int.MaxValue; //不做merge
    ...
    IndexingTask = Task.Factory.StartNew(this.IndexProc); //在後台線程編制索引
}

OK, 大功告成! Outlook搜索精靈支持如下搜索字段:

默認情況下, Outlook搜索精靈會使用

Subject="{0}" OR Body="{0}"

進行搜索, {0}會被自動替換成輸入的關鍵詞. 但是如果我們輸入的本身就是一個搜索表達式, 那麼 Outlook搜索精靈會自動切換成高級搜索模式, 用用戶輸入的表達式進行搜索.

列舉幾個高級搜索的例子:

//1. 搜索標題含有"張三"並且正文含有"朋友聚餐"的郵 件:

Subject="張三" & Body="朋友聚餐"

//2. 在已發郵件中搜索標題中含有"張三"的郵件:

Folder="[已發郵件]" AND Subject="張三"

//3. 搜索標題包含"Hotfix"的郵件: (hotfix和hotfixing都會被搜索到)

Subject WILDCARD "hotfix"

這只是部分例子, 有了WEBUS2.0 SDK的支持, Outlook搜索精靈可以輕松實現7種不同類型的搜索, 並且支持復雜的邏輯搜索表達式, 具體請看 WEBUS2.0 In Action - 搜索操作指南 - (2).

為了讓Outlook搜索精靈根據體貼好用, 我還設計了一些小功能, 比如Outlook連接中斷自動重連, 最小化到托盤等. enjoy吧!

下載程序:http://files.cnblogs.com/iamzyf/OutlookSearcher.zip

下載源代碼:http://files.cnblogs.com/iamzyf/OutlookSearcher_VS2010.zip

相關信息及WEBUS2.0 SDK下載:繼續我的代碼,分享我的快樂 - WEBUS2.0

查看本欄目

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