I offen wondered how I can programmatically read items from mailboxes stored within Microsoft Exchange Server. Some time ago I used Outlook with some macros that accessed the information I needed. But what if Outlook does not run? Or what if the computer crashed – who would logon and start Outlook? Sure you can find workarounds for every problem. But this never seemed to be a ‘cool’ solution to me. In the past few weeks – after I got my Exchange 2010 MCITP – I started to have a look at EWS – Exchange Web Services (available since Microsoft Exchange Server 2007). This one seemed to be pretty simple and also a stable solution to all my needs. Here is how I do it all now with vbscript…

There is not much you’ll need to connect to Exchange, just a http connection to your Client Access Server, a user with credentials and access to the mailbox you want to read, a soap xml request and some lines of code that will parse the response for you.

First, you’ll need to know the dns name or the ip of your Client Access Server – in this example I’ll you EXCAS.domain.tld.
Now we create some objects and define the url to the CAS and username and password to access it:

Dim objXmlHttp, xmlDoc

Const strUrl = "https://EXCAS.domain.tld/ews/exchange.asmx" 'URL to CAS
Const strUser = "domain.tld\myexchangeuser" 'Domain and Username to authenticate with
Const strPassword = "myExchangeUSeRsP4ssw0rd"
Const strEmailAddress = "mailboxtoreadfrom@domain.tld" 'Mailbox that you want to read data from

Set objXmlHttp = CreateObject("Microsoft.XMLHTTP") 'this will send the request to EWS
Set objXmlDoc = CreateObject("MSXML2.DOMDocument") 'this will parse the response for us

Now it is time to decide what we want to do, or better: we need to create the request telling EWS what to do. In this example I want to know about every calendar item in a certain time span. But you can do much more:

Since we want to crawl for many items we will use the FindItem Operation. Following this link you’ll get a complete overview how the request will look like. In common every operation that can be used with Exchange Web Service is really well documented!
As you can see the basic xml soap request is:



  
    
      
        IdOnly
      
      
        
      
    
  

We just need to make some modifications to this example – we want to read all properties in the calendar for example, we do want to connect to another mailbox and we do want to use a certain time span not the whole calendar. So the soap request would look like this (changes marked bold):



  
    
      
        AllProperties
      
      
      
        
          
            mailboxtoreadfrom@domain.tld
          
        
      
    
  

Now we need to connect to EWS, post this request, wait for the answer and parse it. Since this is a complex xml structure we just need to break it down to that level the information is stored in – in this example it is the “t_Items” node.

objXmlHttp.open "POST", strUrl, False, strUser, strPassword
objXmlHttp.setRequestHeader "Content-Type", "text/xml"
objXmlHttp.send strXmlData 'this is the soap request from above
If objXmlHttp.Status = "200" Then 'if the request was successful go on
  If objXmlDoc.loadXML(objXmlHttp.responseText) Then
    Set soap_Body = objXmlDoc.documentElement.childNodes.item(1) 'soap_body is the second node below the document root
    Set m_FindItemResponse = soap_Body.childNodes.item(0) 'm_FindItemResponse is the first node below soap_body
    Set m_ResponseMessages = m_FindItemResponse.childNodes.item(0) 'and so on...
    Set m_FindItemResponseMessage = m_ResponseMessages.childNodes.item(0)
    Set m_RootFolder = m_FindItemResponseMessage.childNodes.item(1)
    Set t_Items = m_RootFolder.childNodes.item(0)
    
    For Each calendarItem In t_Items.childNodes
      Dim t_Subject, t_Start, t_End, t_LegacyFreeBusyStatus, t_Location, t_IsRecurring, t_CalendarItemType, t_MyResponseType, t_Organizer
      t_ItemId = calendarItem.getElementsByTagName("t:ItemId").item(0).getAttribute("Id")
      t_Subject = calendarItem.getElementsByTagName("t:Subject").item(0).text
      t_Start = calendarItem.getElementsByTagName("t:Start").item(0).text
      t_End = calendarItem.getElementsByTagName("t:End").item(0).text
      t_LegacyFreeBusyStatus = calendarItem.getElementsByTagName("t:LegacyFreeBusyStatus").item(0).text
      t_Location = calendarItem.getElementsByTagName("t:Location").item(0).text
      t_IsRecurring = calendarItem.getElementsByTagName("t:IsRecurring").item(0).text
      t_CalendarItemType = calendarItem.getElementsByTagName("t:CalendarItemType").item(0).text
      t_MyResponseType = calendarItem.getElementsByTagName("t:MyResponseType").item(0).text
      t_Organizer = calendarItem.getElementsByTagName("t:Organizer").item(0).getElementsByTagName("t:Mailbox").item(0).getElementsByTagName("t:Name").item(0).text
      
      'Here you can do anything you like with all this information
    Next
  End If
Else
  wscript.echo "Error: " & objXmlHttp.Status & " - " & objXmlHttp.statusText 'If status is not 200
End If

Documentation for functions, methods and properties used in this post: