校验从Outlook2007/2010beta发出的邮件(VS2010beta2, dot Net 3.5 & dot Net 4.0)
Posted on 2009-11-01 18:43 Aaron@cnblogs 阅读(402) 评论(0) 收藏 举报[版权所有,转载请告知,并保存原作者名及文章在博客园的链接]
原因
最近收发的邮件越来越敏感。虽然自己小心翼翼但是有时候难免会发错,不过好记性不如烂笔头。决定花点时间研究一下如何在Outlook发邮件之前做一些必要的校验。要检验的是两个问题:
1. 我的工作环境是公司有自己的邮件系统,客户有另外一个邮件系统。因为我们在工作中和客户的系统是紧密相联的,部门中包括VP都有客户给的邮箱。而且,客户的邮件系统和Outlook结合的更好。所以,往往为了省事,大部分员工优先使用客户邮箱沟通所有的事情。但是,有些内容会涉及到本公司内部的信息,这是不应该使用客户邮箱来沟通的。
2. 发工作邮件没有标题是很糟糕的。虽然我极少犯此错误(印象中没有试过),但是犯错一次可能会有严重的不良影响。
工具
VS2010beta2,Outlook 2007/2010beta,VSTO 40,.Net Framework 3.5/4.0 beta2
VS2010beta2已经完成所有的功能开发,剩下的工作只是性能调优。所以,生成的代码应该可以无缝地RTM中继续使用。虽然不知道 .Net Framework 4.0什么时候发布,但VS2010是可以创建以前版本的工程文件。所以,为了使用者不需要安装临时的 .Net 4.0 beta,可以用 .Net 3.5配合 VSTO40创建功能。用户可以减少安装负担。
VSTO 40是随VS2010发布的针对Office的interop组件。
实现
其实没有什么技术含量。虽然从来没有使用过VSTO,网上的资料也不是很全,但2个小时基本上调试完成。共享出来的原因也就是为了减少大家搜索的时间而已。
1
using System;2
using System.Collections.Generic;3
using System.Collections;4
using System.Linq;5
using System.Text;6
using System.IO;7
using System.Xml.Linq;8
using System.Xml;9
using Outlook = Microsoft.Office.Interop.Outlook;10
using Office = Microsoft.Office.Core;11
using System.Windows.Forms;12
using System.Diagnostics;13

14
namespace MailReminderForOutlook20072010N3515


{16
public partial class ThisAddIn17

{18

/**//// <summary>19
/// key is composed by sender domain and receiver domain;20
/// val is exception list, there is a pair of seperators to wrap the exceptional address.21
/// That is, the exception value should start with the seperator and end with the seperator.22
/// For example: 1. "!#~[alias@domain.com]!#~"23
/// 2. "!#~[alias1@domain.com]!#~[alias2@domain.com]!#~"24
/// </summary>25
private static SortedList<string, string> _violations =26
new SortedList<string, string>(2);27
private static readonly string SPT = "!#~";28
private static readonly string SETTING_XML29
= "MailReminderForOutlook.xml";30
private static readonly string docFolder =31
Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);32
private static readonly string xmlFile =33
Path.Combine(docFolder, SETTING_XML);34
private static readonly string NODE_CONFIG = "configuration";35
private static readonly string NODE_VIOLATIONS = "violations";36

37
private void LoadConfiguraton()38

{39
if (File.Exists(xmlFile))40

{41
XmlDocument doc = new XmlDocument();42
doc.Load(xmlFile);43
XmlNodeList list =44
doc.SelectSingleNode(45
NODE_CONFIG + "/" + NODE_VIOLATIONS).ChildNodes;46
for (int i = 0; i < list.Count; ++i)47

{48
_violations.Add(49
list[i].Name.ToLower(),50
list[i].InnerText == null ? String.Empty : list[i].InnerText);51
}52
}53
else54

{55
_violations.Add("domain1.comdomain2.com", "!#~sample@domain2.com!#~");56
_violations.Add("domain2.comdomain1.com", "!#~sample@domain1.com!#~");57
XmlDocument doc = new XmlDocument();58
XmlNode baseNode = (XmlNode)doc.CreateElement(NODE_CONFIG);59
doc.AppendChild(baseNode);60
XmlNode violationNode =61
(XmlNode)doc.CreateElement(NODE_VIOLATIONS);62
baseNode.AppendChild(violationNode);63
XmlElement first =64
doc.CreateElement("domain1.comdomain2.com");65
XmlElement second =66
doc.CreateElement("domain2.comdomain1.com");67
violationNode.AppendChild((XmlNode)first);68
violationNode.AppendChild((XmlNode)second);69
doc.Save(xmlFile);70
doc = null;71
}72
}73

74
private void ThisAddIn_Startup(object sender, System.EventArgs e)75

{76
try77

{78
LoadConfiguraton();79
this.Application.ItemSend +=80
new Outlook.ApplicationEvents_11_ItemSendEventHandler(81
Application_ItemSend);82
}83
catch (Exception exp)84

{85
ShowError(exp);86
}87
}88

89
private void ViolateVITSensitive(Outlook.MailItem item, StringBuilder msg)90

{91
bool violated = false;92
String sender = item.SendUsingAccount.SmtpAddress;93
string senderDomain =94
sender.Substring(sender.IndexOf("@") + 1).ToLower();95

96
StringBuilder tip = new StringBuilder(64);97
foreach (Outlook.Recipient rec in item.Recipients)98

{99
string receiverDomain =100
rec.AddressEntry.Address.Substring(101
rec.Address.IndexOf("@") + 1).ToLower();102
string key = senderDomain + receiverDomain;103
if (_violations.ContainsKey(key))104

{105
if (_violations[key].IndexOf(106
SPT + rec.AddressEntry.Address.ToLower() + SPT) < 0)107

{108
violated = true;109
tip.AppendFormat(" {0}", rec.Address);110
}111
}112
}113
if (violated)114

{115
msg.AppendFormat(116
"Your Address:{0}\r**These Addresses violate mail sensitive policy:\r{1}.",117
sender, tip);118
}119
}120

121
private void IsWithoutTitle(Outlook.MailItem item, StringBuilder msg)122

{123
if (null == item.Subject || item.Subject.Length < 1)124

{125
msg.AppendFormat(126
"{0}**There is no title of this thread!",127
msg.Length > 0 ? "\r\r" : String.Empty);128
}129
}130

131
void Application_ItemSend(object Item, ref bool Cancel)132

{133
try134

{135
Cancel = false;136
Outlook.MailItem item = (Outlook.MailItem)Item;137
StringBuilder msg = new StringBuilder(256);138
ViolateVITSensitive(item, msg);139
IsWithoutTitle(item, msg);140
if (msg.Length > 0)141

{142
DialogResult res = MessageBox.Show(143
msg.ToString(),144
"Do you want to send this thread anyway?",145
MessageBoxButtons.YesNo,146
MessageBoxIcon.Warning,147
MessageBoxDefaultButton.Button2);148
if (DialogResult.Yes != res)149

{150
Cancel = true;151
}152
}153
}154
catch (Exception exp)155

{156
ShowError(exp);157
}158
}159

160
private void ShowError(Exception e)161

{162
MessageBox.Show(163
String.Format(164
"Click 'ctrl+c' to copy this error and send to XXXX@domain1.com.\rError:{0}\rStack:{1}",165
e.Message, e.StackTrace),166
"Mail Warning Outlook Plug-in Error",167
MessageBoxButtons.OK,168
MessageBoxIcon.Error);169
}170

171
private void ThisAddIn_Shutdown(object sender, System.EventArgs e)172

{173
}174

175

VSTO generated code#region VSTO generated code176

177

/**//// <summary>178
/// Required method for Designer support - do not modify179
/// the contents of this method with the code editor.180
/// </summary>181
private void InternalStartup()182

{183
this.Startup += new System.EventHandler(ThisAddIn_Startup);184
this.Shutdown += new System.EventHandler(ThisAddIn_Shutdown);185
}186
187
#endregion188
}189
}190

整个代码没什么神奇的地方。不再做详细的解释。这段代码也可以直接用在 .Net Framework 4.0的工程中。两者在本例并没有区别。
ViolateVITSensitive用来校验是否有违规的邮件地址。比如发件者的邮箱是alias@domain1.com。那么就不允许出现XXX@domain2.com 的收件人。发现违规会弹出提示,用户可以取消或者强制发送。
代码有不少可以优化的地方,比如所有的校验函数都可以做成DI(IoC)的模式(不过暂时没有必要。而且,这样只会扰乱只关心怎么用VSTO的读者)。
XML部分可以用lambda,不过我对这种在大部分情况只提高书写效率,并不会提高执行效率和调试效率的东西不太感冒(也可能是个人偏见,呵呵)。
浙公网安备 33010602011771号