Monday, August 2, 2010

Viewpoint for Exchange Web Services - Next Generation BETA

I would like to announce the next generation, BETA release of Viewpoint, my Exchange Web Services client library for Ruby. This release has some major changes from the previous one which I'll list below. It was also developed in Ruby 1.9.x and the RSPEC tests have also completed in Ruby 1.8.7. There is much work that needs to be done adding features to the Model, but the SOAP guts have been hashed out fairly well in my mind and adding features from here on out should be fairly incremental. So without further ado, here are some of the major changes found in this BETA release.

Check out the latest code from the Viewpoint Github repository
...or install the gem version 0.1.0 "gem install viewpoint"

New SOAP backend

Viewpoint now uses Handsoap as its back-end instead of soap4r. While soap4r does some very nice things for you automatically, it ends up making your code base fairly large and it complicates any customizations that you might want to make. One example is adding custom headers. Soap4r required you to create a subclass to use as a sort of hook. I can do the same thing in Handsoap with a one-liner in the services #on_create_document method.

Models are completely rewritten

The models are completely new and not backward compatible with the old version of Viewpoint. Some of the methods still exist, but don't count on them. I've tried to make this version much more extensible than the last.

Configuration loader removed

After much thought I determined it really wasn't the place of a client library to provide a configuration loader for credentials. To that end I removed the need for a .viewpointrc file. If this is something you liked it would be relatively easy to write it into your application. Now authentication configuration information is set via class methods:
Viewpoint::EWS::EWS.endpoint = ''

Delegate access is supported

One thing that was often asked for, but missing from the previous version was delegate access to mailboxes and calendars. This is now supported via the 'act_as' parameter to the GenericFolder::get_folder method. For example:

ofolder = Folder.get_folder(:inbox,'')

If your user has delegate access to the Inbox for this operation will retrieve their inbox and allow you to manipulate it as you would with your own Inbox. There is also some support for manipulation of delegate access itself via the methods MailboxUser#add_delegate!, MailboxUser#update_delegate!, and MailboxUser#get_delegate_info.

Some Exchange 2010 Stubs

Some of the new features of Exchange 2010 are being stubbed in. I do not have access to an Exchange 2010 server to test them on so I cannot verify if they work or not.

Misc other changes

Since it's a complete rewrite there are tons of other changes that you'll notice. I've tried to keep the code comments coming so stay tuned to the API docs for library information. I'll also be posting more examples to my blog.

So at a glance there you have it. If there are any features you would like to see added or comments please add it to the bottom of this post or add an issue on the Github page. Also, if you're interested in sponsoring an Exchange 2010 account for me please let me know. I would love to try out some of the new advanced query stuff that 2010 has to offer.




  1. Can viewpoint be used to update GAL (global address book)?

  2. Joshua,

    Exchange Web Services and therefore Viewpoint only supports resolving names via the GAL and not updating it. Since the GAL is just Active Directory you should be able to use the net-ldap gem to make modifications. However, Viewpoint will let you add contacts and query contacts that you have added to your Contacts folder.



  3. I can't tell you how pleased I am so far with Viewpoint. I'd been dreading our Exchange integration for weeks when I found Viewpoint and I've been working with it for the last several nights. I investigated the old Viewpoint a while ago, and the new stuff is so clean it's just fun to work with.

    Is there a roadmap for additions to Viewpoint?



  4. Marc,

    Glad you find Viewpoint useful. I do not have a roadmap for it, but I would like to get a hold of an Exchange 2010 server soon to play with some of the new features like Unified Messaging and advanced filtering. However, I've been pouring most of my free time into WinRM ( lately so Viewpoint's been on my back-burner. If you have any features you'd like to see add them to the issues list on Github and mark them as a "feature request".



  5. It is wery usefull. But I cannot find way how to access public folder like \Calendars\Test.

    Viewpoint::EWS::CalendarFolder.find_folders() doesn't return them and Viewpoint::EWS::GenericFolder.get_folder_by_name('\Calendars\Test') doesn't work as well.

  6. Lukas,

    #get_folder_by_name does not work for subfolders yet. You should put in a feature request on the github page for Viewpoint if you would like to see it as an add-on. I did however create a subfolder called "Test" under my calendar folder and Viewpoint::EWS::CalendarFolder.find_folders() did find it. Make sure that "Test" is indeed of type CalendarFolder.


  7. Hi,
    Thanks for your great work. I have been using it. It save me lots of time.
    I just do not find how to update exchange items from ruby app. Is this feature implemented ?

  8. This comment has been removed by the author.

  9. @guero

    There really isn't a good way to "update" items today. You can however create new items (Calendar, Mail, etc). Take a look at the Message.send and CalendarItem.create_item class methods in the API docs:

  10. hi zenTourist, thanks for your reply.
    Indeed, today when I want to update a calendar item, I delete it and create a new one.

    When you say that there isn't a good way to update items, is this means that viewpoint does not implement it ? or is it means that exchange api do not allow it ?

  11. @guero, it means I haven't implemented it in Viewpoint yet. Exchange Web Services has it implemented and the stubs are in Viewpoint. See:
    Viewpoint::EWS::SOAP::ExchangeWebService#update_item and

    Basically, I haven't had a need for it yet so I haven't implemented it.

  12. I have just come across this GEM and have the following:

    require 'rubygems'
    require 'kconv'
    require 'viewpoint'
    require 'json'

    creds = JSON.load('creds.json','r'))
    Viewpoint::EWS::EWS.endpoint = creds['endpoint']
    @ews = Viewpoint::EWS::EWS.instance

    puts "EWS Object:"
    puts @ews.inspect



    rescue Handsoap::HttpError => e
    puts e.response.inspect

    The response is:

    EWS Object:
    --- Response ---
    HTTP Status: 415
    X-Powered-By: ASP.NET
    X-Aspnet-Version: 2.0.50727
    Server: Microsoft-IIS/7.5
    Date: Mon, 08 Nov 2010 19:39:42 GMT
    Content-Length: 0
    Set-Cookie: exchangecookie=cda2bd5d1178404090b5491582458f23; expires=Tue, 08-Nov-2011 19:39:42 GMT; path=/; HttpOnly
    Cache-Control: private


    Any insight as to why I get a 415 HTTP response would be great.

    Note I am new to EWS.

  13. Kayzio, Did you try hitting your EWS endpoint with a browser first to make sure it's returning a WSDL?

  14. I hit it in Firefox, which prompted me for my username and password, I entered my credentials, then it took me to Service.wsdl in the browser without an issue. I am using Excnage Server 2010 in case that makes a difference.

  15. I really don't know why you would be getting the 415 error. I don't think Exchange 2010 should matter, but I do not have access to a 2010 server to test on so I can't say 100% for sure.

  16. I ended up just using CURL instead.

  17. Sorry it wouldn't work for you. Hopefully I can get access to a 2010 server sometime and bang on it for a bit.



  18. I'm trying to use Viewpoint 0.1.21 on Mac OS X 10.6.6 with ruby 1.8.7, but I keep getting an error when running the following basic script:

    require 'rubygems'
    require 'viewpoint'

    Viewpoint::EWS::EWS.endpoint = ''
    Viewpoint::EWS::EWS.set_trust_ca('cacert.pem') # from
    @ews = Viewpoint::EWS::EWS.instance

    The error I'm getting says:

    /Library/Ruby/Gems/1.8/gems/viewpoint-0.1.21/lib/soap/handsoap/parser.rb:28:in `initialize': undefined method `/' for nil:NilClass (NoMethodError)
    from /Library/Ruby/Gems/1.8/gems/viewpoint-0.1.21/lib/soap/handsoap/ews_service.rb:772:in `new'
    from /Library/Ruby/Gems/1.8/gems/viewpoint-0.1.21/lib/soap/handsoap/ews_service.rb:772:in `parse!'
    from /Library/Ruby/Gems/1.8/gems/viewpoint-0.1.21/lib/soap/handsoap/ews_service.rb:120:in `resolve_names'
    from /Library/Ruby/Gems/1.8/gems/viewpoint-0.1.21/lib/model/mailbox_user.rb:36:in `find_user'
    from /Library/Ruby/Gems/1.8/gems/viewpoint-0.1.21/lib/viewpoint.rb:130:in `me'
    from test.rb:9

    Any ideas what's wrong?

    Thank you very much!

  19. Bernd,

    Your endpoint is wrong. The url should end in '/ews/exchange.asmx'

    If you have any additional issues open an issue the the Viewpoint Github site:



  20. Oops. My mistake. I changed the URL and Viewpoint works as advertised. Awesome! :-)

    The one thing I don't quite understand is why the implementation of CalendarFolder::items_between overwrites the option max_entries_returned and sets it to 256:

    opts[:calendar_view] = {:max_entries_returned => 256, ...

    Is there an easy work-around to increase max_entries_returned without patching the latest release of Viewpoint? Is there a reason why it has to be 256? Can it be larger?

    Thanks again and awesome work!


  21. Glad it's working for you.

    There really isn't a good reason for the 256 limit. It was just a good default at the time and I never revisited it to extend the API. If you could open up an issue (feature request) on Github so it doesn't get lost in the fray I'll add a way to increase the max in the next release.

    In the meantime you can use #find_items as a work-around.

    opts[:calendar_view] = {:max_entries_returned => maxnum, :start_date => start_date, :end_date => end_date}

  22. Great work, love Ruby and love your plugin/gem.

  23. @dejan glad it's working well for you.

  24. This is a great library thanks so much for the efforts!

    A question: I am running into validation trouble:

    folders = Viewpoint::EWS::CalendarFolder.find_folders
    Handsoap::Fault: Handsoap::Fault { :code => 'soap11:Client', :reason => 'The request failed schema validation: The element 'Contains' in namespace '' has invalid child element 'Constant' in namespace ''. List of possible elements expected: 'Path' in namespace ''.' }
    from /Library/Ruby/Gems/1.8/gems/handsoap-1.1.8/lib/handsoap/service.rb:379:in `on_fault'
    from /Library/Ruby/Gems/1.8/gems/handsoap-1.1.8/lib/handsoap/service.rb:434:in `parse_http_response'
    from /Library/Ruby/Gems/1.8/gems/handsoap-1.1.8/lib/handsoap/service.rb:250:in `invoke'
    from /Library/Ruby/Gems/1.8/gems/viewpoint-0.1.24/lib/soap/handsoap/ews_service.rb:780:in `invoke'
    from /Library/Ruby/Gems/1.8/gems/viewpoint-0.1.24/lib/soap/handsoap/ews_service.rb:184:in `find_item'
    from /Library/Ruby/Gems/1.8/gems/viewpoint-0.1.24/lib/model/generic_folder.rb:225:in `find_items'
    from /Library/Ruby/Gems/1.8/gems/viewpoint-0.1.24/lib/model/generic_folder.rb:300:in `search_by_subject'
    from (irb):48
    from :0

    Any ideas what is going on here? I did some debugging and it looks like the XML getting sent over to my exchange server is correct.

    I can create items and retrieve them fine via folder[0].find_items, so I know I'm on the right track. Any help would be tremendously appreciated!

  25. @dhawt

    It looks like there was a Hash ordering issue with ruby 1.8 clients. I fixed it and pushed out a new gem: 0.1.25 that has the fix.

  26. Looks like it's working now ... thanks!