Jaa


Working with Streaming Notifications By Using the EWS Managed API

Microsoft Exchange Server 2010 Service Pack 1 (SP1) introduces streaming notifications, a new feature that combines push and pull notifications. For those of you who are not too familiar with notifications, I’ll give some background information. Pull notifications require your application to create a subscription and every now and then request an update from the server. This can create quite a bit of traffic between the client and server if you want to keep up-to-date with events on the server. Push notifications require you to write your own listener application. You create a push subscription with the server and when an event fires, it pushes the notification to your listener application. This works well because you don’t have to keep asking the server for updates, but it does require that you create a separate application to receive the notifications. Now, we have the best of both worlds with streaming notifications. After you have established your notification subscription, the connection remains open to allow the server to push notifications back to your application. You don’t have to request updates as for the pull subscription, and you don’t have to create a listener application as for the push notifications.

We wrote a console example for creating the subscription and handling notification responses. The first step in your application is to create a service binding to your Exchange mailbox. Because this is a pretty common routine in Microsoft Exchange Web Services (EWS) Managed API, I don’t want to go over it in detail here, but if you need a refresher check out the topic Connecting to EWS in the EWS Managed API SDK.

After the service binding is completed, call the SetStreamingNotifications function and pass in the service binding. In this example, a subscription is made to the Inbox and the notifications will be sent for new e-mail messages and for items that have been created or deleted in the Inbox. Because this is just an example, the timeout is set to one minute, but you can adjust this as necessary for your application. This example will also recognize the OnDisconnect event and ask if the connection should remain open. You can see that after the subscription is created, it’s very easy to reopen the connection. If you don’t want to reopen the connection, the code will close the connection object.

When a notification is sent back, the OnEvent function is called and a message is output to the console. When you get the notification, you also get the itemID that you can use to bind to the item and get additional information about that item.

The following code shows the console application…

static void SetStreamingNotifications(ExchangeService service)
{
    // Subscribe to streaming notifications on the Inbox folder, and listen
    // for "NewMail", "Created", and "Deleted" events.
    StreamingSubscription streamingsubscription = service.SubscribeToStreamingNotifications(
        new FolderId[] { WellKnownFolderName.Inbox },
        EventType.NewMail,
        EventType.Created,
        EventType.Deleted);

    StreamingSubscriptionConnection connection = new StreamingSubscriptionConnection(service, 1);

    connection.AddSubscription(streamingsubscription);
    // Delegate event handlers.
    connection.OnNotificationEvent +=
        new StreamingSubscriptionConnection.NotificationEventDelegate(OnEvent);
    connection.OnSubscriptionError +=
        new StreamingSubscriptionConnection.SubscriptionErrorDelegate(OnError);
    connection.OnDisconnect +=
        new StreamingSubscriptionConnection.SubscriptionErrorDelegate(OnDisconnect);
    connection.Open();

    Console.WriteLine("--------- StreamSubscription event -------");
}

static private void OnDisconnect(object sender, SubscriptionErrorEventArgs args)
{
    // Cast the sender as a StreamingSubscriptionConnection object.          
    StreamingSubscriptionConnection connection = (StreamingSubscriptionConnection)sender;
    // Ask the user if they want to reconnect or close the subscription.
    ConsoleKeyInfo cki;
    Console.WriteLine("The connection to the subscription is disconnected.");
    Console.WriteLine("Do you want to reconnect to the subscription? Y/N");
    while (true)
    {
        cki = Console.ReadKey(true);
        {
            if (cki.Key == ConsoleKey.Y)
            {
                connection.Open();
                Console.WriteLine("Connection open.");
                break;
            }
            else if (cki.Key == ConsoleKey.N)
            {
                // The ReadKey in the Main() consumes the E.
                Console.WriteLine("\n\nPress E to exit");
                break;
            }
        }
    }
}

static void OnEvent(object sender, NotificationEventArgs args)
{
    StreamingSubscription subscription = args.Subscription;

    // Loop through all item-related events.
    foreach (NotificationEvent notification in args.Events)
    {

        switch (notification.EventType)
        {
            case EventType.NewMail:
                Console.WriteLine("\n-------------Mail created:-------------");
                break;
            case EventType.Created:
                Console.WriteLine("\n-------------Item or folder created:-------------");
                break;
            case EventType.Deleted:
                Console.WriteLine("\n-------------Item or folder deleted:-------------");
                break;
        }
        // Display the notification identifier.
        if (notification is ItemEvent)
        {
            // The NotificationEvent for an e-mail message is an ItemEvent.
            ItemEvent itemEvent = (ItemEvent)notification;
            Console.WriteLine("\nItemId: " + itemEvent.ItemId.UniqueId);
        }
        else
        {
            // The NotificationEvent for a folder is an FolderEvent.
            FolderEvent folderEvent = (FolderEvent)notification;
            Console.WriteLine("\nFolderId: " + folderEvent.FolderId.UniqueId);
        }
    }
}
static void OnError(object sender, SubscriptionErrorEventArgs args)
{
    // Handle error conditions.
    Exception e = args.Exception;
    Console.WriteLine("\n-------------Error ---" + e.Message + "-------------");
}

To make this application work properly, bind it to your Exchange mailbox and call the SetStreamingNotifications function. Then send a message to this mailbox from an e-mail client of your choice — just do it before the one minute timeout occurs. You will then get a message that an item was created and you have a new e-mail message in your Inbox.

Comments

  • Anonymous
    January 06, 2011
    I building an app that is capable of mapping more than one client's mailboxes on it. Let say my my app can configure user1@abc.com and user2@abc.com, and my keeps syncing with the mailboxes with the exchange. So it possible to configure streaming notification for user1 for time t1-t2 and user2 for time t1-t2. Please give some example.. rajeshkalra86@gmail.com

  • Anonymous
    January 10, 2011
    The comment has been removed

  • Anonymous
    February 28, 2011
    Is there any place where to find maximum value of lifetime paramter ??? StreamingSubscriptionConnection API is not documented ! Thx

  • Anonymous
    March 07, 2012
    The three events are not firing on event when wired up Please see the link for detailed questions stackoverflow.com/.../ews-api-working-with-streamingnotificationssample-c-sharp thanks,

  • Anonymous
    February 12, 2013
    Hi, i build a application that should replace Exchange 2003 Eventsyncs with EWS after a Mailboxmigration. The Streaming Sync works perfekt with Mailboxes and Public Folders that created on 2010 - but as soon as i use it with an PubFolder that was synchronised from 2003, no Event will be fired (even if i remove the original replica of the 2003 so that i only have a 2010 replica) Is this a Bug or "by design"? Thanks Martin

  • Anonymous
    July 24, 2013
    How do I get notified about deleted contacts or calendar items? I only get a folder changed event, but no item event. Thanks, Michael

  • Anonymous
    February 27, 2018
    The comment has been removed