[原创] - C#编程大幅提高OUTLOOK的邮件搜索能力!

时间:2022-12-22 13:12:29

[原创] - C#编程大幅提高OUTLOOK的邮件搜索能力!

使用OUTLOOK, 你有没有遇到过上图的问题? 多达18419封邮件! 太多了, 每次想找一个邮件都非常耗时, 想办法解决这个问题成了一件非常紧迫的事情. 利用MS Search当然可以, 但是它太heavy了, 而且不支持如逻辑搜索表达式等复杂查找功能, 怎么办? 幸运的是我有WEBUS2.0 SDK, 于是我决定自己开发一个名为Outlook Searcher (Outlook搜索精灵) 的小工具.

[原创] - C#编程大幅提高OUTLOOK的邮件搜索能力!

Outlook搜索精灵主要包含两个功能:

1. 读取Outlook中的邮件信息并创建全文索引;

2. 提供搜索功能, 支持各种复杂的逻辑表达式.

先看看如何读取Outlook:

引用COM组件:

[原创] - C#编程大幅提高OUTLOOK的邮件搜索能力!

我这里引用的是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的邮件搜索能力!的更多相关文章

  1. - C&num;编程大幅提高OUTLOOK的邮件搜索能力&excl;

    原文:[原创] - C#编程大幅提高OUTLOOK的邮件搜索能力! 使用OUTLOOK, 你有没有遇到过上图的问题? 多达18419封邮件! 太多了, 每次想找一个邮件都非常耗时, 想办法解决这个问题 ...

  2. &lbrack;Outlook&rsqb;设置邮件自动接收时间

    [Outlook]设置邮件自动接收时间   找了好久,一直都没设置正常,导致老是收到邮件有延迟,今天头脑清晰,搜了一下,然后自己竟然给找到了,记下来当笔记,好记性不如烂笔头,呵呵   搜索百度&quo ...

  3. outlook新邮件到达提醒设置以及outlook最小化到托盘设置

    有些邮件是需要马上处理的,因此希望能在收到邮件之后马上就知道,但是有不希望频繁的去检查有没有.outlook可以帮我们轻松做到新邮件到达提醒. 一 .设置outlook新邮件到达提醒:选项->电 ...

  4. &lbrack;原创&rsqb;obj-c编程17&colon;键值观察&lpar;KVO&rpar;

    原文链接:[原创]obj-c编程17:键值观察(KVO) 系列专栏链接:objective-c 编程系列 说完了前面一篇KVC,不能不说说它的应用KVO(Key-Value Observing)喽.K ...

  5. 今天,Java编程周末提高班(第一期)正式结束

    Java编程周末提高班(第一期),走过了近两个月历程,一共同拥有68人次学生周末到老师家进行Java学习与交流.近距离的和一群年轻的学习接触,收获非常多,特别是对以后教学的改进.在学习的闲暇.大家自己 ...

  6. &lbrack;原创&rsqb;用&OpenCurlyDoubleQuote;人话”解释不精确线搜索中的Armijo-Goldstein准则及Wolfe-Powell准则

    [原创]用“人话”解释不精确线搜索中的Armijo-Goldstein准则及Wolfe-Powell准则 转载请注明出处:http://www.codelast.com/ line search(一维 ...

  7. NOIP2018提高组金牌训练营——搜索专题

    NOIP2018提高组金牌训练营——搜索专题 1416 两点 福克斯在玩一款手机解迷游戏,这个游戏叫做”两点”.基础级别的时候是在一个n×m单元上玩的.像这样: 每一个单元有包含一个有色点.我们将用不 ...

  8. 为outlook增加&OpenCurlyDoubleQuote;邮件召回”功能

    outlook 2007开始软件自带邮件召回功能.2003版本没有,可惜此版本盗版最厉害,用户很广,这次项目中用户分布很广,其中outlook2003版本用户数甚多,达到397人. 不可能让他们新装2 ...

  9. outlook邮箱邮件与企业邮箱同步&lpar;outlook本地文件夹邮件,web邮箱里没有&rpar;

    用惯了outlook2010, 问题:今天将邮件放到自定义文件夹后,发现在web邮箱中看不到邮件了.不能同步到企业邮箱. 解决忙了一天,才知道是账户类型问题,pop3类型,只下载不上传.所以outlo ...

随机推荐

  1. &period;NET 产品版权保护方案 &lpar;&period;NET源码加密保护&rpar; (转载)

    说 明:你希望自己用.net辛辛苦苦做出来的软件被人轻易破解吗?你希望自己花了大量人力物力用.net开发出来的产品被竞争对手轻易获取核心代码吗?这是 一篇比较详尽地介绍如何保护自己的.net源代码的文 ...

  2. BZOJ3529&colon; &lbrack;Sdoi2014&rsqb;数表

    题目:http://www.lydsy.com/JudgeOnline/problem.php?id=3529 挺恶心的数论TAT... 设f[i]是i的约数和,这个可以nln(n)扫出来. ans= ...

  3. 【mac】ssh免登录密码

    mac ssh免登录密码 在mac或者Linux上需要使用ssh登服务器,每次都需要输密码感觉很麻烦,搜了一下找到一个脚本,实践后发现可行. 1.创建脚本xx.sh $ vim xx.sh 输入: # ...

  4. 芝麻HTTP:Gerapy的安装

    Gerapy是一个Scrapy分布式管理模块,本节就来介绍一下它的安装方式. 1. 相关链接 GitHub:https://github.com/Gerapy 2. pip安装 这里推荐使用pip安装 ...

  5. docker学习笔记(一)-vagrant&sol;docker machine安装docker,阿里云通过docker machine安装docker

    首先需要先安装virtualbox https://www.vagrantup.com/ 下载安装vagrant 安装完毕后通过vagrant下载镜像,生成实例 mkdir test_centos7 ...

  6. postman&lpar;六&rpar;:详解在Pre-request Script中如何执行请求

    上一篇借着如何在不同接口之间传递数据,简单说了下在postman编写脚本发送请求,这里再详细介绍一下如何在Pre-request Script和Tests标签中编写脚本.因为我目前研究的也不是很深,对 ...

  7. cyclone iv中DDR2的本地接口时序

    本地接口 信号名 方向  描述  local_burstbegin input 如果local_ready无效不起作用.IP核在local_write_req为高时,在phy_clk上升沿采样.当lo ...

  8. InvalidArgumentError&colon; You must feed a value for placeholder tensor &&num;39&semi;Placeholder&lowbar;1&&num;39&semi; with dtype float and shape &lbrack;&quest;&comma;10&rsqb;

    在莫烦Python教程的“Dropout 解决 overfitting”一节中,出现错误如下: InvalidArgumentError: You must feed a value for plac ...

  9. P3620 &lbrack;APIO&sol;CTSC 2007&rsqb;数据备份

    P3620 [APIO/CTSC 2007]数据备份 题目描述 你在一家 IT 公司为大型写字楼或办公楼(offices)的计算机数据做备份.然而数据备份的工作是枯燥乏味的,因此你想设计一个系统让不同 ...

  10. Maven聚合、Maven仓库jar包以及Spring&plus;MyBatis&plus;JUnit&plus;Maven整合测试的搭建过程

    一.Maven将父项目创建到父项目的内部 在父项目的pom.xml上 点右键,选择maven-->new-->maven module  project 二.Maven聚合 在某个项目的p ...