Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

EWS Mail Notifier

0.00/5 (No votes)
19 Apr 2010 1  
Simple mail notifier for Exchange

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(); // 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;
    }
}        

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;
        // 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...");
}

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

screenshot.jpg

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

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here