How to connect to and read data from Mailboxes, Calendars, … via Exchange Web Services and vbScript?

Posted by on Aug 3, 2011 in Exchange Server, VBScript | 16 comments

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:

16 Comments

  1. Hi, i have a problem. When i send this request:

    IdOnly

    the webservice (exchange 2010) returns this error: The parameter is incorrect.

    can you help me?

    thanks.
    SFM

  2. Could you please try the code example from http://msdn.microsoft.com/en-us/library/aa566107(v=EXCHG.140).aspx?

    I personally use the second xml requested in my post with “allproperties”. I did not try the basic code from the Microsoft site.

  3. hi,
    i am newbie in this type of programming. im trying to learn in how to get the email notification without login in microsoft outlok 2010. what i should do in the first place??? could you guide me or give me a link to where i should refer to??? thx for the advance…. hope could get ur reply as soon as possible…

  4. @vin
    Sorry, I didn’t get it… What exactly are you trying to achieve?

  5. what i am trying to do is to access the exchange server to pull out any new email notifications,calendar updates and any new events sent to my inbox via an external application without needing me to access the microsoft outlook.
    I really need help on how to get start. Appreciate your help on this

  6. @vin
    Well, thats what this post is all about. EWS (Exchange Web Services) is all you need – no Outlook at all… At least this small script is just about calendar items but it should be a small step to change the script to your needs since it is well documented on MSDN.
    You can just try to copy and paste this script, change some variables to match your environment and see how it works. Then start modifiying it to your needs. That’s what I would propose… If you get stuck, feel free to ask again.

  7. May i know what version of Visual Basic did you use for EWS 2010? I really appreciate your help. Thanks.

  8. @vin
    That’s all vbScript. Simply create a .vbs file, copy, paste and run… ๐Ÿ™‚

  9. Thank you for your guide… I appreciate it a lot. ๐Ÿ™‚

  10. Do you have any video tutorial for this?

  11. I’m sorry I don’t. But feel free to ask questions…

  12. So I don’t quite understand … You have 3 sections here. I understand the first part, and am able to use it just fine. I follow your XML file, however, does that need to be inside of the VBS code? How is it used exactly? I can’t simply put it into a VBS file …

  13. @James

    Right, I have 3 parts. vbscript, xml, vbscript. The complete xml goes in the variable strxmldata in line 3 in the second vbscript part. So you just need to get your xml into that variable. This would look like this:

    strXmlData = ""
    strXmlData = strXmlData & "<?xml version=""1.0"" encoding=""utf-8""?> "
    strXmlData = strXmlData & "<soap:Envelope xmlns:soap=""http://schemas.xmlsoap.org/soap/envelope/"" "
    strXmlData = strXmlData & "               xmlns:t=""http://schemas.microsoft.com/exchange/services/2006/types""> "
    strXmlData = strXmlData & "  <soap:Body> "
    strXmlData = strXmlData & "    <FindItem xmlns=""http://schemas.microsoft.com/exchange/services/2006/messages"" "
    strXmlData = strXmlData & "               xmlns:t=""http://schemas.microsoft.com/exchange/services/2006/types"" "
    strXmlData = strXmlData & "              Traversal=""Shallow""> "
    strXmlData = strXmlData & "      <ItemShape> "
    strXmlData = strXmlData & "        <t:BaseShape>AllProperties</t:BaseShape> "
    strXmlData = strXmlData & "      </ItemShape> "
    strXmlData = strXmlData & "      <CalendarView StartDate=""2012-01-01T00:00:00"" EndDate=""2012-01-31T23:59:59""/>"
    strXmlData = strXmlData & "      <ParentFolderIds> "
    strXmlData = strXmlData & "        <t:DistinguishedFolderId Id=""calendar""> "
    strXmlData = strXmlData & "         	<t:Mailbox><t:EmailAddress>mailboxtoreadfrom@domain.tld</t:EmailAddress></t:Mailbox> "
    strXmlData = strXmlData & "        </t:DistinguishedFolderId> "
    strXmlData = strXmlData & "      </ParentFolderIds> "
    strXmlData = strXmlData & "    </FindItem> "
    strXmlData = strXmlData & "  </soap:Body> "
    strXmlData = strXmlData & "</soap:Envelope> "
    
  14. I see. Thanks for that. However I am receiving “The download of the specified resource has failed”. It errors out when I submit strXmlData.

    objXmlHttp.send strXmlData

    Any suggestions?

  15. It’s years later… but thanks for this one, it’ helped me a lot.

    As far as the last question above: I got the same error which was because of an improper SSL certificate on the test server (being test, stuff wasn’t set up right).

    Fixing the certificate (or making the request over HTTP instead of HTTPS <- don't do it! You'll be sending a password in clear text!) allowed it to run properly.

  16. Thanks for posting this! I’m able to run the code successfully!! How do I get data about received emails (for a certain duration and in a folder) and parse the data (especially the sender, recipient, subject and content).

Leave a Reply

Your email address will not be published. Required fields are marked *

Captcha: * Time limit is exhausted. Please reload CAPTCHA.