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 = "firstname.lastname@example.org" '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:
- create, move, copy, delete, update, find calendar, email, folder, … items
- get user availability, get and set out of office settings
- add, remove, update delegates
- many many more, have a look at the full list at http://msdn.microsoft.com/en-us/library/bb409286(v=EXCHG.140).aspx
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:
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):
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: