zoukankan      html  css  js  c++  java
  • C#编程大幅提高OUTLOOK的邮件搜索能力!

    C#编程大幅提高OUTLOOK的邮件搜索能力!

    使用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搜索精灵支持如下搜索字段:

    字段 类型 描述
    Subject string 邮件标题
    Body string 邮件正文, HTML格式
    Folder string 邮件所属目录, 比如"收件箱", "已发邮件"等
    From string 发件人
    To string 收件人
    ConversationId string 会话ID

    默认情况下, 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吧!

    下载程序 | 下载源代码

     相关信息及WEBUS2.0 SDK下载:继续我的代码,分享我的快乐 - WEBUS2.0

     
     
    分类: WEBUS
  • 相关阅读:
    Insertion Sort List
    Max Points on a Line
    Evaluate Reverse Polish Notation
    vue路由传参的三种基本方式
    如何搭建一个vue项目
    vue路由跳转时更改页面title
    CSS清除浮动大全共8种方法
    border:none 与border:0的区别
    for..in和for..of的功能
    IE浏览器兼容问题-----html和css的兼容写法
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/3224148.html
Copyright © 2011-2022 走看看