Introduction
Recently I have been working on a project that consists of a real-time new mails notifier for Exchange 2010. To do this, I have used the Exchange Web Services API, and web server skeleton of our friend Rodolfo Ortega also available on CodeProject.
Requirements
How This Works?
The program creates a push subscription through EWS API, and then, I use the web server skeleton to listen to the SOAP messages that will send me Exchange. To deserialize the Exchange's notifications contained in the SOAP message, I needed to generate the class from Exchange's schema files, and then, I used WSE 3.0 to deserialize the SOAP message.
Generating Classes
To generate the class for deserialize Exchange's notifications, we will use "messages.xsd" and "types.xsd" schema files, located in the EWS directory of our server:
xsd /c /language:CS /namespace:EWSConsoleNotify messages.xsd types.xsd
Deserializing Exchange SOAP Message
To deserialize the SOAP message sent by Exchange and received through our web server skeleton, we will use WSE to deserialize it by passing the XML message to the serializer:
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);
Processing Exchange Notifications
Once we have our deserialized message, this method processes all notifications contained in the SOAP message sent by Exchange. Note that inside of the buckle, I check for new mail events only, because Exchange also send me "Status
" messages:
public SendNotificationResultType ProcessNotification
(SendNotificationResponseType SendNotification)
{
SendNotificationResultType result =
new SendNotificationResultType(); bool unsubscribe = false;
ResponseMessageType[] responseMessages =
SendNotification.ResponseMessages.Items; 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 (subscriptionId != _parent.SubscriptionId)
{
unsubscribe = true;
}
else
{
for (int c = 0; c < notification.Items.Length; c++)
{
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;
}
}
Creating the Subscription for Push Notifications using EWS API
This method creates the push subscription, and starts the thread with our web server skeleton for listening to the incoming connections:
public void Start()
{
System.Net.ServicePointManager.ServerCertificateValidationCallback = delegate(
Object obj,
X509Certificate certificate,
X509Chain chain,
SslPolicyErrors errors)
{
return true;
};
_service = new ExchangeService();
_service.Credentials = new WebCredentials("user", "password", "domain");
_service.Url = new Uri("https://exchange_server/ews/exchange.asmx");
PushSubscription ps =
_service.SubscribeToPushNotificationsOnAllFolders(new Uri("http://your_IP:5050"),
5 , null, EventType.NewMail);
SubscriptionId = ps.Id;
_listener = new TcpListener(5050);
_listener.Start();
_th = new Thread(new ThreadStart(ProcessIncomingMessages));
_th.Start();
WriteLog("Listening for incoming messages...");
}
Showing the New Mail Received
To show the new mail received, we need to bind to the item Id sent in the notification:
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);
}
Screenshot
Remarks
This sample has been tested on Exchange 2010, I don't know if it will work on previous versions. Probably would be made using WCF, but in the tests that I have made, it did not work for me, for these reasons I have used the Rodolfo's web server skeleton to listen to SOAP messages sent by Exchange.
I hope this sample will help you. ;-)
Recommended Links