EWS 邮件通知器
适用于 Exchange 的简单邮件通知器
引言
最近我一直在做一个项目,该项目是一个Exchange 2010的实时新邮件通知器。为此,我使用了Exchange Web Services API,以及我们的朋友Rodolfo Ortega在CodeProject上提供的web 服务器骨架。
要求
工作原理?
该程序通过EWS API创建一个推送订阅,然后,我使用web服务器骨架来监听Exchange发送的SOAP消息。为了反序列化Exchange在SOAP消息中包含的通知,我需要从Exchange的模式文件生成类,然后,我使用WSE 3.0来反序列化SOAP消息。
生成类
为了生成用于反序列化Exchange通知的类,我们将使用位于服务器EWS目录中的“messages.xsd”和“types.xsd”模式文件
xsd /c /language:CS /namespace:EWSConsoleNotify messages.xsd types.xsd
反序列化Exchange SOAP消息
为了反序列化Exchange发送并通过我们的web服务器骨架接收的SOAP消息,我们将使用WSE通过将XML消息传递给序列化器来反序列化它
SoapEnvelope soapEnvelope = new SoapEnvelope();
soapEnvelope.InnerXml = Body;
Type type = typeof(SendNotificationResponseType);
XmlRootAttribute xRoot = new XmlRootAttribute();
xRoot.ElementName = "SendNotification";
xRoot.Namespace = "http://schemas.microsoft.com/exchange/services/2006/messages";
XmlSerializer serializer = new XmlSerializer(type, xRoot);
XmlNodeReader reader = new XmlNodeReader(soapEnvelope.Body.FirstChild);
SendNotificationResponseType obj =
(SendNotificationResponseType)serializer.Deserialize(reader);
处理Exchange通知
一旦我们有了反序列化的消息,此方法将处理SOAP消息中包含的所有通知。请注意,在循环内部,我只检查新邮件事件,因为Exchange还会发送“Status
”消息
public SendNotificationResultType ProcessNotification
(SendNotificationResponseType SendNotification)
{
SendNotificationResultType result =
new SendNotificationResultType(); // Notification's result
bool unsubscribe = false;
ResponseMessageType[] responseMessages =
SendNotification.ResponseMessages.Items; // Response messages
foreach (ResponseMessageType responseMessage in responseMessages)
{
if (responseMessage.ResponseCode != ResponseCodeType.NoError)
{
result.SubscriptionStatus = SubscriptionStatusType.Unsubscribe;
return result;
}
NotificationType notification =
((SendNotificationResponseMessageType)responseMessage).Notification;
string subscriptionId = notification.SubscriptionId;
// If subscription Id is not the current subscription Id, unsubscribe
if (subscriptionId != _parent.SubscriptionId)
{
unsubscribe = true;
}
else
{
for (int c = 0; c < notification.Items.Length; c++)
{
// Get only new mail events
if (notification.ItemsElementName[c].ToString() == "NewMailEvent")
{
BaseObjectChangedEventType bocet =
(BaseObjectChangedEventType)notification.Items[c];
_parent.ShowMessage(((ItemIdType)bocet.Item).Id);
}
}
}
}
if (unsubscribe)
{
result.SubscriptionStatus = SubscriptionStatusType.Unsubscribe;
}
else
{
result.SubscriptionStatus = SubscriptionStatusType.OK;
}
return result;
}
}
使用EWS API创建推送通知的订阅
此方法创建推送订阅,并启动带有我们的web服务器骨架的线程以监听传入连接
public void Start()
{
System.Net.ServicePointManager.ServerCertificateValidationCallback = delegate(
Object obj,
X509Certificate certificate,
X509Chain chain,
SslPolicyErrors errors)
{
return true;
// TODO: check for a valid certificate
};
// Create the subscription
_service = new ExchangeService();
// Set credentials: user, password and domain
_service.Credentials = new WebCredentials("user", "password", "domain");
// URL of the EWS
_service.Url = new Uri("https://exchange_server/ews/exchange.asmx");
PushSubscription ps =
_service.SubscribeToPushNotificationsOnAllFolders(new Uri("http://your_IP:5050"),
5 // Every 5 minutes Exchange will send us a status message
, null, EventType.NewMail);
SubscriptionId = ps.Id;
// Listen on port 5050
_listener = new TcpListener(5050);
_listener.Start();
_th = new Thread(new ThreadStart(ProcessIncomingMessages));
_th.Start();
WriteLog("Listening for incoming messages...");
}
显示接收到的新邮件
要显示接收到的新邮件,我们需要绑定到通知中发送的项目Id
public void ShowMessage(string UniqueId)
{
EmailMessage mail = ((EmailMessage)Item.Bind(_service, new ItemId(UniqueId)));
Console.WriteLine("New mail from: {0}, Subject: {1}", mail.From.Name, mail.Subject);
}
屏幕截图

备注
此示例在Exchange 2010上进行了测试,我不知道它是否适用于早期版本。可能需要使用WCF来实现,但在我进行的测试中,它对我不起作用,因此我使用了Rodolfo的web服务器骨架来监听Exchange发送的SOAP消息。
我希望这个示例能帮助你。;-)