Tuesday, May 12, 2015

Microsoft Exchange Server EWS Java API push notification working example

Microsoft Exchange Server EWS Java API push notification working example



First, connect to exchange server via EWS Java API as

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
ExchangeService service; 
private void init() throws Exception {
 service = new ExchangeService(ExchangeVersion.Exchange2010_SP2);
 
 // Provide Crendentials
 ExchangeCredentials credentials = new WebCredentials("my_login_id",
   "nypassword", "my_login_domain");
 service.setCredentials(credentials);

 service.setUrl(new URI("https://somepoint.company.com/EWS/exchange.asmx"));
}

then, talk to exchange server to subscribe to push notification as
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
private void subscribeToPush() throws Exception {
 WellKnownFolderName wkFolder = WellKnownFolderName.Inbox;
 FolderId folderId = new FolderId(wkFolder);
 List<FolderId> folder = new ArrayList<FolderId>();
 folder.add(folderId);
 
 URI callback = new URI("http://my_notification_listener_host:7777/podm/rs/emailnotification");
 
 PushSubscription pushSubscription = service.subscribeToPushNotifications(
   folder,
   callback /* The endpoint of the listener. */,
      5 /* Get a status event every 5 minutes if no new events are available. */,
      null  /* watermark: null to start a new subscription. */,
      EventType.NewMail);  
 System.out.println("PushSubscription = " + pushSubscription);
 
 BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
 System.out.print("Enter String");
 String s = br.readLine();  
}

The push notification listener is implemented as Restful Web Service in Java as
1
2
3
4
5
6
7
8
9
@POST()
@Path("/emailnotification")
@Produces(MediaType.TEXT_XML)
public Response onNotificationReceived() throws Exception {
 logger.debug("received EWS notification");
 File file = new File("C:\\Users\\XYZ\\workspace\\POC\\ews_notification_response.xml");
 String responseXMLStr = IOUtils.toString(new FileInputStream(file));
 return Response.ok(responseXMLStr).build();
}

Once deployed to JBoss AS 7.1, below are the traffic back end force between notification listener and exchange server as
on new email arrived in INBOX, exchange server notify our registered notification listener via SOAP message as

notification SOAP message header:
POST /podm/rs/emailnotification HTTP/1.1
Content-Type: text/xml; charset=utf-8
Accept: text/xml
SOAPAction: http://schemas.microsoft.com/exchange/services/2006/messages/SendNotification
Host: my_notification_listener_host:8080
Content-Length: 1492
Connection: Close

notification SOAP message body:

<?xml version="1.0" encoding="UTF-8"?>
<soap11:Envelope xmlns:soap11="http://schemas.xmlsoap.org/soap/envelope/">
   <soap11:Header>
      <t:RequestServerVersion xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types" xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages" Version="Exchange2010_SP2" />
   </soap11:Header>
   <soap11:Body>
      <m:SendNotification xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages" xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types">
         <m:ResponseMessages>
            <m:SendNotificationResponseMessage ResponseClass="Success">
               <m:ResponseCode>NoError</m:ResponseCode>
               <m:Notification>
                  <t:SubscriptionId>EABnaXphLWZlLm93ZmcuY29tEAAAAA4cC3zQY3VAn3vY0tY6uAZ8uvK7TlLSCA==</t:SubscriptionId>
                  <t:PreviousWatermark>AQAAAB0YmFETCChLogUFZRl0jsftgtkCAAAAAAA=</t:PreviousWatermark>
                  <t:MoreEvents>false</t:MoreEvents>
                  <t:NewMailEvent>
                     <t:Watermark>AQAAAB0YmFETCChLogUFZRl0jscHg9kCAAAAAAE=</t:Watermark>
                     <t:TimeStamp>2015-05-01T17:52:40Z</t:TimeStamp>
                     <t:ItemId Id="AAMkADAzNTU1N2I2LWY1MTgtNDFmMC1iMzY0LWQ0YzE0NzJiNTBlYwBGAAAAAACwfA0zVZM5SIQ183rvBHkaBwAgnojIUDF8R5DPCbpjOk1jAAAATOY4AAAgnojIUDF8R5DPCbpjOk1jAAAATidsAAA=" ChangeKey="CQAAAA==" />
                     <t:ParentFolderId Id="AQMkADAzNTUBN2I2LWY1MTgtNDFmMC1iMzY0LWQ0YzE0NzJiNTBlYwAuAAADsHwNM1WTOUiENfN67wR5GgEAIJ6IyFAxfEeQzwm6YzpNYwAAAUzmOAAAAA==" ChangeKey="AQAAAA==" />
                  </t:NewMailEvent>
               </m:Notification>
            </m:SendNotificationResponseMessage>
         </m:ResponseMessages>
      </m:SendNotification>
   </soap11:Body>
</soap11:Envelope>

Once our notification listener receives a notification from exchange server, it sends back a ACK response to exchange server and also let exchange server know it's still alive:
notification response message header:
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Content-Type: text/xml
Content-Length: 474
Date: Fri, 01 May 2015 17:52:41 GMT
Connection: close 
notification response message body:
<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages" xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
   <soap:Body>
      <m:SendNotificationResult>
         <m:SubscriptionStatus>OK</m:SubscriptionStatus>
      </m:SendNotificationResult>
   </soap:Body>
</soap:Envelope>


More traffic output:


14:38:29,151 DEBUG [jwang.poc.ejbs.EmailProcessorSB] (ServerService Thread Pool -- 64) subscription id=EABnaXphLWZlLm93ZmcuY29tEAAAAGcHwXOH1UFIuzwCceWIzEw2k58eE1vSCA==
14:38:29,152 INFO  [jwang.poc.ejbs.EmailProcessorSB] (ServerService Thread Pool -- 64) resumed subscription to push notification on exchange server with previous watermark = AQAAAB0YmFETCChLogUFZRl0jscNWfACAAAAAAA=


*** notification with events
<?xml version="1.0" encoding="UTF-8"?>
<soap11:Envelope xmlns:soap11="http://schemas.xmlsoap.org/soap/envelope/">
   <soap11:Header>
      <t:RequestServerVersion xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types" xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages" Version="Exchange2010_SP2" />
   </soap11:Header>
   <soap11:Body>
      <m:SendNotification xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages" xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types">
         <m:ResponseMessages>
            <m:SendNotificationResponseMessage ResponseClass="Success">
               <m:ResponseCode>NoError</m:ResponseCode>
               <m:Notification>
                  <t:SubscriptionId>EABnaXphLWZlLm93ZmcuY29tEAAAAGcHwXOH1UFIuzwCceWIzEw2k58eE1vSCA==</t:SubscriptionId>
                  <t:PreviousWatermark>AQAAAB0YmFETCChLogUFZRl0jscE+vACAAAAAAE=</t:PreviousWatermark>
                  <t:MoreEvents>false</t:MoreEvents>
                  <t:NewMailEvent>
                     <t:Watermark>AQAAAB0YmFETCChLogUFZRl0jsd/BPECAAAAAAE=</t:Watermark>
                     <t:TimeStamp>2015-05-12T21:39:07Z</t:TimeStamp>
                     <t:ItemId Id="AAMkADAzNTU1N2I2LWY1MTgtNDFmMC1iMzY0LWQ0YzE0NzJiNTBlYwBGAAAAAACwfA0zVZM5SIQ183rvBHkaBwAgnojIUDF8R5DPCbpjOk1jAAAATOY4AAAgnojIUDF8R5DPCbpjOk1jAAAATigPAAA=" ChangeKey="CQAAAA==" />
                     <t:ParentFolderId Id="AQMkADAzNTUBN2I2LWY1MTgtNDFmMC1iMzY0LWQ0YzE0NzJiNTBlYwAuAAADsHwNM1WTOUiENfN67wR5GgEAIJ6IyFAxfEeQzwm6YzpNYwAAAUzmOAAAAA==" ChangeKey="AQAAAA==" />
                  </t:NewMailEvent>
               </m:Notification>
            </m:SendNotificationResponseMessage>
         </m:ResponseMessages>
      </m:SendNotification>
   </soap11:Body>
</soap11:Envelope>


** notification status ping from server without events
<?xml version="1.0" encoding="UTF-8"?>
<soap11:Envelope xmlns:soap11="http://schemas.xmlsoap.org/soap/envelope/">
   <soap11:Header>
      <t:RequestServerVersion xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types" xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages" Version="Exchange2010_SP2" />
   </soap11:Header>
   <soap11:Body>
      <m:SendNotification xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages" xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types">
         <m:ResponseMessages>
            <m:SendNotificationResponseMessage ResponseClass="Success">
               <m:ResponseCode>NoError</m:ResponseCode>
               <m:Notification>
                  <t:SubscriptionId>EABnaXphLWZlLm93ZmcuY29tEAAAAGcHwXOH1UFIuzwCceWIzEw2k58eE1vSCA==</t:SubscriptionId>
                  <t:PreviousWatermark>AQAAAB0YmFETCChLogUFZRl0jsd/BPECAAAAAAE=</t:PreviousWatermark>
                  <t:MoreEvents>false</t:MoreEvents>
                  <t:StatusEvent>
                     <t:Watermark>AQAAAB0YmFETCChLogUFZRl0jscbCPECAAAAAAE=</t:Watermark>
                  </t:StatusEvent>
               </m:Notification>
            </m:SendNotificationResponseMessage>
         </m:ResponseMessages>
      </m:SendNotification>
   </soap11:Body>
</soap11:Envelope>

By observation, exchange server seems generate new subscription id for every new subscription to push notification request (even with valid previous watermark parameter). After JBoss AS restars and new email arrives in inbox, exchange server will send notification event to all subscriptions (old and new). When we received a notification, we can check if its notification id matches our current active notification id, if not, we can response with "unscribe" to the exchange server to unscribe the stale subscription.

Unsubscribe response as:

<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages" xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
   <soap:Body>
      <m:SendNotificationResult>
         <m:SubscriptionStatus>Unsubscribe</m:SubscriptionStatus>
      </m:SendNotificationResult>
   </soap:Body>
</soap:Envelope>

as for the notification of current active notification id, we can response with OK to tell the exchange server we got the message and we're still alive:
OK response as:

<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages" xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
   <soap:Body>
      <m:SendNotificationResult>
         <m:SubscriptionStatus>OK</m:SubscriptionStatus>
      </m:SendNotificationResult>
   </soap:Body>
</soap:Envelope>

6 comments:

  1. Hi, i'm trying to make this work with the ews java API but i can't. I hope you can help me !
    I do the following steps:

    1)Connect to the exchange web service

    ExchangeService newService = new ExchangeService(ExchangeVersion.Exchange2010_SP2);
    newService.setUrl("https://myurl/ews/Exchange.asmx");
    ExchangeCredentials credentials = new WebCredentials("asd","asd123");
    newService.setCredentials(credentials);

    2) Then subscribe to the push notifications:

    callback = new URI("http://localhost:8081/rest/emailnotification/incomingevent");
    pushSubscription = service.subscribeToPushNotifications(getFoldersForSubscription(), callback, 5, null, EventType.NewMail, EventType.Deleted);

    3) Then developed my Listener, a Restful webservice (i've tested with dummy method and it's working)

    @Path("/emailnotification")
    public class ExchangeNotificationListener {

    @Path("/incomingevent")
    @POST()
    @Produces(MediaType.TEXT_XML)
    public Response onNotificationReceived(){ //..my code...}

    But i set the breakpoint and send me an email but nothings happens.. What i am doing wrong???

    Thanks !

    ReplyDelete
  2. Thanks! This post was helpful

    ReplyDelete
  3. Please can you provide full code for your example on how to implement Push Notification Listener in java

    ReplyDelete
  4. Thanks for sharing this useful info. Check it on: advertising agencies in st louis

    ReplyDelete
  5. Really great post, Thank you for sharing This knowledge.Excellently written article, if only all bloggers offered the same level of content as you, the internet would be a much better place. Please keep it up!
    Data Science Training in Chennai
    Data Science course in anna nagar
    Data Science course in chennai
    Data science course in Bangalore
    Data Science course in marathahalli

    ReplyDelete
  6. Great post! I am actually getting ready to across this information, It’s very helpful for this blog.Also great with all of the valuable information you have Keep up the good work you are doing well.
    Best Devops Training in pune
    Devops Training in Bangalore
    Microsoft azure training in Bangalore
    Power bi training in Chennai

    ReplyDelete