[原创] - 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
[原创] - C#编程大幅提高OUTLOOK的邮件搜索能力!的更多相关文章
- - C#编程大幅提高OUTLOOK的邮件搜索能力!
原文:[原创] - C#编程大幅提高OUTLOOK的邮件搜索能力! 使用OUTLOOK, 你有没有遇到过上图的问题? 多达18419封邮件! 太多了, 每次想找一个邮件都非常耗时, 想办法解决这个问题 ...
- [Outlook]设置邮件自动接收时间
[Outlook]设置邮件自动接收时间 找了好久,一直都没设置正常,导致老是收到邮件有延迟,今天头脑清晰,搜了一下,然后自己竟然给找到了,记下来当笔记,好记性不如烂笔头,呵呵 搜索百度&quo ...
- outlook新邮件到达提醒设置以及outlook最小化到托盘设置
有些邮件是需要马上处理的,因此希望能在收到邮件之后马上就知道,但是有不希望频繁的去检查有没有.outlook可以帮我们轻松做到新邮件到达提醒. 一 .设置outlook新邮件到达提醒:选项->电 ...
- [原创]obj-c编程17:键值观察(KVO)
原文链接:[原创]obj-c编程17:键值观察(KVO) 系列专栏链接:objective-c 编程系列 说完了前面一篇KVC,不能不说说它的应用KVO(Key-Value Observing)喽.K ...
- 今天,Java编程周末提高班(第一期)正式结束
Java编程周末提高班(第一期),走过了近两个月历程,一共同拥有68人次学生周末到老师家进行Java学习与交流.近距离的和一群年轻的学习接触,收获非常多,特别是对以后教学的改进.在学习的闲暇.大家自己 ...
- [原创]用“人话”解释不精确线搜索中的Armijo-Goldstein准则及Wolfe-Powell准则
[原创]用“人话”解释不精确线搜索中的Armijo-Goldstein准则及Wolfe-Powell准则 转载请注明出处:http://www.codelast.com/ line search(一维 ...
- NOIP2018提高组金牌训练营——搜索专题
NOIP2018提高组金牌训练营——搜索专题 1416 两点 福克斯在玩一款手机解迷游戏,这个游戏叫做”两点”.基础级别的时候是在一个n×m单元上玩的.像这样: 每一个单元有包含一个有色点.我们将用不 ...
- 为outlook增加“邮件召回”功能
outlook 2007开始软件自带邮件召回功能.2003版本没有,可惜此版本盗版最厉害,用户很广,这次项目中用户分布很广,其中outlook2003版本用户数甚多,达到397人. 不可能让他们新装2 ...
- outlook邮箱邮件与企业邮箱同步(outlook本地文件夹邮件,web邮箱里没有)
用惯了outlook2010, 问题:今天将邮件放到自定义文件夹后,发现在web邮箱中看不到邮件了.不能同步到企业邮箱. 解决忙了一天,才知道是账户类型问题,pop3类型,只下载不上传.所以outlo ...
随机推荐
- POJ 2992 Divisors (求因子个数)
题意:给n和k,求组合C(n,k)的因子个数. 这道题,若一开始先预处理出C[i][j]的大小,再按普通方法枚举2~sqrt(C[i][j])来求解对应的因子个数,会TLE.所以得用别的方法. 在说方 ...
- 未能正确加载“Microsoft.VisualStudio.Editor.Implementation.EditorPackage”
VS2012启动/加载项目出问题 未能正确加载“Microsoft.VisualStudio.Editor.Implementation.EditorPackage, Microsoft.Visual ...
- hdu 2999 Stone Game, Why are you always there? 博弈论
SG函数应用!! 代码如下: #include<cstdio> #include<cstring> #include<iostream> #include<c ...
- C Primer Plus之文件输入/输出
文件 一个文件通常就是磁盘上的一段命名的存储区.但对于操作系统来说,文件就会更复杂一些.例如,一个大文件可以存储在一些分散的区段中,或者还会包含一些使操作系统可以确定其文件类型的附加数据. C将文件看 ...
- lintcode: 最长连续序列
最长连续序列 给定一个未排序的整数数组,找出最长连续序列的长度. 说明 要求你的算法复杂度为O(n) 样例 给出数组[100, 4, 200, 1, 3, 2],这个最长的连续序列是 [1, 2, 3 ...
- Project Euler 102:Triangle containment 包含原点的三角形
Triangle containment Three distinct points are plotted at random on a Cartesian plane, for which -10 ...
- ruby libmysqlclient.18.dylib
在mac 的rails环境中,如果已经确定安装了 mysql server,但是在启动rails s (服务器)的时候出现 Library not loaded: libmysqlclient.18 ...
- 什么是A股、B股、H股、蓝筹股、红筹股
A股 A股的正式名称是人民币普通股票.它是由我同境内的公司发行,供境内机构.组织或个人(不含台.港.澳投资者)以人民币认购和交易的普通股股票,我国A股股票市场经过几年快速发展,已经初具规模. B股 B ...
- weblogic 安装与配置
Weblogic 安装 从官网 下载 需要的weblogic 版本, 解压缩后得到 wls1036_generic.jar [fmw_12.1.3.0.0_wls.jar , fmw_12.2.1.1 ...
- WPF之通过EventTrigger修改模板中元素的属性
前言:对于此操作,我只想说是微软的神经,还是我的笨蛋.为什么EventTrigger就不能像Trigger那样直接设置Property以及Value就对属性进行操作,而必须要放一个Action,而默认 ...