├── .devcontainer └── devcontainer.json ├── .github ├── dependabot.yml └── workflows │ └── ruby.yml ├── .gitignore ├── Changelog.txt ├── Gemfile ├── Guardfile ├── LICENSE ├── README.md ├── Rakefile ├── TODO ├── VERSION ├── lib ├── ews │ ├── calendar_accessors.rb │ ├── connection.rb │ ├── connection_helper.rb │ ├── convert_accessors.rb │ ├── errors.rb │ ├── ews_client.rb │ ├── exceptions │ │ └── exceptions.rb │ ├── folder_accessors.rb │ ├── impersonation.rb │ ├── item_accessors.rb │ ├── mailbox_accessors.rb │ ├── meeting_accessors.rb │ ├── message_accessors.rb │ ├── push_subscription_accessors.rb │ ├── room_accessors.rb │ ├── roomlist_accessors.rb │ ├── soap.rb │ ├── soap │ │ ├── builders │ │ │ └── ews_builder.rb │ │ ├── ews_response.rb │ │ ├── ews_soap_availability_response.rb │ │ ├── ews_soap_free_busy_response.rb │ │ ├── ews_soap_response.rb │ │ ├── ews_soap_room_response.rb │ │ ├── ews_soap_roomlist_response.rb │ │ ├── exchange_availability.rb │ │ ├── exchange_data_services.rb │ │ ├── exchange_notification.rb │ │ ├── exchange_synchronization.rb │ │ ├── exchange_time_zones.rb │ │ ├── exchange_user_configuration.rb │ │ ├── exchange_web_service.rb │ │ ├── parsers │ │ │ ├── ews_parser.rb │ │ │ └── ews_sax_document.rb │ │ ├── response_message.rb │ │ └── responses │ │ │ ├── create_attachment_response_message.rb │ │ │ ├── create_item_response_message.rb │ │ │ ├── find_item_response_message.rb │ │ │ ├── get_events_response_message.rb │ │ │ ├── send_notification_response_message.rb │ │ │ ├── subscribe_response_message.rb │ │ │ ├── sync_folder_hierarchy_response_message.rb │ │ │ └── sync_folder_items_response_message.rb │ ├── templates │ │ ├── calendar_item.rb │ │ ├── forward_item.rb │ │ ├── message.rb │ │ ├── reply_to_item.rb │ │ └── task.rb │ ├── types.rb │ └── types │ │ ├── attachment.rb │ │ ├── attendee.rb │ │ ├── calendar_folder.rb │ │ ├── calendar_item.rb │ │ ├── contact.rb │ │ ├── contacts_folder.rb │ │ ├── copied_event.rb │ │ ├── created_event.rb │ │ ├── deleted_event.rb │ │ ├── distribution_list.rb │ │ ├── event.rb │ │ ├── export_items_response_message.rb │ │ ├── file_attachment.rb │ │ ├── folder.rb │ │ ├── free_busy_changed_event.rb │ │ ├── generic_folder.rb │ │ ├── item.rb │ │ ├── item_attachment.rb │ │ ├── item_field_uri_map.rb │ │ ├── mailbox_user.rb │ │ ├── meeting_cancellation.rb │ │ ├── meeting_message.rb │ │ ├── meeting_request.rb │ │ ├── meeting_response.rb │ │ ├── message.rb │ │ ├── modified_event.rb │ │ ├── moved_event.rb │ │ ├── new_mail_event.rb │ │ ├── out_of_office.rb │ │ ├── post_item.rb │ │ ├── search_folder.rb │ │ ├── status_event.rb │ │ ├── task.rb │ │ └── tasks_folder.rb ├── viewpoint.rb └── viewpoint │ ├── logging.rb │ ├── logging │ └── config.rb │ └── string_utils.rb ├── preamble ├── spec ├── .rspec ├── ews │ ├── ews_client_spec.rb │ └── types │ │ └── calendar_item_spec.rb ├── soap_data │ ├── basic_request.xml │ ├── copy_folder_request.xml │ ├── create_folder_request.xml │ ├── delete_folder_request.xml │ ├── dodgy_ews_response.xml │ ├── empty_folder_request.xml │ ├── find_folder_error_response.xml │ ├── find_folder_request.xml │ ├── find_folder_response.xml │ ├── get_folder_request.xml │ ├── get_room_lists_request.xml │ ├── get_rooms_request.xml │ └── move_folder_request.xml ├── spec_helper.rb ├── unit │ ├── dodgy_file_spec.rb │ ├── ews_folder_operations_spec.rb │ ├── ews_parser_spec.rb │ ├── ews_rooms_operations_spec.rb │ ├── ews_soap_free_busy_response_spec.rb │ ├── folder_accessors_spec.rb │ ├── item_accessors_spec.rb │ ├── mailbox_accessors_spec.rb │ ├── meeting_accessors_spec.rb │ └── soap │ │ └── builders │ │ └── ews_builder_spec.rb ├── viewpoint │ └── string_utils_spec.rb └── xml_matcher.rb └── viewpoint.gemspec /.devcontainer/devcontainer.json: -------------------------------------------------------------------------------- 1 | // For format details, see https://aka.ms/devcontainer.json. For config options, see the 2 | // README at: https://github.com/devcontainers/templates/tree/main/src/ruby 3 | { 4 | "name": "Ruby", 5 | // Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile 6 | "image": "mcr.microsoft.com/devcontainers/ruby:1-3.3-bullseye" 7 | 8 | // Features to add to the dev container. More info: https://containers.dev/features. 9 | // "features": {}, 10 | 11 | // Use 'forwardPorts' to make a list of ports inside the container available locally. 12 | // "forwardPorts": [], 13 | 14 | // Use 'postCreateCommand' to run commands after the container is created. 15 | // "postCreateCommand": "ruby --version", 16 | 17 | // Configure tool-specific properties. 18 | // "customizations": {}, 19 | 20 | // Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root. 21 | // "remoteUser": "root" 22 | } 23 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # To get started with Dependabot version updates, you'll need to specify which 2 | # package ecosystems to update and where the package manifests are located. 3 | # Please see the documentation for more information: 4 | # https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates 5 | # https://containers.dev/guide/dependabot 6 | 7 | version: 2 8 | updates: 9 | - package-ecosystem: "devcontainers" 10 | directory: "/" 11 | schedule: 12 | interval: weekly 13 | -------------------------------------------------------------------------------- /.github/workflows/ruby.yml: -------------------------------------------------------------------------------- 1 | # This workflow uses actions that are not certified by GitHub. 2 | # They are provided by a third-party and are governed by 3 | # separate terms of service, privacy policy, and support 4 | # documentation. 5 | # This workflow will download a prebuilt Ruby version, install dependencies and run tests with Rake 6 | # For more information see: https://github.com/marketplace/actions/setup-ruby-jruby-and-truffleruby 7 | 8 | name: Ruby 9 | 10 | on: 11 | - push 12 | - pull_request 13 | 14 | permissions: 15 | contents: read 16 | 17 | jobs: 18 | test: 19 | 20 | runs-on: ubuntu-latest 21 | strategy: 22 | matrix: 23 | ruby-version: ['2.7', '3.0', '3.1', '3.2', '3.3'] 24 | 25 | steps: 26 | - uses: actions/checkout@v4 27 | - name: Set up Ruby 28 | uses: ruby/setup-ruby@v1 29 | with: 30 | ruby-version: ${{ matrix.ruby-version }} 31 | bundler-cache: true # runs 'bundle install' and caches installed gems automatically 32 | - name: Run tests 33 | run: bundle exec rspec 34 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | Gemfile.lock 2 | .DS_Store 3 | .rvmrc 4 | *.swp 5 | /test*.rb 6 | /\.test* 7 | .idea 8 | tmp 9 | vendor 10 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org/' 2 | 3 | gemspec 4 | 5 | group :development do 6 | gem 'rspec' 7 | gem 'rb-inotify', :require => false 8 | gem 'turn' 9 | gem "pry-nav" 10 | end 11 | -------------------------------------------------------------------------------- /Guardfile: -------------------------------------------------------------------------------- 1 | # A sample Guardfile 2 | # More info at https://github.com/guard/guard#readme 3 | 4 | guard 'rspec' do 5 | watch(%r{^spec/.+_spec\.rb$}) 6 | watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" } 7 | watch('spec/spec_helper.rb') { "spec" } 8 | end 9 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require 'rubygems' 2 | require 'bundler' 3 | 4 | require 'bundler/gem_tasks' 5 | require 'date' 6 | 7 | task :default => [:gem] 8 | 9 | desc "Build the gem without a version change" 10 | task :gem do 11 | system "gem build viewpoint.gemspec" 12 | end 13 | 14 | desc "Clean the build environment" 15 | task :clean do 16 | system "rm -f viewpoint*.gem" 17 | end 18 | 19 | desc "Build the gem, but increment the version first" 20 | task :newrelease => [:versionup, :clean, :gem] 21 | 22 | 23 | desc "Increment the version by 1 minor release" 24 | task :versionup do 25 | ver = up_min_version 26 | puts "New version: #{ver}" 27 | end 28 | 29 | 30 | def up_min_version 31 | f = File.open('VERSION', 'r+') 32 | ver = f.readline.chomp 33 | v_arr = ver.split(/\./).map do |v| 34 | v.to_i 35 | end 36 | v_arr[2] += 1 37 | ver = v_arr.join('.') 38 | f.rewind 39 | f.write(ver) 40 | f.close 41 | ver 42 | end 43 | -------------------------------------------------------------------------------- /TODO: -------------------------------------------------------------------------------- 1 | h2. TODOS 2 | 3 | * Automate "deepening" of Model objects by over-riding method_missing 4 | 5 |
 6 | if object.is_shallow? && all_methods.index(method)
 7 |   deepen!
 8 | else
 9 |   raise the NoMethod error
10 | 
11 | 12 | * Clean-up exceptions. There is exception raising in the Model that will never ocurr because it is already being checked for in the Parser 13 | 14 | * Refactor #find_folders methods. There is a lot of duplicate code right now and it could be simplified quite a bit. 15 | 16 | * Test TODO 17 | ** Test for undefined methods and make sure the method_missing method isn't causing problems 18 | -------------------------------------------------------------------------------- /VERSION: -------------------------------------------------------------------------------- 1 | 1.1.0 2 | -------------------------------------------------------------------------------- /lib/ews/calendar_accessors.rb: -------------------------------------------------------------------------------- 1 | =begin 2 | This file is a cotribution to Viewpoint; the Ruby library for Microsoft Exchange Web Services. 3 | 4 | Copyright © 2013 Mark McCahill 5 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); 7 | you may not use this file except in compliance with the License. 8 | You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | =end 18 | 19 | module Viewpoint::EWS::CalendarAccessors 20 | include Viewpoint::EWS 21 | 22 | def event_busy_type( the_event ) 23 | the_event[:calendar_event][:elems][2][:busy_type][:text] 24 | end 25 | 26 | def event_start_time( the_event ) 27 | the_event[:calendar_event][:elems][0][:start_time][:text] 28 | end 29 | 30 | def event_end_time( the_event ) 31 | the_event[:calendar_event][:elems][1][:end_time][:text] 32 | end 33 | 34 | end # Viewpoint::EWS::CalendarAccessors 35 | -------------------------------------------------------------------------------- /lib/ews/connection.rb: -------------------------------------------------------------------------------- 1 | =begin 2 | This file is part of Viewpoint; the Ruby library for Microsoft Exchange Web Services. 3 | 4 | Copyright © 2011 Dan Wanek 5 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); 7 | you may not use this file except in compliance with the License. 8 | You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | =end 18 | require 'httpclient' 19 | 20 | class Viewpoint::EWS::Connection 21 | include Viewpoint::EWS::ConnectionHelper 22 | include Viewpoint::EWS 23 | 24 | attr_reader :endpoint 25 | # @param [String] endpoint the URL of the web service. 26 | # @example https:///ews/Exchange.asmx 27 | # @param [Hash] opts Misc config options (mostly for developement) 28 | # @option opts [Fixnum] :ssl_verify_mode 29 | # @option opts [Fixnum] :receive_timeout override the default receive timeout 30 | # seconds 31 | # @option opts [Fixnum] :connect_timeout override the default connect timeout 32 | # seconds 33 | # @option opts [Array] :trust_ca an array of hashed dir paths or a file 34 | # @option opts [String] :user_agent the http user agent to use in all requests 35 | def initialize(endpoint, opts = {}) 36 | @log = Logging.logger[self.class.name.to_s.to_sym] 37 | if opts[:user_agent] 38 | @httpcli = HTTPClient.new(agent_name: opts[:user_agent]) 39 | else 40 | @httpcli = HTTPClient.new 41 | end 42 | 43 | if opts[:trust_ca] 44 | @httpcli.ssl_config.clear_cert_store 45 | opts[:trust_ca].each do |ca| 46 | @httpcli.ssl_config.add_trust_ca ca 47 | end 48 | end 49 | 50 | @httpcli.ssl_config.verify_mode = opts[:ssl_verify_mode] if opts[:ssl_verify_mode] 51 | @httpcli.ssl_config.ssl_version = opts[:ssl_version] if opts[:ssl_version] 52 | # Up the keep-alive so we don't have to do the NTLM dance as often. 53 | @httpcli.keep_alive_timeout = 60 54 | @httpcli.receive_timeout = opts[:receive_timeout] if opts[:receive_timeout] 55 | @httpcli.connect_timeout = opts[:connect_timeout] if opts[:connect_timeout] 56 | @endpoint = endpoint 57 | end 58 | 59 | def set_auth(user,pass) 60 | @httpcli.set_auth(@endpoint.to_s, user, pass) 61 | end 62 | 63 | # Authenticate to the web service. You don't have to do this because 64 | # authentication will happen on the first request if you don't do it here. 65 | # @return [Boolean] true if authentication is successful, false otherwise 66 | def authenticate 67 | self.get && true 68 | end 69 | 70 | # Every Connection class must have the dispatch method. It is what sends the 71 | # SOAP request to the server and calls the parser method on the EWS instance. 72 | # 73 | # This was originally in the ExchangeWebService class but it was added here 74 | # to make the processing chain easier to modify. For example, it allows the 75 | # reactor pattern to handle the request with a callback. 76 | # @param ews [Viewpoint::EWS::SOAP::ExchangeWebService] used to call 77 | # #parse_soap_response 78 | # @param soapmsg [String] 79 | # @param opts [Hash] misc opts for handling the Response 80 | def dispatch(ews, soapmsg, opts) 81 | respmsg = post(soapmsg) 82 | @log.debug <<-EOF.gsub(/^ {6}/, '') 83 | Received SOAP Response: 84 | ---------------- 85 | #{Nokogiri::XML(respmsg).to_xml} 86 | ---------------- 87 | EOF 88 | opts[:raw_response] ? respmsg : ews.parse_soap_response(respmsg, opts) 89 | end 90 | 91 | # Send a GET to the web service 92 | # @return [String] If the request is successful (200) it returns the body of 93 | # the response. 94 | def get 95 | check_response( @httpcli.get(@endpoint) ) 96 | end 97 | 98 | # Send a POST to the web service 99 | # @return [String] If the request is successful (200) it returns the body of 100 | # the response. 101 | def post(xmldoc) 102 | headers = {'Content-Type' => 'text/xml'} 103 | check_response( @httpcli.post(@endpoint, xmldoc, headers) ) 104 | end 105 | 106 | 107 | private 108 | 109 | def check_response(resp) 110 | case resp.status 111 | when 200 112 | resp.body 113 | when 302 114 | # @todo redirect 115 | raise Errors::UnhandledResponseError.new("Unhandled HTTP Redirect", resp) 116 | when 401 117 | raise Errors::UnauthorizedResponseError.new("Unauthorized request", resp) 118 | when 500 119 | if resp.headers['Content-Type'] =~ /xml/ 120 | err_string, err_code = parse_soap_error(resp.body) 121 | raise Errors::SoapResponseError.new("SOAP Error: Message: #{err_string} Code: #{err_code}", resp, err_code, err_string) 122 | else 123 | raise Errors::ServerError.new("Internal Server Error. Message: #{resp.body}", resp) 124 | end 125 | else 126 | raise Errors::ResponseError.new("HTTP Error Code: #{resp.status}, Msg: #{resp.body}", resp) 127 | end 128 | end 129 | 130 | # @param [String] xml to parse the errors from. 131 | def parse_soap_error(xml) 132 | ndoc = Nokogiri::XML(xml) 133 | ns = ndoc.collect_namespaces 134 | err_string = ndoc.xpath("//faultstring",ns).text 135 | err_code = ndoc.xpath("//faultcode",ns).text 136 | @log.debug "Internal SOAP error. Message: #{err_string}, Code: #{err_code}" 137 | [err_string, err_code] 138 | end 139 | 140 | end 141 | -------------------------------------------------------------------------------- /lib/ews/connection_helper.rb: -------------------------------------------------------------------------------- 1 | =begin 2 | This file is part of Viewpoint; the Ruby library for Microsoft Exchange Web Services. 3 | 4 | Copyright © 2011 Dan Wanek 5 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); 7 | you may not use this file except in compliance with the License. 8 | You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | =end 18 | 19 | module Viewpoint::EWS::ConnectionHelper 20 | 21 | def init_logging! 22 | @log = Logging.logger[self.class.name.to_s.to_sym] 23 | end 24 | 25 | # @param [String] xml to parse the errors from. 26 | def parse_soap_error(xml) 27 | ndoc = Nokogiri::XML(xml) 28 | ns = ndoc.collect_namespaces 29 | err_string = ndoc.xpath("//faultstring",ns).text 30 | err_code = ndoc.xpath("//faultcode",ns).text 31 | @log.debug "Internal SOAP error. Message: #{err_string}, Code: #{err_code}" 32 | [err_string, err_code] 33 | end 34 | 35 | end 36 | -------------------------------------------------------------------------------- /lib/ews/convert_accessors.rb: -------------------------------------------------------------------------------- 1 | =begin 2 | This file is part of Viewpoint; the Ruby library for Microsoft Exchange Web Services. 3 | 4 | Copyright © 2013 Dan Wanek 5 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); 7 | you may not use this file except in compliance with the License. 8 | You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | =end 18 | module Viewpoint::EWS::ConvertAccessors 19 | include Viewpoint::EWS 20 | 21 | # This is a class method that converts identifiers between formats. 22 | # @param [String] id The id to be converted 23 | # @param [Hash] opts Misc options to control request 24 | # @option opts [Symbol] :format :ews_legacy_id/:ews_id/:entry_id/:hex_entry_id/:store_id/:owa_id 25 | # @option opts [Symbol] :destination_format :ews_legacy_id/:ews_id/:entry_id/:hex_entry_id/:store_id/:owa_id 26 | # @option opts [String] :mailbox Mailbox, if required 27 | # @return [EwsResponse] Returns an EwsResponse containing the convert response message 28 | 29 | def convert_id(id, opts = {}) 30 | args = convert_id_args(id, opts.clone) 31 | obj = OpenStruct.new(opts: args) 32 | yield obj if block_given? 33 | resp = ews.convert_id(args) 34 | convert_id_parser(resp) 35 | end 36 | 37 | private 38 | 39 | def convert_id_args(id, opts) 40 | { id: id }.merge opts 41 | end 42 | 43 | def convert_id_parser(resp) 44 | rm = resp.response_messages[0] 45 | 46 | if(rm && rm.status == 'Success') 47 | # @todo create custom response class 48 | rm 49 | else 50 | code = rm.respond_to?(:code) ? rm.code : "Unknown" 51 | text = rm.respond_to?(:message_text) ? rm.message_text : "Unknown" 52 | raise EwsError, "Could not convert id. #{rm.code}: #{rm.message_text}" 53 | end 54 | end 55 | 56 | end # Viewpoint::EWS::ItemAccessors 57 | -------------------------------------------------------------------------------- /lib/ews/errors.rb: -------------------------------------------------------------------------------- 1 | =begin 2 | This file is part of Viewpoint; the Ruby library for Microsoft Exchange Web Services. 3 | 4 | Copyright © 2011 Dan Wanek 5 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); 7 | you may not use this file except in compliance with the License. 8 | You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | =end 18 | 19 | module Viewpoint::EWS::Errors 20 | class ResponseError < RuntimeError 21 | attr_reader :response 22 | 23 | def initialize(message, response) 24 | super(message) 25 | @response = response 26 | end 27 | 28 | def status 29 | response.status 30 | end 31 | 32 | def body 33 | response.body 34 | end 35 | end 36 | 37 | class UnhandledResponseError < ResponseError 38 | end 39 | 40 | class ServerError < ResponseError 41 | end 42 | 43 | class UnauthorizedResponseError < ResponseError 44 | end 45 | 46 | class SoapResponseError < ResponseError 47 | attr_reader :faultcode, 48 | :faultstring 49 | 50 | def initialize(message, response, faultcode, faultstring) 51 | super(message, response) 52 | @faultcode = faultcode 53 | @faultstring = faultstring 54 | end 55 | end 56 | end 57 | -------------------------------------------------------------------------------- /lib/ews/ews_client.rb: -------------------------------------------------------------------------------- 1 | require 'ews/folder_accessors' 2 | require 'ews/item_accessors' 3 | require 'ews/message_accessors' 4 | require 'ews/mailbox_accessors' 5 | require 'ews/push_subscription_accessors' 6 | require 'ews/calendar_accessors' 7 | require 'ews/room_accessors' 8 | require 'ews/roomlist_accessors' 9 | require 'ews/convert_accessors' 10 | require 'ews/meeting_accessors' 11 | 12 | # This class is the glue between the Models and the Web Service. 13 | class Viewpoint::EWSClient 14 | include Viewpoint::EWS 15 | include Viewpoint::EWS::FolderAccessors 16 | include Viewpoint::EWS::ItemAccessors 17 | include Viewpoint::EWS::MessageAccessors 18 | include Viewpoint::EWS::MailboxAccessors 19 | include Viewpoint::EWS::PushSubscriptionAccessors 20 | include Viewpoint::EWS::CalendarAccessors 21 | include Viewpoint::EWS::RoomAccessors 22 | include Viewpoint::EWS::RoomlistAccessors 23 | include Viewpoint::EWS::ConvertAccessors 24 | include Viewpoint::EWS::MeetingAccessors 25 | include Viewpoint::StringUtils 26 | 27 | # The instance of Viewpoint::EWS::SOAP::ExchangeWebService 28 | attr_reader :ews, :endpoint, :username 29 | 30 | # Initialize the EWSClient instance. 31 | # @param [String] endpoint The EWS endpoint we will be connecting to 32 | # @param [String] user The user to authenticate as. If you are using 33 | # NTLM or Negotiate authentication you do not need to pass this parameter. 34 | # @param [String] pass The user password. If you are using NTLM or 35 | # Negotiate authentication you do not need to pass this parameter. 36 | # @param [Hash] opts Various options to pass to the backends 37 | # @option opts [String] :server_version The Exchange server version to 38 | # target. See the VERSION_* constants in 39 | # Viewpoint::EWS::SOAP::ExchangeWebService. 40 | # @option opts [Object] :http_class specify an alternate HTTP connection class. 41 | # @option opts [Hash] :http_opts options to pass to the connection 42 | def initialize(endpoint, username, password, opts = {}) 43 | # dup all. @see ticket https://github.com/zenchild/Viewpoint/issues/68 44 | @endpoint = endpoint.dup 45 | @username = username.dup 46 | password = password.dup 47 | opts = opts.dup 48 | http_klass = opts[:http_class] || Viewpoint::EWS::Connection 49 | con = http_klass.new(endpoint, opts[:http_opts] || {}) 50 | con.set_auth @username, password 51 | @ews = SOAP::ExchangeWebService.new(con, opts) 52 | end 53 | 54 | # @param deepen [Boolean] true to autodeepen, false otherwise 55 | # @param behavior [Symbol] :raise, :nil When setting autodeepen to false you 56 | # can choose what the behavior is when an attribute does not exist. The 57 | # default is to raise a EwsMinimalObjectError. 58 | def set_auto_deepen(deepen, behavior = :raise) 59 | if deepen 60 | ews.auto_deepen = true 61 | else 62 | behavior = [:raise, :nil].include?(behavior) ? behavior : :raise 63 | ews.no_auto_deepen_behavior = behavior 64 | ews.auto_deepen = false 65 | end 66 | end 67 | 68 | def auto_deepen=(deepen) 69 | set_auto_deepen deepen 70 | end 71 | 72 | # Specify a default time zone context for all time attributes 73 | # @param id [String] Identifier of a Microsoft well known time zone (e.g: 'UTC', 'W. Europe Standard Time') 74 | # @note A list of time zones known by the server can be requested via {EWS::SOAP::ExchangeTimeZones#get_time_zones} 75 | def set_time_zone(microsoft_time_zone_id) 76 | ews.set_time_zone_context microsoft_time_zone_id 77 | end 78 | 79 | private 80 | 81 | 82 | # This method also exists in EWS::Types, but there is a lot of other stuff 83 | # in there that I didn't want to include directly in this class. 84 | def class_by_name(cname) 85 | if(cname.instance_of? Symbol) 86 | cname = camel_case(cname) 87 | end 88 | Viewpoint::EWS::Types.const_get(cname) 89 | end 90 | 91 | # Used for multiple accessors 92 | def merge_restrictions!(obj, merge_type = :and) 93 | if obj.opts[:restriction] && !obj.opts[:restriction].empty? && !obj.restriction.empty? 94 | obj.opts[:restriction] = { 95 | merge_type => [ 96 | obj.opts.delete(:restriction), 97 | obj.restriction 98 | ] 99 | } 100 | elsif !obj.restriction.empty? 101 | obj.opts[:restriction] = obj.restriction 102 | end 103 | end 104 | 105 | end 106 | -------------------------------------------------------------------------------- /lib/ews/exceptions/exceptions.rb: -------------------------------------------------------------------------------- 1 | =begin 2 | This file is part of Viewpoint; the Ruby library for Microsoft Exchange Web Services. 3 | 4 | Copyright © 2011 Dan Wanek 5 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); 7 | you may not use this file except in compliance with the License. 8 | You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | =end 18 | module Viewpoint::EWS 19 | 20 | # Generic Ews Error 21 | class EwsError < StandardError; end 22 | 23 | # Raise when authentication/authorization issues occur. 24 | class EwsLoginError < EwsError; end 25 | 26 | class EwsSubscriptionError < EwsError; end 27 | 28 | # Raised when a user tries to query a folder subscription after the 29 | # subscription has timed out. 30 | class EwsSubscriptionTimeout < EwsSubscriptionError; end 31 | 32 | # Represents a function in EWS that is not yet implemented in Viewpoint 33 | class EwsNotImplemented < EwsError; end 34 | 35 | # Raised when an method is called in the wrong way 36 | class EwsBadArgumentError < EwsError; end 37 | 38 | # Raised when an item that is asked for is not found 39 | class EwsItemNotFound < EwsError; end 40 | 41 | # Raised when a folder that is asked for is not found 42 | class EwsFolderNotFound < EwsError; end 43 | 44 | # Raise an Exchange Server version error. This is in case some functionality 45 | # does not exist in a particular Server version but is called. 46 | class EwsServerVersionError < EwsError; end 47 | 48 | # Raised when #auto_deepen == false and a method is called for attributes 49 | # that have not yet been fetched. 50 | class EwsMinimalObjectError < EwsError; end 51 | 52 | class EwsFrozenObjectError < EwsError; end 53 | 54 | # Failed to save an object back to the EWS store. 55 | class SaveFailed < EwsError; end 56 | 57 | class EwsCreateItemError < EwsError; end 58 | 59 | class EwsSendItemError < EwsError; end 60 | 61 | end # Viewpoint::EWS 62 | -------------------------------------------------------------------------------- /lib/ews/impersonation.rb: -------------------------------------------------------------------------------- 1 | module Viewpoint::EWS 2 | 3 | ConnectingSID = { 4 | :UPN => 'PrincipalName', 5 | :SID => 'SID', 6 | :PSMTP => 'PrimarySmtpAddress', 7 | :SMTP => 'SmtpAddress' 8 | } 9 | 10 | # @param connecting_type [String] should be one of the ConnectingSID variables 11 | # ConnectingSID[:UPN] - use User Principal Name method 12 | # ConnectingSID[:SID] - use Security Identifier method 13 | # ConnectingSID[:PSMTP] - use primary Simple Mail Transfer Protocol method 14 | # ConnectingSID[:SMTP] - use Simple Mail Transfer Protocol method 15 | # you can add any other string, it will be converted into xml tag on soap request 16 | # @param address [String] an address to include to requests for impersonation 17 | def set_impersonation(connecting_type, address) 18 | if ConnectingSID.has_value? connecting_type or connecting_type.is_a? String then 19 | ews.impersonation_type = connecting_type 20 | ews.impersonation_address = address 21 | else 22 | raise EwsBadArgumentError, "Not a proper connecting method: #{connecting_type.class}" 23 | end 24 | end 25 | 26 | def remove_impersonation 27 | ews.impersonation_type = "" 28 | ews.impersonation_address = "" 29 | end 30 | end -------------------------------------------------------------------------------- /lib/ews/mailbox_accessors.rb: -------------------------------------------------------------------------------- 1 | =begin 2 | This file is part of Viewpoint; the Ruby library for Microsoft Exchange Web Services. 3 | 4 | Copyright © 2011 Dan Wanek 5 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); 7 | you may not use this file except in compliance with the License. 8 | You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | =end 18 | 19 | module Viewpoint::EWS::MailboxAccessors 20 | include Viewpoint::EWS 21 | 22 | # Resolve contacts in the Exchange Data Store 23 | # @param [String] ustring A string to resolve contacts to. 24 | # @return [Array] It returns an Array of MailboxUsers. 25 | def search_contacts(ustring) 26 | resp = ews.resolve_names(:name => ustring) 27 | 28 | users = [] 29 | if(resp.status == 'Success') 30 | mb = resp.response_message[:elems][:resolution_set][:elems][0][:resolution][:elems][0] 31 | users << Types::MailboxUser.new(ews, mb[:mailbox][:elems]) 32 | elsif(resp.code == 'ErrorNameResolutionMultipleResults') 33 | resp.response_message[:elems][:resolution_set][:elems].each do |u| 34 | if u[:resolution][:elems][0][:mailbox] 35 | users << Types::MailboxUser.new(ews, u[:resolution][:elems][0][:mailbox][:elems]) 36 | end 37 | end 38 | else 39 | raise EwsError, "Find User produced an error: #{resp.code}: #{resp.message}" 40 | end 41 | users 42 | end 43 | 44 | # GetUserAvailability request 45 | # @see http://msdn.microsoft.com/en-us/library/aa563800.aspx 46 | # @param [Array] emails A list of emails you want to retrieve free-busy info for. 47 | # @param [Hash] opts 48 | # @option opts [DateTime] :start_time 49 | # @option opts [DateTime] :end_time 50 | # @option opts [Symbol] :requested_view :merged_only/:free_busy/ 51 | # :free_busy_merged/:detailed/:detailed_merged 52 | # @option opts [Hash] :time_zone The TimeZone data 53 | # Example: {:bias => 'UTC offset in minutes', 54 | # :standard_time => {:bias => 480, :time => '02:00:00', 55 | # :day_order => 5, :month => 10, :day_of_week => 'Sunday'}, 56 | # :daylight_time => {same options as :standard_time}} 57 | def get_user_availability(emails, opts) 58 | opts = opts.clone 59 | args = get_user_availability_args(emails, opts) 60 | resp = ews.get_user_availability(args.merge(opts)) 61 | get_user_availability_parser(resp) 62 | end 63 | 64 | 65 | private 66 | 67 | def get_user_availability_args(emails, opts) 68 | unless opts.has_key?(:start_time) && opts.has_key?(:end_time) && opts.has_key?(:requested_view) 69 | raise EwsBadArgumentError, "You must specify a start_time, end_time and requested_view." 70 | end 71 | 72 | default_args = { 73 | mailbox_data: (emails.collect{|e| [email: {address: e}]}.flatten), 74 | free_busy_view_options: { 75 | time_window: { 76 | start_time: opts[:start_time], 77 | end_time: opts[:end_time] 78 | }, 79 | requested_view: { :requested_free_busy_view => opts[:requested_view] }, 80 | } 81 | } 82 | end 83 | 84 | def get_user_availability_parser(resp) 85 | if(resp.status == 'Success') 86 | resp 87 | else 88 | raise EwsError, "GetUserAvailability produced an error: #{resp.code}: #{resp.message}" 89 | end 90 | end 91 | 92 | end # Viewpoint::EWS::MailboxAccessors 93 | -------------------------------------------------------------------------------- /lib/ews/meeting_accessors.rb: -------------------------------------------------------------------------------- 1 | module Viewpoint::EWS::MeetingAccessors 2 | include Viewpoint::EWS 3 | 4 | def accept_meeting(opts) 5 | ews.create_item({ 6 | message_disposition: 'SendOnly', 7 | items: [ { accept_item: opts_to_item(opts) } ] 8 | }) 9 | end 10 | 11 | def decline_meeting(opts) 12 | ews.create_item({ 13 | message_disposition: 'SendOnly', 14 | items: [ { decline_item: opts_to_item(opts) } ] 15 | }) 16 | end 17 | 18 | def tentatively_accept_meeting(opts) 19 | ews.create_item({ 20 | message_disposition: 'SendOnly', 21 | items: [ { tentatively_accept_item: opts_to_item(opts) } ] 22 | }) 23 | end 24 | 25 | private 26 | 27 | def opts_to_item(opts) 28 | hash = { 29 | id: opts[:id], 30 | change_key: opts[:change_key], 31 | sensitivity: opts[:sensitivity] 32 | } 33 | 34 | hash[:text] = opts[:text] if opts[:text] 35 | hash[:body_type] = (opts[:body_type] || 'Text') if opts[:text] 36 | 37 | hash 38 | end 39 | end 40 | -------------------------------------------------------------------------------- /lib/ews/message_accessors.rb: -------------------------------------------------------------------------------- 1 | =begin 2 | This file is part of Viewpoint; the Ruby library for Microsoft Exchange Web Services. 3 | 4 | Copyright © 2011 Dan Wanek 5 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); 7 | you may not use this file except in compliance with the License. 8 | You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | =end 18 | module Viewpoint::EWS::MessageAccessors 19 | include Viewpoint::EWS 20 | 21 | # Send an E-mail message 22 | # 23 | # @param [Hash] opts A Hash with message params 24 | # @option opts [String] :subject The message subject 25 | # @option opts [String] :body The message body 26 | # @option opts [Array] :to_recipients An array of e-mail addresses to send to 27 | # @option opts [Array] :cc_recipients An array of e-mail addresses to send to 28 | # @option opts [Array] :bcc_recipients An array of e-mail addresses to send to 29 | # @option opts [Array] :extended_properties An array of extended properties 30 | # [{extended_field_uri: {epros}, value: }] or values: [, ] 31 | # @option opts [Boolean] :draft if true it will save to the draft folder 32 | # without sending the message. 33 | # @option opts [String,Symbol,Hash] saved_item_folder_id Either a 34 | # FolderId(String) or a DistinguishedFolderId(Symbol). You can also pass a 35 | # Hash in the form: {id: , change_key: } 36 | # @option opts [Array] :file_attachments an Array of File or Tempfile objects 37 | # @option opts [Array] :inline_attachments an Array of Inline File or Tempfile objects 38 | # @return [Message,Boolean] Returns true if the message is sent, false if 39 | # nothing is returned from EWS or if draft is true it will return the 40 | # Message object. Finally, if something goes wrong, it raises an error 41 | # with a message stating why the e-mail could not be sent. 42 | # @todo Finish ItemAttachments 43 | def send_message(opts = {}, &block) 44 | msg = Template::Message.new opts.clone 45 | yield msg if block_given? 46 | if msg.has_attachments? 47 | draft = msg.draft 48 | resp = parse_create_item(ews.create_item(msg.to_ews)) 49 | msg.draft = true 50 | msg.file_attachments.each do |f| 51 | next unless f.kind_of?(File) or f.kind_of?(Tempfile) 52 | resp.add_file_attachment(f) 53 | end 54 | msg.inline_attachments.each do |f| 55 | next unless f.kind_of?(File) or f.kind_of?(Tempfile) 56 | resp.add_inline_attachment(f) 57 | end 58 | if draft 59 | resp.submit_attachments! 60 | resp 61 | else 62 | resp.submit! 63 | end 64 | else 65 | resp = ews.create_item(msg.to_ews) 66 | resp.response_messages ? parse_create_item(resp) : false 67 | end 68 | end 69 | 70 | # See #send_message for options 71 | def draft_message(opts = {}, &block) 72 | send_message opts.merge(draft: true), &block 73 | end 74 | 75 | 76 | private 77 | 78 | 79 | def parse_create_item(resp) 80 | rm = resp.response_messages[0] 81 | if(rm.status == 'Success') 82 | rm.items.empty? ? true : parse_message(rm.items.first) 83 | else 84 | raise EwsError, "Could not send message. #{rm.code}: #{rm.message_text}" 85 | end 86 | end 87 | 88 | def parse_message(msg) 89 | mtype = msg.keys.first 90 | message = class_by_name(mtype).new(ews, msg[mtype]) 91 | end 92 | 93 | end # Viewpoint::EWS::MessageAccessors 94 | -------------------------------------------------------------------------------- /lib/ews/push_subscription_accessors.rb: -------------------------------------------------------------------------------- 1 | =begin 2 | This file is part of Viewpoint; the Ruby library for Microsoft Exchange Web Services. 3 | 4 | Copyright © 2011 Dan Wanek 5 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); 7 | you may not use this file except in compliance with the License. 8 | You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | =end 18 | 19 | module Viewpoint::EWS::PushSubscriptionAccessors 20 | include Viewpoint::EWS 21 | 22 | def parse_send_notification(msg) 23 | parser = Viewpoint::EWS::SOAP::EwsParser.new(msg) 24 | resp = parser.parse response_class: Viewpoint::EWS::SOAP::EwsResponse 25 | rmsg = resp.response_messages[0] 26 | if rmsg.success? 27 | rmsg 28 | else 29 | raise EwsSubscriptionError, "#{rmsg.code}: #{rmsg.message_text}" 30 | end 31 | end 32 | 33 | end # Viewpoint::EWS::PushSubscriptionAccessors 34 | -------------------------------------------------------------------------------- /lib/ews/room_accessors.rb: -------------------------------------------------------------------------------- 1 | =begin 2 | This file is part of Viewpoint; the Ruby library for Microsoft Exchange Web Services. 3 | 4 | Copyright © 2013 Camille Baldock 5 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); 7 | you may not use this file except in compliance with the License. 8 | You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | =end 18 | 19 | module Viewpoint::EWS::RoomAccessors 20 | include Viewpoint::EWS 21 | 22 | # Gets the rooms that are available within the specified room distribution list 23 | # @see http://msdn.microsoft.com/en-us/library/dd899415.aspx 24 | # @param [String] roomDistributionList 25 | def get_rooms(roomDistributionList) 26 | resp = ews.get_rooms(roomDistributionList) 27 | get_rooms_parser(resp) 28 | end 29 | 30 | def room_name( room ) 31 | room[:room][:elems][:id][:elems][0][:name][:text] 32 | end 33 | 34 | def room_email( room ) 35 | room[:room][:elems][:id][:elems][1][:email_address][:text] 36 | end 37 | 38 | private 39 | 40 | def get_rooms_parser(resp) 41 | if resp.success? 42 | resp 43 | else 44 | raise EwsError, "GetRooms produced an error: #{resp.code}: #{resp.message}" 45 | end 46 | end 47 | 48 | end # Viewpoint::EWS::RoomAccessors -------------------------------------------------------------------------------- /lib/ews/roomlist_accessors.rb: -------------------------------------------------------------------------------- 1 | =begin 2 | This file is part of Viewpoint; the Ruby library for Microsoft Exchange Web Services. 3 | 4 | Copyright © 2013 Camille Baldock 5 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); 7 | you may not use this file except in compliance with the License. 8 | You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | =end 18 | 19 | module Viewpoint::EWS::RoomlistAccessors 20 | include Viewpoint::EWS 21 | 22 | # Gets the room lists that are available within the Exchange organization. 23 | # @see http://msdn.microsoft.com/en-us/library/dd899416.aspx 24 | def get_room_lists 25 | resp = ews.get_room_lists 26 | get_room_lists_parser(resp) 27 | end 28 | 29 | def roomlist_name( roomlist ) 30 | roomlist[:address][:elems][:name][:text] 31 | end 32 | 33 | def roomlist_email( roomlist ) 34 | roomlist[:address][:elems][:email_address][:text] 35 | end 36 | 37 | private 38 | 39 | def get_room_lists_parser(resp) 40 | if resp.success? 41 | resp 42 | else 43 | raise EwsError, "GetRoomLists produced an error: #{resp.code}: #{resp.message}" 44 | end 45 | end 46 | 47 | end # Viewpoint::EWS::RoomlistAccessors -------------------------------------------------------------------------------- /lib/ews/soap.rb: -------------------------------------------------------------------------------- 1 | =begin 2 | This file is part of Viewpoint; the Ruby library for Microsoft Exchange Web Services. 3 | 4 | Copyright © 2011 Dan Wanek 5 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); 7 | you may not use this file except in compliance with the License. 8 | You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | =end 18 | 19 | # This module defines some constants and other niceties to make available to 20 | # the underlying SOAP classes and modules that do the actual work. 21 | module Viewpoint 22 | module EWS 23 | module SOAP 24 | 25 | # CONSTANTS 26 | 27 | NS_SOAP = 'soap'.freeze 28 | NS_EWS_TYPES = 't'.freeze 29 | NS_EWS_MESSAGES = 'm'.freeze 30 | NAMESPACES = { 31 | "xmlns:#{NS_SOAP}" => 'http://schemas.xmlsoap.org/soap/envelope/', 32 | "xmlns:#{NS_EWS_TYPES}" => 'http://schemas.microsoft.com/exchange/services/2006/types', 33 | "xmlns:#{NS_EWS_MESSAGES}" => 'http://schemas.microsoft.com/exchange/services/2006/messages', 34 | }.freeze 35 | 36 | # used in ResolveNames to determine where names are resolved 37 | ActiveDirectory = 'ActiveDirectory' 38 | ActiveDirectoryContacts = 'ActiveDirectoryContacts' 39 | Contacts = 'Contacts' 40 | ContactsActiveDirectory = 'ContactsActiveDirectory' 41 | 42 | # Target specific Exchange Server versions 43 | # @see http://msdn.microsoft.com/en-us/library/bb891876(v=exchg.140).aspx 44 | VERSION_2007 = 'Exchange2007' 45 | VERSION_2007_SP1 = 'Exchange2007_SP1' 46 | VERSION_2010 = 'Exchange2010' 47 | VERSION_2010_SP1 = 'Exchange2010_SP1' 48 | VERSION_2010_SP2 = 'Exchange2010_SP2' 49 | VERSION_2013 = 'Exchange2013' 50 | VERSION_2013_SP1 = 'Exchange2013_SP1' 51 | VERSION_NONE = 'none' 52 | 53 | HARD_DELETE = 'HardDelete' 54 | SOFT_DELETE = 'SoftDelete' 55 | MOVE_TO_DELETED_ITEMS = 'MoveToDeletedItems' 56 | 57 | def initialize 58 | @log = Logging.logger[self.class.name.to_s.to_sym] 59 | @default_ns = NAMESPACES["xmlns:#{NS_EWS_MESSAGES}"] 60 | end 61 | 62 | end # SOAP 63 | end # EWS 64 | end # Viewpoint 65 | -------------------------------------------------------------------------------- /lib/ews/soap/ews_response.rb: -------------------------------------------------------------------------------- 1 | =begin 2 | This file is part of Viewpoint; the Ruby library for Microsoft Exchange Web Services. 3 | 4 | Copyright © 2011 Dan Wanek 5 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); 7 | you may not use this file except in compliance with the License. 8 | You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | =end 18 | 19 | module Viewpoint::EWS::SOAP 20 | 21 | # A Generic Class for SOAP returns. 22 | class EwsResponse 23 | include Viewpoint::StringUtils 24 | 25 | def initialize(sax_hash) 26 | @resp = sax_hash 27 | simplify! 28 | end 29 | 30 | def envelope 31 | @resp[:envelope][:elems] 32 | end 33 | 34 | def header 35 | envelope[0][:header][:elems] 36 | end 37 | 38 | def body 39 | envelope[1][:body][:elems] 40 | end 41 | 42 | def response 43 | body[0] 44 | end 45 | 46 | def response_messages 47 | return @response_messages if @response_messages 48 | 49 | @response_messages = [] 50 | response_type = response.keys.first 51 | response[response_type][:elems][0][:response_messages][:elems].each do |rm| 52 | response_message_type = rm.keys[0] 53 | rm_klass = class_by_name(response_message_type) 54 | @response_messages << rm_klass.new(rm) 55 | end 56 | @response_messages 57 | end 58 | 59 | 60 | private 61 | 62 | 63 | def simplify! 64 | response_type = response.keys.first 65 | response[response_type][:elems][0][:response_messages][:elems].each do |rm| 66 | key = rm.keys.first 67 | rm[key][:elems] = rm[key][:elems].inject(&:merge) 68 | end 69 | end 70 | 71 | def class_by_name(cname) 72 | begin 73 | if(cname.instance_of? Symbol) 74 | cname = camel_case(cname) 75 | end 76 | Viewpoint::EWS::SOAP.const_get(cname) 77 | rescue NameError => e 78 | ResponseMessage 79 | end 80 | end 81 | 82 | end # EwsSoapResponse 83 | 84 | end # Viewpoint::EWS::SOAP 85 | -------------------------------------------------------------------------------- /lib/ews/soap/ews_soap_availability_response.rb: -------------------------------------------------------------------------------- 1 | =begin 2 | This file is part of Viewpoint; the Ruby library for Microsoft Exchange Web Services. 3 | 4 | Copyright © 2011 Dan Wanek 5 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); 7 | you may not use this file except in compliance with the License. 8 | You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | =end 18 | 19 | module Viewpoint::EWS::SOAP 20 | 21 | # This is a speciality response class to handle the idiosynracies of 22 | # Availability responses. 23 | # @attr_reader [String] :message The text from the EWS element 24 | class EwsSoapAvailabilityResponse < EwsSoapResponse 25 | 26 | def response_messages 27 | nil 28 | end 29 | 30 | def response 31 | body[0][response_key] 32 | end 33 | 34 | def response_message 35 | key = response.keys.first 36 | response[key] 37 | end 38 | 39 | def response_code 40 | response_message[:elems][:response_code][:text] 41 | end 42 | alias :code :response_code 43 | 44 | def response_key 45 | key = body[0].keys.first 46 | end 47 | 48 | private 49 | 50 | def simplify! 51 | key = response_key 52 | body[0][key] = body[0][key][:elems].inject(:merge) 53 | response_message[:elems] = response_message[:elems].inject(:merge) 54 | end 55 | 56 | end # EwsSoapAvailabilityResponse 57 | 58 | end # Viewpoint::EWS::SOAP 59 | -------------------------------------------------------------------------------- /lib/ews/soap/ews_soap_free_busy_response.rb: -------------------------------------------------------------------------------- 1 | =begin 2 | This file is a cotribution to Viewpoint; the Ruby library for Microsoft Exchange Web Services. 3 | 4 | Copyright © 2013 Mark McCahill 5 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); 7 | you may not use this file except in compliance with the License. 8 | You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | =end 18 | 19 | module Viewpoint::EWS::SOAP 20 | 21 | class EwsSoapFreeBusyResponse < EwsSoapResponse 22 | 23 | def initialize(sax_hash) 24 | @resp = sax_hash 25 | simplify! 26 | end 27 | 28 | def envelope 29 | @resp[:envelope][:elems] 30 | end 31 | 32 | def header 33 | envelope[0][:header][:elems] 34 | end 35 | 36 | def body 37 | envelope[1][:body][:elems] 38 | end 39 | 40 | def get_user_availability_response 41 | body.first[:get_user_availability_response][:elems].first[:free_busy_response_array][:elems].first[:free_busy_response][:elems] 42 | end 43 | 44 | def response 45 | body 46 | end 47 | 48 | def calendar_event_array 49 | result = find_in_hash_list(get_user_availability_response[1][:free_busy_view][:elems], :calendar_event_array) 50 | result ? result[:elems] : [] 51 | end 52 | 53 | def working_hours 54 | get_user_availability_response[1][:free_busy_view][:elems][2][:working_hours][:elems] 55 | end 56 | 57 | def response_message 58 | find_in_hash_list(get_user_availability_response, :response_message) 59 | end 60 | 61 | def response_class 62 | response_message[:attribs][:response_class] 63 | end 64 | alias :status :response_class 65 | 66 | def response_code 67 | result = find_in_hash_list(response_message[:elems], :response_code) 68 | result ? result[:text] : nil 69 | end 70 | alias :code :response_code 71 | 72 | def response_message_text 73 | guard_hash response_message[:elems], [:message_text, :text] 74 | end 75 | alias :message :response_message_text 76 | 77 | def response_key 78 | response_message[:elems] 79 | end 80 | 81 | def success? 82 | response_class == "Success" 83 | end 84 | 85 | private 86 | 87 | def simplify! 88 | # key = response_key 89 | # body[0][key] = body[0][key][:elems].inject(:merge) 90 | # response_message[:elems] = response_message[:elems].inject(:merge) 91 | end 92 | 93 | # If the keys don't exist in the Hash return nil 94 | # @param[Hash] hsh 95 | # @param[Array] keys keys to follow in the array 96 | # @return [Object, nil] 97 | def guard_hash(hsh, keys) 98 | key = keys.shift 99 | return nil unless hsh.is_a?(Hash) && hsh.has_key?(key) 100 | 101 | if keys.empty? 102 | hsh[key] 103 | else 104 | guard_hash hsh[key], keys 105 | end 106 | end 107 | 108 | # Find the first element in a list of hashes or return nil 109 | # Example: 110 | # find_in_hash_list([{:foo => :bar}, {:bar => :baz}], :foo) 111 | # => :bar 112 | def find_in_hash_list(collection, key) 113 | result = collection.find { |hsh| hsh.keys.include?(key) } 114 | result ? result[key] : nil 115 | end 116 | 117 | end # EwsSoapFreeBusyResponse 118 | 119 | end # Viewpoint::EWS::SOAP 120 | -------------------------------------------------------------------------------- /lib/ews/soap/ews_soap_response.rb: -------------------------------------------------------------------------------- 1 | =begin 2 | This file is part of Viewpoint; the Ruby library for Microsoft Exchange Web Services. 3 | 4 | Copyright © 2011 Dan Wanek 5 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); 7 | you may not use this file except in compliance with the License. 8 | You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | =end 18 | 19 | module Viewpoint::EWS::SOAP 20 | 21 | # A Generic Class for SOAP returns. 22 | # @attr_reader [String] :message The text from the EWS element 23 | class EwsSoapResponse 24 | 25 | def initialize(sax_hash) 26 | @resp = sax_hash 27 | simplify! 28 | end 29 | 30 | def envelope 31 | @resp[:envelope][:elems] 32 | end 33 | 34 | def header 35 | envelope[0][:header][:elems] 36 | end 37 | 38 | def body 39 | envelope[1][:body][:elems] 40 | end 41 | 42 | def response 43 | body[0] 44 | end 45 | 46 | def response_messages 47 | key = response.keys.first 48 | response[key][:elems].find{|e| e.keys.include? :response_messages }[:response_messages][:elems] 49 | end 50 | 51 | def response_message 52 | key = response_messages[0].keys.first 53 | response_messages[0][key] 54 | end 55 | 56 | def response_class 57 | response_message[:attribs][:response_class] 58 | end 59 | alias :status :response_class 60 | 61 | def response_code 62 | response_message[:elems][:response_code][:text] 63 | end 64 | alias :code :response_code 65 | 66 | def response_message_text 67 | guard_hash response_message[:elems], [:message_text, :text] 68 | end 69 | alias :message :response_message_text 70 | 71 | def success? 72 | response_class == "Success" 73 | end 74 | 75 | 76 | private 77 | 78 | 79 | def simplify! 80 | response_messages.each do |rm| 81 | key = rm.keys.first 82 | rm[key][:elems] = rm[key][:elems].inject(&:merge) 83 | end 84 | end 85 | 86 | # If the keys don't exist in the Hash return nil 87 | # @param[Hash] hsh 88 | # @param[Array] keys keys to follow in the array 89 | # @return [Object, nil] 90 | def guard_hash(hsh, keys) 91 | key = keys.shift 92 | return nil unless hsh.is_a?(Hash) && hsh.has_key?(key) 93 | 94 | if keys.empty? 95 | hsh[key] 96 | else 97 | guard_hash hsh[key], keys 98 | end 99 | end 100 | 101 | end # EwsSoapResponse 102 | 103 | end # Viewpoint::EWS::SOAP 104 | -------------------------------------------------------------------------------- /lib/ews/soap/ews_soap_room_response.rb: -------------------------------------------------------------------------------- 1 | =begin 2 | This file is a contribution to Viewpoint; the Ruby library for Microsoft Exchange Web Services. 3 | 4 | Copyright © 2013 Camille Baldock 5 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); 7 | you may not use this file except in compliance with the License. 8 | You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | =end 18 | 19 | module Viewpoint::EWS::SOAP 20 | 21 | # A class for roomlists SOAP returns. 22 | # @attr_reader [String] :message The text from the EWS element 23 | class EwsSoapRoomResponse < EwsSoapResponse 24 | 25 | def response_messages 26 | key = response.keys.first 27 | subresponse = response[key][:elems][1] 28 | response_class = subresponse.keys.first 29 | subresponse[response_class][:elems] 30 | end 31 | 32 | def roomsArray 33 | response[:get_rooms_response][:elems][1][:rooms][:elems] 34 | end 35 | 36 | def success? 37 | response.first[1][:attribs][:response_class] == "Success" 38 | end 39 | 40 | private 41 | 42 | def simplify! 43 | if response_messages 44 | response_messages.each do |rm| 45 | key = rm.keys.first 46 | rm[key][:elems] = rm[key][:elems].inject(&:merge) 47 | end 48 | end 49 | end 50 | 51 | end # EwsSoapRoomResponse 52 | 53 | end # Viewpoint::EWS::SOAP 54 | -------------------------------------------------------------------------------- /lib/ews/soap/ews_soap_roomlist_response.rb: -------------------------------------------------------------------------------- 1 | =begin 2 | This file is a contribution to Viewpoint; the Ruby library for Microsoft Exchange Web Services. 3 | 4 | Copyright © 2013 Camille Baldock 5 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); 7 | you may not use this file except in compliance with the License. 8 | You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | =end 18 | 19 | module Viewpoint::EWS::SOAP 20 | 21 | # A class for roomlists SOAP returns. 22 | # @attr_reader [String] :message The text from the EWS element 23 | class EwsSoapRoomlistResponse < EwsSoapResponse 24 | 25 | def response_messages 26 | key = response.keys.first 27 | subresponse = response[key][:elems][1] 28 | response_class = subresponse.keys.first 29 | subresponse[response_class][:elems] 30 | end 31 | 32 | def roomListsArray 33 | response[:get_room_lists_response][:elems][1][:room_lists][:elems] 34 | end 35 | 36 | def success? 37 | response.first[1][:attribs][:response_class] == "Success" 38 | end 39 | 40 | private 41 | 42 | 43 | def simplify! 44 | if response_messages 45 | response_messages.each do |rm| 46 | key = rm.keys.first 47 | rm[key][:elems] = rm[key][:elems].inject(&:merge) 48 | end 49 | end 50 | end 51 | 52 | end # EwsSoapRoomlistResponse 53 | 54 | end # Viewpoint::EWS::SOAP 55 | -------------------------------------------------------------------------------- /lib/ews/soap/exchange_availability.rb: -------------------------------------------------------------------------------- 1 | module Viewpoint::EWS::SOAP 2 | 3 | # Exchange Availability operations as listed in the EWS Documentation. 4 | # @see http://msdn.microsoft.com/en-us/library/bb409286.aspx 5 | module ExchangeAvailability 6 | include Viewpoint::EWS::SOAP 7 | 8 | # -------------- Availability Operations ------------- 9 | 10 | # Gets a mailbox user's Out of Office (OOF) settings and messages. 11 | # @see http://msdn.microsoft.com/en-us/library/aa563465.aspx 12 | # @param [Hash] opts 13 | # @option opts [String] :address the email address of the user 14 | # @option opts [String] :name the user display name (optional) 15 | # @option opts [String] :routing_type the routing protocol (optional and stupid) 16 | def get_user_oof_settings(opts) 17 | opts = opts.clone 18 | [:address].each do |k| 19 | validate_param(opts, k, true) 20 | end 21 | req = build_soap! do |type, builder| 22 | if(type == :header) 23 | else 24 | builder.nbuild.GetUserOofSettingsRequest {|x| 25 | x.parent.default_namespace = @default_ns 26 | builder.mailbox!(opts) 27 | } 28 | end 29 | end 30 | do_soap_request(req, response_class: EwsSoapAvailabilityResponse) 31 | end 32 | 33 | # Sets a mailbox user's Out of Office (OOF) settings and message. 34 | # @see http://msdn.microsoft.com/en-us/library/aa580294.aspx 35 | # @param [Hash] opts 36 | # @option opts [Hash] :mailbox the mailbox hash for the use 37 | # @option opts [String,Symbol] :oof_state :enabled, :disabled, :scheduled 38 | # @option opts [Hash] :duration {start_time: DateTime, end_time: DateTime} 39 | # @option opts [String] :internal_reply 40 | # @option opts [String] :external_reply 41 | # @option opts [String,Symbol] :external_audience :none, :known, :all 42 | def set_user_oof_settings(opts) 43 | opts = opts.clone 44 | [:mailbox, :oof_state].each do |k| 45 | validate_param(opts, k, true) 46 | end 47 | req = build_soap! do |type, builder| 48 | if(type == :header) 49 | else 50 | builder.nbuild.SetUserOofSettingsRequest {|x| 51 | x.parent.default_namespace = @default_ns 52 | builder.mailbox! opts.delete(:mailbox) 53 | builder.user_oof_settings!(opts) 54 | } 55 | end 56 | end 57 | do_soap_request(req, response_class: EwsSoapAvailabilityResponse) 58 | end 59 | 60 | end #ExchangeAvailability 61 | end 62 | -------------------------------------------------------------------------------- /lib/ews/soap/exchange_notification.rb: -------------------------------------------------------------------------------- 1 | =begin 2 | This file is part of Viewpoint; the Ruby library for Microsoft Exchange Web Services. 3 | 4 | Copyright © 2011 Dan Wanek 5 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); 7 | you may not use this file except in compliance with the License. 8 | You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | =end 18 | 19 | module Viewpoint::EWS::SOAP 20 | 21 | # Exchange Notification operations as listed in the EWS Documentation. 22 | # @see http://msdn.microsoft.com/en-us/library/bb409286.aspx 23 | module ExchangeNotification 24 | include Viewpoint::EWS::SOAP 25 | 26 | # Used to subscribe client applications to either push, pull or stream notifications. 27 | # @see http://msdn.microsoft.com/en-us/library/aa566188(v=EXCHG.140).aspx 28 | # @param [Array] subscriptions An array of Hash objects that describe each 29 | # subscription. 30 | # Ex: [ {:pull_subscription_request => { 31 | # :subscribe_to_all_folders => false, 32 | # :folder_ids => [ {:id => 'id', :change_key => 'ck'} ], 33 | # :event_types=> %w{CopiedEvent CreatedEvent}, 34 | # :watermark => 'watermark id', 35 | # :timeout => intval 36 | # }}, 37 | # {:push_subscription_request => { 38 | # :subscribe_to_all_folders => true, 39 | # :event_types=> %w{CopiedEvent CreatedEvent}, 40 | # :status_frequency => 15, 41 | # :uRL => 'http://my.endpoint.for.updates/', 42 | # }}, 43 | # {:streaming_subscription_request => { 44 | # :subscribe_to_all_folders => false, 45 | # :folder_ids => [ {:id => 'id', :change_key => 'ck'} ], 46 | # :event_types=> %w{NewMailEvent DeletedEvent}, 47 | # }}, 48 | # ] 49 | def subscribe(subscriptions) 50 | req = build_soap! do |type, builder| 51 | if(type == :header) 52 | else 53 | builder.nbuild.Subscribe { 54 | builder.nbuild.parent.default_namespace = @default_ns 55 | subscriptions.each do |sub| 56 | subtype = sub.keys.first 57 | if(builder.respond_to?(subtype)) 58 | builder.send subtype, sub[subtype] 59 | else 60 | raise EwsBadArgumentError, "Bad subscription type. #{subtype}" 61 | end 62 | end 63 | } 64 | end 65 | end 66 | do_soap_request(req, response_class: EwsResponse) 67 | end 68 | 69 | # End a pull notification subscription. 70 | # @see http://msdn.microsoft.com/en-us/library/aa564263.aspx 71 | # 72 | # @param [String] subscription_id The Id of the subscription 73 | def unsubscribe(subscription_id) 74 | req = build_soap! do |type, builder| 75 | if(type == :header) 76 | else 77 | builder.nbuild.Unsubscribe { 78 | builder.nbuild.parent.default_namespace = @default_ns 79 | builder.subscription_id!(subscription_id) 80 | } 81 | end 82 | end 83 | do_soap_request(req, response_class: EwsResponse) 84 | end 85 | 86 | # Used by pull subscription clients to request notifications from the Client Access server 87 | # @see http://msdn.microsoft.com/en-us/library/aa566199.aspx GetEvents on MSDN 88 | # 89 | # @param [String] subscription_id Subscription identifier 90 | # @param [String] watermark Event bookmark in the events queue 91 | def get_events(subscription_id, watermark) 92 | req = build_soap! do |type, builder| 93 | if(type == :header) 94 | else 95 | builder.nbuild.GetEvents { 96 | builder.nbuild.parent.default_namespace = @default_ns 97 | builder.subscription_id!(subscription_id) 98 | builder.watermark!(watermark, NS_EWS_MESSAGES) 99 | } 100 | end 101 | end 102 | do_soap_request(req, response_class: EwsResponse) 103 | end 104 | 105 | 106 | # ------- convenience methods ------- # 107 | 108 | # Create a pull subscription to a single folder 109 | # @param folder [Hash] a hash with the folder :id and :change_key 110 | # @param evtypes [Array] the events you would like to subscribe to. 111 | # @param timeout [Fixnum] http://msdn.microsoft.com/en-us/library/aa565201.aspx 112 | # @param watermark [String] http://msdn.microsoft.com/en-us/library/aa565886.aspx 113 | def pull_subscribe_folder(folder, evtypes, timeout = nil, watermark = nil) 114 | timeout ||= 240 # 4 hour default timeout 115 | psr = { 116 | :subscribe_to_all_folders => false, 117 | :folder_ids => [ {:id => folder[:id], :change_key => folder[:change_key]} ], 118 | :event_types=> evtypes, 119 | :timeout => timeout 120 | } 121 | psr[:watermark] = watermark if watermark 122 | subscribe([{pull_subscription_request: psr}]) 123 | end 124 | 125 | # Create a push subscription to a single folder 126 | # @param folder [Hash] a hash with the folder :id and :change_key 127 | # @param evtypes [Array] the events you would like to subscribe to. 128 | # @param url [String,URI] http://msdn.microsoft.com/en-us/library/aa566309.aspx 129 | # @param watermark [String] http://msdn.microsoft.com/en-us/library/aa565886.aspx 130 | # @param status_frequency [Fixnum] http://msdn.microsoft.com/en-us/library/aa564048.aspx 131 | def push_subscribe_folder(folder, evtypes, url, status_frequency = nil, watermark = nil) 132 | status_frequency ||= 30 133 | psr = { 134 | :subscribe_to_all_folders => false, 135 | :folder_ids => [ {:id => folder[:id], :change_key => folder[:change_key]} ], 136 | :event_types=> evtypes, 137 | :status_frequency => status_frequency, 138 | :uRL => url.to_s 139 | } 140 | psr[:watermark] = watermark if watermark 141 | subscribe([{push_subscription_request: psr}]) 142 | end 143 | 144 | 145 | end #ExchangeNotification 146 | end 147 | -------------------------------------------------------------------------------- /lib/ews/soap/exchange_synchronization.rb: -------------------------------------------------------------------------------- 1 | =begin 2 | This file is part of Viewpoint; the Ruby library for Microsoft Exchange Web Services. 3 | 4 | Copyright © 2011 Dan Wanek 5 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); 7 | you may not use this file except in compliance with the License. 8 | You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | =end 18 | 19 | module Viewpoint::EWS::SOAP 20 | 21 | # Exchange Synchronization operations as listed in the EWS Documentation. 22 | # @see http://msdn.microsoft.com/en-us/library/bb409286.aspx 23 | module ExchangeSynchronization 24 | include Viewpoint::EWS::SOAP 25 | 26 | # Defines a request to synchronize a folder hierarchy on a client 27 | # @see http://msdn.microsoft.com/en-us/library/aa580990.aspx 28 | # @param [Hash] opts 29 | # @option opts [Hash] :folder_shape The folder shape properties 30 | # Ex: {:base_shape => 'Default', :additional_properties => 'bla bla bla'} 31 | # @option opts [Hash] :sync_folder_id An optional Hash that represents a FolderId or 32 | # DistinguishedFolderId. 33 | # Ex: {:id => :inbox} 34 | # @option opts [Hash] :sync_state The Base64 sync state id. If this is the 35 | # first time syncing this does not need to be passed. 36 | def sync_folder_hierarchy(opts) 37 | opts = opts.clone 38 | req = build_soap! do |type, builder| 39 | if(type == :header) 40 | else 41 | builder.nbuild.SyncFolderHierarchy { 42 | builder.nbuild.parent.default_namespace = @default_ns 43 | builder.folder_shape!(opts[:folder_shape]) 44 | builder.sync_folder_id!(opts[:sync_folder_id]) if opts[:sync_folder_id] 45 | builder.sync_state!(opts[:sync_state]) if opts[:sync_state] 46 | } 47 | end 48 | end 49 | do_soap_request(req, response_class: EwsResponse) 50 | end 51 | 52 | # Synchronizes items between the Exchange server and the client 53 | # @see http://msdn.microsoft.com/en-us/library/aa563967(v=EXCHG.140).aspx 54 | # @param [Hash] opts 55 | # @option opts [Hash] :item_shape The item shape properties 56 | # Ex: {:base_shape => 'Default', :additional_properties => 'bla bla bla'} 57 | # @option opts [Hash] :sync_folder_id A Hash that represents a FolderId or 58 | # DistinguishedFolderId. [ Ex: {:id => :inbox} ] OPTIONAL 59 | # @option opts [String] :sync_state The Base64 sync state id. If this is the 60 | # first time syncing this does not need to be passed. OPTIONAL on first call 61 | # @option opts [Array ] :ignore An Array of ItemIds for items to ignore 62 | # during the sync process. Ex: [{:id => 'id1', :change_key => 'ck'}, {:id => 'id2'}] 63 | # OPTIONAL 64 | # @option opts [Integer] :max_changes_returned ('required') The amount of items to sync per call. 65 | # @option opts [String] :sync_scope specifies whether just items or items and folder associated 66 | # information are returned. OPTIONAL 67 | # options: 'NormalItems' or 'NormalAndAssociatedItems' 68 | # @example 69 | # { :item_shape => {:base_shape => 'Default'}, 70 | # :sync_folder_id => {:id => :inbox}, 71 | # :sync_state => myBase64id, 72 | # :max_changes_returned => 256 } 73 | def sync_folder_items(opts) 74 | opts = opts.clone 75 | req = build_soap! do |type, builder| 76 | if(type == :header) 77 | else 78 | builder.nbuild.SyncFolderItems { 79 | builder.nbuild.parent.default_namespace = @default_ns 80 | builder.item_shape!(opts[:item_shape]) 81 | builder.sync_folder_id!(opts[:sync_folder_id]) if opts[:sync_folder_id] 82 | builder.sync_state!(opts[:sync_state]) if opts[:sync_state] 83 | builder.ignore!(opts[:ignore]) if opts[:ignore] 84 | builder.max_changes_returned!(opts[:max_changes_returned]) 85 | builder.sync_scope!(opts[:sync_scope]) if opts[:sync_scope] 86 | } 87 | end 88 | end 89 | do_soap_request(req, response_class: EwsResponse) 90 | end 91 | 92 | end #ExchangeSynchronization 93 | end 94 | -------------------------------------------------------------------------------- /lib/ews/soap/exchange_time_zones.rb: -------------------------------------------------------------------------------- 1 | module Viewpoint::EWS::SOAP 2 | 3 | module ExchangeTimeZones 4 | include Viewpoint::EWS::SOAP 5 | 6 | # Request list of server known time zones 7 | # @param full [Boolean] Request full time zone definition? Returns only name and id if false. 8 | # @param ids [Array] Returns only the specified time zones instead of all if present 9 | # @return [Array] Array of Objects responding to #id() and #name() 10 | # @example Retrieving server time zones 11 | # ews_client = Viewpoint::EWSClient.new # ... 12 | # zones = ews_client.ews.get_time_zones 13 | # @todo Implement TimeZoneDefinition with sub elements Periods, TransitionsGroups and Transitions 14 | def get_time_zones(full = false, ids = nil) 15 | req = build_soap! do |type, builder| 16 | unless type == :header 17 | builder.get_server_time_zones!(full: full, ids: ids) 18 | end 19 | end 20 | result = do_soap_request req, response_class: EwsSoapResponse 21 | 22 | if result.success? 23 | zones = [] 24 | result.response_messages.each do |message| 25 | elements = message[:get_server_time_zones_response_message][:elems][:time_zone_definitions][:elems] 26 | elements.each do |definition| 27 | data = { 28 | id: definition[:time_zone_definition][:attribs][:id], 29 | name: definition[:time_zone_definition][:attribs][:name] 30 | } 31 | zones << OpenStruct.new(data) 32 | end 33 | end 34 | zones 35 | else 36 | raise EwsError, "Could not get time zones" 37 | end 38 | end 39 | 40 | # Sets the time zone context header 41 | # @param id [String] Identifier of a Microsoft well known time zone 42 | # @example Set time zone context for connection 43 | # ews_client = Viewpoint::EWSClient.new # ... 44 | # ews_client.set_time_zone 'AUS Central Standard Time' 45 | # # subsequent request will send the TimeZoneContext header 46 | # @see EWSClient#set_time_zone 47 | def set_time_zone_context(id) 48 | if id 49 | @time_zone_context = {id: id} 50 | else 51 | @time_zone_context = nil 52 | end 53 | end 54 | 55 | end 56 | end 57 | -------------------------------------------------------------------------------- /lib/ews/soap/exchange_user_configuration.rb: -------------------------------------------------------------------------------- 1 | module Viewpoint::EWS::SOAP 2 | 3 | # Exchange User Configuration operations as listed in the EWS Documentation. 4 | # @see http://msdn.microsoft.com/en-us/library/bb409286.aspx 5 | module ExchangeUserConfiguration 6 | include Viewpoint::EWS::SOAP 7 | 8 | # The GetUserConfiguration operation gets a user configuration object from 9 | # a folder. 10 | # @see http://msdn.microsoft.com/en-us/library/aa563465.aspx 11 | # @param [Hash] opts 12 | # @option opts [Hash] :user_config_name 13 | # @option opts [String] :user_config_props 14 | def get_user_configuration(opts) 15 | opts = opts.clone 16 | [:user_config_name, :user_config_props].each do |k| 17 | validate_param(opts, k, true) 18 | end 19 | req = build_soap! do |type, builder| 20 | if(type == :header) 21 | else 22 | builder.nbuild.GetUserConfiguration {|x| 23 | x.parent.default_namespace = @default_ns 24 | builder.user_configuration_name!(opts[:user_config_name]) 25 | builder.user_configuration_properties!(opts[:user_config_props]) 26 | } 27 | end 28 | end 29 | do_soap_request(req, response_class: EwsSoapAvailabilityResponse) 30 | end 31 | 32 | end #ExchangeUserConfiguration 33 | end 34 | -------------------------------------------------------------------------------- /lib/ews/soap/parsers/ews_parser.rb: -------------------------------------------------------------------------------- 1 | =begin 2 | This file is part of Viewpoint; the Ruby library for Microsoft Exchange Web Services. 3 | 4 | Copyright © 2011 Dan Wanek 5 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); 7 | you may not use this file except in compliance with the License. 8 | You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | =end 18 | 19 | module Viewpoint::EWS::SOAP 20 | class EwsParser 21 | include Viewpoint::EWS 22 | 23 | # @param [String] soap_resp 24 | def initialize(soap_resp) 25 | @soap_resp = soap_resp 26 | @sax_doc = EwsSaxDocument.new 27 | end 28 | 29 | def parse(opts = {}) 30 | opts[:response_class] ||= EwsSoapResponse 31 | @soap_resp.gsub!(/&#x([0-8bcef]|1[0-9a-f]);/i, '') 32 | sax_parser.parse(@soap_resp) 33 | opts[:response_class].new @sax_doc.struct 34 | end 35 | 36 | private 37 | 38 | def sax_parser 39 | @parser ||= Nokogiri::XML::SAX::Parser.new(@sax_doc) 40 | end 41 | 42 | end # EwsParser 43 | end # Viewpoint 44 | -------------------------------------------------------------------------------- /lib/ews/soap/parsers/ews_sax_document.rb: -------------------------------------------------------------------------------- 1 | =begin 2 | This file is part of Viewpoint; the Ruby library for Microsoft Exchange Web Services. 3 | 4 | Copyright © 2011 Dan Wanek 5 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); 7 | you may not use this file except in compliance with the License. 8 | You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | =end 18 | 19 | module Viewpoint::EWS::SOAP 20 | # Parse the incoming response document via a SAX parser instead of the 21 | # traditional DOM parser. In early benchmarks this was performing about 22 | # 132% faster than the DOM-based parser for large documents. 23 | class EwsSaxDocument < Nokogiri::XML::SAX::Document 24 | include Viewpoint::EWS 25 | include Viewpoint::StringUtils 26 | 27 | attr_reader :struct 28 | 29 | def initialize 30 | @struct = {} 31 | @elems = [] 32 | end 33 | 34 | def characters(string) 35 | # FIXME: Move white space removal to somewhere else. 36 | # This function can be called multiple times. In this case newlines in Text Bodies get stripped. 37 | # See: https://github.com/zenchild/Viewpoint/issues/90 38 | #string.strip! 39 | return if string.empty? 40 | if @elems.last[:text] 41 | @elems.last[:text] += string 42 | else 43 | @elems.last[:text] = string 44 | end 45 | end 46 | 47 | def start_element_namespace(name, attributes = [], prefix = nil, uri = nil, ns = []) 48 | name = ruby_case(name).to_sym 49 | elem = {} 50 | unless attributes.empty? 51 | elem[:attribs] = attributes.collect{|a| 52 | { ruby_case(a.localname).to_sym => a.value} 53 | }.inject(&:merge) 54 | end 55 | @elems << elem 56 | end 57 | 58 | def end_element_namespace name, prefix=nil, uri=nil 59 | name = ruby_case(name).to_sym 60 | elem = @elems.pop 61 | if @elems.empty? 62 | @struct[name] = elem 63 | else 64 | @elems.last[:elems] = [] unless @elems.last[:elems].is_a?(Array) 65 | @elems.last[:elems] << {name => elem} 66 | end 67 | end 68 | 69 | end 70 | end 71 | -------------------------------------------------------------------------------- /lib/ews/soap/response_message.rb: -------------------------------------------------------------------------------- 1 | =begin 2 | This file is part of Viewpoint; the Ruby library for Microsoft Exchange Web Services. 3 | 4 | Copyright © 2011 Dan Wanek 5 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); 7 | you may not use this file except in compliance with the License. 8 | You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | =end 18 | 19 | module Viewpoint::EWS::SOAP 20 | class ResponseMessage 21 | 22 | attr_reader :message, :type 23 | 24 | def initialize(message) 25 | @type = message.keys.first 26 | @message = message[@type] 27 | end 28 | 29 | def response_class 30 | message[:attribs][:response_class] 31 | end 32 | alias :status :response_class 33 | 34 | def success? 35 | response_class == 'Success' 36 | end 37 | 38 | def message_text 39 | safe_hash_access message, [:elems, :message_text, :text] 40 | end 41 | 42 | def response_code 43 | safe_hash_access message, [:elems, :response_code, :text] 44 | end 45 | alias :code :response_code 46 | 47 | def message_xml 48 | safe_hash_access message, [:elems, :message_xml, :text] 49 | end 50 | 51 | def items 52 | safe_hash_access(message, [:elems, :items, :elems]) || [] 53 | end 54 | 55 | 56 | private 57 | 58 | 59 | def safe_hash_access(hsh, keys) 60 | key = keys.shift 61 | return nil unless hsh.is_a?(Hash) && hsh.has_key?(key) 62 | 63 | if keys.empty? 64 | hsh[key] 65 | else 66 | safe_hash_access hsh[key], keys 67 | end 68 | end 69 | 70 | end 71 | end # Viewpoint::EWS::SOAP 72 | 73 | require_relative './responses/create_item_response_message' 74 | require_relative './responses/create_attachment_response_message' 75 | require_relative './responses/find_item_response_message' 76 | require_relative './responses/subscribe_response_message' 77 | require_relative './responses/get_events_response_message' 78 | require_relative './responses/send_notification_response_message' 79 | require_relative './responses/sync_folder_items_response_message' 80 | require_relative './responses/sync_folder_hierarchy_response_message' 81 | -------------------------------------------------------------------------------- /lib/ews/soap/responses/create_attachment_response_message.rb: -------------------------------------------------------------------------------- 1 | =begin 2 | This file is part of Viewpoint; the Ruby library for Microsoft Exchange Web Services. 3 | 4 | Copyright © 2011 Dan Wanek 5 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); 7 | you may not use this file except in compliance with the License. 8 | You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | =end 18 | 19 | module Viewpoint::EWS::SOAP 20 | 21 | class CreateAttachmentResponseMessage < ResponseMessage 22 | include Viewpoint::StringUtils 23 | 24 | def attachments 25 | return @attachments if @attachments 26 | 27 | a = safe_hash_access message, [:elems, :attachments, :elems] 28 | @attachments = a.nil? ? nil : parse_attachments(a) 29 | end 30 | 31 | 32 | private 33 | 34 | 35 | def parse_attachments(att) 36 | att.collect do |a| 37 | type = a.keys.first 38 | klass = Viewpoint::EWS::Types.const_get(camel_case(type)) 39 | item = OpenStruct.new 40 | item.ews = nil 41 | klass.new(item, a[type]) 42 | end 43 | end 44 | 45 | end # CreateAttachmentResponseMessage 46 | 47 | end # Viewpoint::EWS::SOAP 48 | -------------------------------------------------------------------------------- /lib/ews/soap/responses/create_item_response_message.rb: -------------------------------------------------------------------------------- 1 | =begin 2 | This file is part of Viewpoint; the Ruby library for Microsoft Exchange Web Services. 3 | 4 | Copyright © 2011 Dan Wanek 5 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); 7 | you may not use this file except in compliance with the License. 8 | You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | =end 18 | 19 | module Viewpoint::EWS::SOAP 20 | 21 | class CreateItemResponseMessage < ResponseMessage 22 | 23 | end # CreateItemResponseMessage 24 | 25 | end # Viewpoint::EWS::SOAP 26 | -------------------------------------------------------------------------------- /lib/ews/soap/responses/find_item_response_message.rb: -------------------------------------------------------------------------------- 1 | =begin 2 | This file is part of Viewpoint; the Ruby library for Microsoft Exchange Web Services. 3 | 4 | Copyright © 2011 Dan Wanek 5 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); 7 | you may not use this file except in compliance with the License. 8 | You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | =end 18 | 19 | module Viewpoint::EWS::SOAP 20 | 21 | class RootFolder 22 | 23 | attr_reader :root 24 | 25 | def initialize(root) 26 | @root = root 27 | end 28 | 29 | def indexed_paging_offset 30 | attrib :index_paging_offset 31 | end 32 | 33 | def numerator_offset 34 | attrib :numerator_offset 35 | end 36 | 37 | def absolute_denominator 38 | attrib :absolute_denominator 39 | end 40 | 41 | def includes_last_item_in_range 42 | attrib :includes_last_item_in_range 43 | end 44 | 45 | def total_items_in_view 46 | attrib :total_items_in_view 47 | end 48 | 49 | def items 50 | root[:elems][0][:items][:elems] || [] 51 | end 52 | 53 | def groups 54 | root[:elems][0][:groups][:elems] 55 | end 56 | 57 | 58 | private 59 | 60 | 61 | def attrib(key) 62 | return nil unless root.has_key?(:attribs) 63 | root[:attribs][key] 64 | end 65 | 66 | end 67 | 68 | 69 | class FindItemResponseMessage < ResponseMessage 70 | 71 | def root_folder 72 | return @root_folder if @root_folder 73 | 74 | rf = safe_hash_access message, [:elems, :root_folder] 75 | @root_folder = rf.nil? ? nil : RootFolder.new(rf) 76 | end 77 | 78 | end # FindItemResponseMessage 79 | 80 | end # Viewpoint::EWS::SOAP 81 | -------------------------------------------------------------------------------- /lib/ews/soap/responses/get_events_response_message.rb: -------------------------------------------------------------------------------- 1 | =begin 2 | This file is part of Viewpoint; the Ruby library for Microsoft Exchange Web Services. 3 | 4 | Copyright © 2011 Dan Wanek 5 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); 7 | you may not use this file except in compliance with the License. 8 | You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | =end 18 | 19 | module Viewpoint::EWS::SOAP 20 | class GetEventsResponseMessage < ResponseMessage 21 | 22 | def notification 23 | safe_hash_access message, [:elems, :notification, :elems] 24 | end 25 | 26 | def subscription_id 27 | safe_hash_access notification[0], [:subscription_id, :text] 28 | end 29 | 30 | def previous_watermark 31 | safe_hash_access notification[1], [:previous_watermark, :text] 32 | end 33 | 34 | def new_watermark 35 | ev = notification.last 36 | if ev 37 | type = ev.keys.first 38 | ev[type][:elems][0][:watermark][:text] 39 | else 40 | nil 41 | end 42 | end 43 | 44 | def more_events? 45 | safe_hash_access(notification[2], [:more_events, :text]) == 'true' 46 | end 47 | 48 | def events 49 | notification[3..-1] 50 | end 51 | 52 | end # GetEventsResponseMessage 53 | end # Viewpoint::EWS::SOAP 54 | -------------------------------------------------------------------------------- /lib/ews/soap/responses/send_notification_response_message.rb: -------------------------------------------------------------------------------- 1 | =begin 2 | This file is part of Viewpoint; the Ruby library for Microsoft Exchange Web Services. 3 | 4 | Copyright © 2011 Dan Wanek 5 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); 7 | you may not use this file except in compliance with the License. 8 | You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | =end 18 | 19 | module Viewpoint::EWS::SOAP 20 | class SendNotificationResponseMessage < ResponseMessage 21 | include Viewpoint::StringUtils 22 | 23 | def notification 24 | safe_hash_access message, [:elems, :notification, :elems] 25 | end 26 | 27 | def subscription_id 28 | safe_hash_access notification[0], [:subscription_id, :text] 29 | end 30 | 31 | def previous_watermark 32 | safe_hash_access notification[1], [:previous_watermark, :text] 33 | end 34 | 35 | def new_watermark 36 | ev = notification.last 37 | if ev 38 | type = ev.keys.first 39 | ev[type][:elems][0][:watermark][:text] 40 | else 41 | nil 42 | end 43 | end 44 | 45 | def more_events? 46 | safe_hash_access(notification[2], [:more_events, :text]) == 'true' 47 | end 48 | 49 | def events 50 | @events ||= 51 | notification[3..-1].collect do |ev| 52 | type = ev.keys.first 53 | klass = Viewpoint::EWS::Types.const_get(camel_case(type)) 54 | klass.new(nil, ev[type]) 55 | end 56 | end 57 | 58 | end # SendNotificationResponseMessage 59 | end # Viewpoint::EWS::SOAP 60 | -------------------------------------------------------------------------------- /lib/ews/soap/responses/subscribe_response_message.rb: -------------------------------------------------------------------------------- 1 | =begin 2 | This file is part of Viewpoint; the Ruby library for Microsoft Exchange Web Services. 3 | 4 | Copyright © 2011 Dan Wanek 5 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); 7 | you may not use this file except in compliance with the License. 8 | You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | =end 18 | 19 | module Viewpoint::EWS::SOAP 20 | class SubscribeResponseMessage < ResponseMessage 21 | 22 | def subscription 23 | safe_hash_access message, [:elems] 24 | end 25 | 26 | def subscription_id 27 | safe_hash_access subscription, [:subscription_id, :text] 28 | end 29 | 30 | def watermark 31 | safe_hash_access subscription, [:watermark, :text] 32 | end 33 | 34 | end # SubscribeResponseMessage 35 | end # Viewpoint::EWS::SOAP 36 | -------------------------------------------------------------------------------- /lib/ews/soap/responses/sync_folder_hierarchy_response_message.rb: -------------------------------------------------------------------------------- 1 | =begin 2 | This file is part of Viewpoint; the Ruby library for Microsoft Exchange Web Services. 3 | 4 | Copyright © 2011 Dan Wanek 5 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); 7 | you may not use this file except in compliance with the License. 8 | You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | =end 18 | 19 | module Viewpoint::EWS::SOAP 20 | class SyncFolderHierarchyResponseMessage < ResponseMessage 21 | 22 | def sync_state 23 | safe_hash_access message, [:elems, :sync_state, :text] 24 | end 25 | 26 | def includes_last_folder_in_range? 27 | ans = safe_hash_access message, [:elems, :includes_last_folder_in_range, :text] 28 | ans.downcase == 'true' 29 | end 30 | 31 | def changes 32 | safe_hash_access(message, [:elems, :changes, :elems]) || [] 33 | end 34 | 35 | end # SyncFolderHierarchyResponseMessage 36 | end # Viewpoint::EWS::SOAP 37 | -------------------------------------------------------------------------------- /lib/ews/soap/responses/sync_folder_items_response_message.rb: -------------------------------------------------------------------------------- 1 | =begin 2 | This file is part of Viewpoint; the Ruby library for Microsoft Exchange Web Services. 3 | 4 | Copyright © 2011 Dan Wanek 5 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); 7 | you may not use this file except in compliance with the License. 8 | You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | =end 18 | 19 | module Viewpoint::EWS::SOAP 20 | class SyncFolderItemsResponseMessage < ResponseMessage 21 | 22 | def sync_state 23 | safe_hash_access message, [:elems, :sync_state, :text] 24 | end 25 | 26 | def includes_last_item_in_range? 27 | ans = safe_hash_access message, [:elems, :includes_last_item_in_range, :text] 28 | ans.downcase == 'true' 29 | end 30 | 31 | def changes 32 | safe_hash_access(message, [:elems, :changes, :elems]) || [] 33 | end 34 | 35 | end # SyncFolderItemsResponseMessage 36 | end # Viewpoint::EWS::SOAP 37 | -------------------------------------------------------------------------------- /lib/ews/templates/calendar_item.rb: -------------------------------------------------------------------------------- 1 | module Viewpoint::EWS 2 | module Template 3 | # Template for creating CalendarItems 4 | # @see http://msdn.microsoft.com/en-us/library/exchange/aa564765.aspx 5 | class CalendarItem < OpenStruct 6 | 7 | # Available parameters with the required ordering 8 | PARAMETERS = %w{mime_content item_id parent_folder_id item_class subject sensitivity body attachments 9 | date_time_received size categories in_reply_to is_submitted is_draft is_from_me is_resend is_unmodified 10 | internet_message_headers date_time_sent date_time_created response_objects reminder_due_by reminder_is_set 11 | reminder_minutes_before_start display_cc display_to has_attachments extended_property culture start end 12 | original_start is_all_day_event legacy_free_busy_status location when is_meeting is_cancelled is_recurring 13 | meeting_request_was_sent is_response_requested calendar_item_type my_response_type organizer 14 | required_attendees optional_attendees resources conflicting_meeting_count adjacent_meeting_count 15 | conflicting_meetings adjacent_meetings duration time_zone appointment_reply_time appointment_sequence_number 16 | appointment_state recurrence first_occurrence last_occurrence modified_occurrences deleted_occurrences 17 | meeting_time_zone start_time_zone end_time_zone conference_type allow_new_time_proposal is_online_meeting 18 | meeting_workspace_url net_show_url effective_rights last_modified_name last_modified_time is_associated 19 | web_client_read_form_query_string web_client_edit_form_query_string conversation_id unique_body 20 | }.map(&:to_sym).freeze 21 | 22 | # Returns a new CalendarItem template 23 | def initialize(opts = {}) 24 | super opts.dup 25 | end 26 | 27 | # EWS CreateItem container 28 | # @return [Hash] 29 | def to_ews_create(opts = {}) 30 | structure = {} 31 | structure[:message_disposition] = (draft ? 'SaveOnly' : 'SendAndSaveCopy') 32 | # options 33 | structure[:send_meeting_invitations] = (opts.has_key?(:send_meeting_invitations) ? opts[:send_meeting_invitations] : 'SendToNone') 34 | 35 | if self.saved_item_folder_id 36 | if self.saved_item_folder_id.kind_of?(Hash) 37 | structure[:saved_item_folder_id] = saved_item_folder_id 38 | else 39 | structure[:saved_item_folder_id] = {id: saved_item_folder_id} 40 | end 41 | end 42 | 43 | structure[:items] = [{calendar_item: to_ews_item}] 44 | structure 45 | end 46 | 47 | # EWS Item hash 48 | # 49 | # Puts all known parameters in the required ordering and structure 50 | # @return [Hash] 51 | def to_ews_item 52 | item_parameters = {} 53 | PARAMETERS.each do |key| 54 | if !(value = self.send(key)).nil? 55 | 56 | # Convert non duplicable values to String 57 | case value 58 | when NilClass, FalseClass, TrueClass, Symbol, Numeric 59 | value = value.to_s 60 | end 61 | 62 | # Convert attributes 63 | case key 64 | when :start, :end 65 | item_parameters[key] = {text: value.respond_to?(:iso8601) ? value.iso8601 : value} 66 | when :body 67 | item_parameters[key] = {body_type: self.body_type || 'Text', text: value.to_s} 68 | else 69 | item_parameters[key] = value 70 | end 71 | end 72 | end 73 | 74 | item_parameters 75 | end 76 | 77 | end 78 | end 79 | end 80 | -------------------------------------------------------------------------------- /lib/ews/templates/forward_item.rb: -------------------------------------------------------------------------------- 1 | module Viewpoint::EWS 2 | module Template 3 | class ForwardItem < Message 4 | 5 | # Format this object for EWS backend consumption. 6 | def to_ews 7 | ews_opts, msg = to_ews_basic 8 | msg[:reference_item_id] = reference_item_id 9 | msg[:new_body_content] = {text: new_body_content, body_type: new_body_type} 10 | ews_opts.merge({items: [{forward_item: msg}]}) 11 | end 12 | 13 | private 14 | 15 | 16 | def init_defaults! 17 | super 18 | self.new_body_content ||= '' 19 | self.new_body_type ||= 'Text' 20 | end 21 | 22 | end 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /lib/ews/templates/message.rb: -------------------------------------------------------------------------------- 1 | module Viewpoint::EWS 2 | module Template 3 | class Message < OpenStruct 4 | 5 | def initialize(opts = {}) 6 | super opts.clone 7 | init_defaults! 8 | end 9 | 10 | # Format this object for EWS backend consumption. 11 | def to_ews 12 | ews_opts, msg = to_ews_basic 13 | ews_opts.merge({items: [{message: msg}]}) 14 | end 15 | 16 | def has_attachments? 17 | !(file_attachments.empty? && item_attachments.empty? && inline_attachments.empty?) 18 | end 19 | 20 | 21 | private 22 | 23 | 24 | def init_defaults! 25 | self.subject ||= nil 26 | self.body ||= nil 27 | self.body_type ||= 'Text' 28 | self.importance ||= 'Normal' 29 | self.draft ||= false 30 | self.is_read = true if is_read.nil? 31 | self.to_recipients ||= [] 32 | self.cc_recipients ||= [] 33 | self.bcc_recipients ||= [] 34 | self.file_attachments ||= [] 35 | self.item_attachments ||= [] 36 | self.inline_attachments ||= [] 37 | self.extended_properties ||= [] 38 | end 39 | 40 | def to_ews_basic 41 | ews_opts = {} 42 | ews_opts[:message_disposition] = (draft ? 'SaveOnly' : 'SendAndSaveCopy') 43 | 44 | if saved_item_folder_id 45 | if saved_item_folder_id.kind_of?(Hash) 46 | ews_opts[:saved_item_folder_id] = saved_item_folder_id 47 | else 48 | ews_opts[:saved_item_folder_id] = {id: saved_item_folder_id} 49 | end 50 | end 51 | 52 | msg = {} 53 | msg[:subject] = subject if subject 54 | msg[:body] = {text: body, body_type: body_type} if body 55 | 56 | msg[:importance] = importance if importance 57 | 58 | to_r = to_recipients.collect{|r| {mailbox: {email_address: r}}} 59 | msg[:to_recipients] = to_r unless to_r.empty? 60 | 61 | cc_r = cc_recipients.collect{|r| {mailbox: {email_address: r}}} 62 | msg[:cc_recipients] = cc_r unless cc_r.empty? 63 | 64 | bcc_r = bcc_recipients.collect{|r| {mailbox: {email_address: r}}} 65 | msg[:bcc_recipients] = bcc_r unless bcc_r.empty? 66 | 67 | msg[:is_read] = is_read 68 | 69 | msg[:extended_properties] = extended_properties unless extended_properties.empty? 70 | 71 | [ews_opts, msg] 72 | end 73 | 74 | end 75 | end 76 | end 77 | -------------------------------------------------------------------------------- /lib/ews/templates/reply_to_item.rb: -------------------------------------------------------------------------------- 1 | module Viewpoint::EWS 2 | module Template 3 | class ReplyToItem < Message 4 | 5 | # Format this object for EWS backend consumption. 6 | def to_ews 7 | ews_opts, msg = to_ews_basic 8 | msg[:reference_item_id] = reference_item_id 9 | msg[:new_body_content] = {text: new_body_content, body_type: new_body_type} 10 | ews_opts.merge({items: [{ews_type => msg}]}) 11 | end 12 | 13 | private 14 | 15 | 16 | def init_defaults! 17 | super 18 | self.new_body_content ||= '' 19 | self.new_body_type ||= 'Text' 20 | self.ews_type = :reply_to_item 21 | end 22 | 23 | end 24 | end 25 | end 26 | -------------------------------------------------------------------------------- /lib/ews/templates/task.rb: -------------------------------------------------------------------------------- 1 | module Viewpoint::EWS 2 | module Template 3 | # Template for creating Tasks 4 | # @see http://msdn.microsoft.com/en-us/library/exchange/aa564765.aspx 5 | class Task < OpenStruct 6 | 7 | # Available parameters with the required ordering 8 | PARAMETERS = %w{mime_content item_id parent_folder_id item_class subject sensitivity body attachments 9 | date_time_received size categories in_reply_to is_submitted is_draft is_from_me is_resend 10 | is_unmodified internet_message_headers date_time_sent date_time_created response_objects 11 | reminder_due_by reminder_is_set reminder_minutes_before_start display_cc display_to 12 | has_attachments extended_property culture actual_work assigned_time billing_information 13 | change_count companies complete_date contacts delegation_state delegator due_date 14 | is_assignment_editable is_complete is_recurring is_team_task mileage owner percent_complete 15 | recurrence start_date status status_description total_work effective_rights last_modified_name 16 | last_modified_time is_associated web_client_read_form_query_string 17 | web_client_edit_form_query_string conversation_id unique_body 18 | }.map(&:to_sym).freeze 19 | 20 | # Returns a new Task template 21 | def initialize(opts = {}) 22 | super opts.dup 23 | end 24 | 25 | # EWS CreateItem container 26 | # @return [Hash] 27 | def to_ews_create 28 | structure = {} 29 | 30 | if self.saved_item_folder_id 31 | if self.saved_item_folder_id.kind_of?(Hash) 32 | structure[:saved_item_folder_id] = saved_item_folder_id 33 | else 34 | structure[:saved_item_folder_id] = {id: saved_item_folder_id} 35 | end 36 | end 37 | 38 | structure[:items] = [{task: to_ews_item}] 39 | structure 40 | end 41 | 42 | # EWS Item hash 43 | # 44 | # Puts all known parameters in the required ordering and structure 45 | # @return [Hash] 46 | def to_ews_item 47 | item_parameters = {} 48 | PARAMETERS.each do |key| 49 | if !(value = self.send(key)).nil? 50 | 51 | # Convert non duplicable values to String 52 | case value 53 | when NilClass, FalseClass, TrueClass, Symbol, Numeric 54 | value = value.to_s 55 | end 56 | 57 | # Convert attributes 58 | case key 59 | when :start_date, :due_date 60 | item_parameters[key] = {text: value.respond_to?(:iso8601) ? value.iso8601 : value} 61 | when :body 62 | item_parameters[key] = {body_type: self.body_type || 'Text', text: value.to_s} 63 | else 64 | item_parameters[key] = value 65 | end 66 | end 67 | end 68 | 69 | item_parameters 70 | end 71 | 72 | end 73 | end 74 | end 75 | -------------------------------------------------------------------------------- /lib/ews/types.rb: -------------------------------------------------------------------------------- 1 | module Viewpoint::EWS 2 | module Types 3 | include Viewpoint::StringUtils 4 | 5 | KEY_PATHS = { 6 | extended_properties: [:extended_property], 7 | } 8 | KEY_TYPES = { 9 | extended_properties: :build_extended_properties, 10 | } 11 | KEY_ALIAS = {} 12 | 13 | attr_reader :ews_item 14 | 15 | # @param [SOAP::ExchangeWebService] ews the EWS reference 16 | # @param [Hash] ews_item the EWS parsed response document 17 | def initialize(ews, ews_item) 18 | @ews = ews 19 | @ews_item = ews_item 20 | @shallow = true 21 | @frozen = false 22 | end 23 | 24 | def method_missing(method_sym, *arguments, &block) 25 | if method_keys.include?(method_sym) 26 | type_convert( method_sym, resolve_method(method_sym) ) 27 | else 28 | super 29 | end 30 | end 31 | 32 | def to_s 33 | "#{self.class.name}: EWS METHODS: #{self.ews_methods.sort.join(', ')}" 34 | end 35 | 36 | def frozen? 37 | @frozen 38 | end 39 | 40 | # @param ronly [Boolean] true to freeze 41 | def freeze! 42 | @frozen = true 43 | end 44 | 45 | def unfreeze! 46 | @frozen = false 47 | end 48 | 49 | def shallow? 50 | @shallow 51 | end 52 | 53 | def mark_deep! 54 | @shallow = false 55 | end 56 | 57 | def auto_deepen? 58 | ews.auto_deepen 59 | end 60 | 61 | def deepen! 62 | if shallow? 63 | self.get_all_properties! 64 | @shallow = false 65 | true 66 | end 67 | end 68 | alias_method :enlighten!, :deepen! 69 | 70 | # @see http://www.ruby-doc.org/core/classes/Object.html#M000333 71 | def respond_to?(method_sym, include_private = false) 72 | if method_keys.include?(method_sym) 73 | true 74 | else 75 | super 76 | end 77 | end 78 | 79 | def methods(include_super = true) 80 | super + ews_methods 81 | end 82 | 83 | def ews_methods 84 | key_paths.keys + key_alias.keys 85 | end 86 | 87 | protected # things like OutOfOffice need protected level access 88 | 89 | def ews 90 | @ews 91 | end 92 | 93 | private 94 | 95 | def key_paths 96 | KEY_PATHS 97 | end 98 | 99 | def key_types 100 | KEY_TYPES 101 | end 102 | 103 | def key_alias 104 | KEY_ALIAS 105 | end 106 | 107 | def class_by_name(cname) 108 | if(cname.instance_of? Symbol) 109 | cname = camel_case(cname) 110 | end 111 | Viewpoint::EWS::Types.const_get(cname) 112 | end 113 | 114 | def type_convert(key,str) 115 | begin 116 | key = key_alias[key] || key 117 | if key_types[key] 118 | key_types[key].is_a?(Symbol) ? method(key_types[key]).call(str) : key_types[key].call(str) 119 | else 120 | str 121 | end 122 | rescue 123 | nil 124 | end 125 | end 126 | 127 | def resolve_method(method_sym) 128 | begin 129 | resolve_key_path(@ews_item, method_path(method_sym)) 130 | rescue 131 | if shallow? 132 | if frozen? 133 | raise EwsFrozenObjectError, "Could not resolve :#{method_sym} on frozen object." 134 | elsif auto_deepen? 135 | enlighten! 136 | retry 137 | else 138 | if !auto_deepen? 139 | if ews.no_auto_deepen_behavior == :raise 140 | raise EwsMinimalObjectError, "Could not resolve :#{method_sym}. #auto_deepen set to false" 141 | else 142 | nil 143 | end 144 | else 145 | end 146 | end 147 | else 148 | nil 149 | end 150 | end 151 | end 152 | 153 | def resolve_key_path(hsh, path) 154 | k = path.first 155 | return hsh[k] if path.length == 1 156 | resolve_key_path(hsh[k],path[1..-1]) 157 | end 158 | 159 | def method_keys 160 | key_paths.keys + key_alias.keys 161 | end 162 | 163 | # Resolve the method path with or without an alias 164 | def method_path(sym) 165 | key_paths[key_alias[sym] || sym] 166 | end 167 | 168 | def build_extended_properties(eprops) 169 | h = {} 170 | # todo 171 | # the return pattern seems broken in some cases, 172 | # probably needs fixing via a dedicated response parser 173 | eprops.each do |e| 174 | if e.size == 1 175 | e[:elems].each_cons(2) do |k,v| 176 | key = k[:extended_field_u_r_i][:attribs][:property_name].downcase.to_sym 177 | val = v[:value][:text] 178 | h.store(key,val) 179 | end 180 | elsif e.size == 2 181 | e[1].each_cons(2) do |k,v| 182 | key = k[:extended_field_u_r_i][:attribs][:property_name].downcase.to_sym 183 | val = v[:value][:text] 184 | h.store(key,val) 185 | end 186 | else 187 | raise EwsMinimalObjectError, "Not prepared to deal with elements greater than 2" 188 | end 189 | end 190 | h 191 | end 192 | 193 | end 194 | end 195 | -------------------------------------------------------------------------------- /lib/ews/types/attachment.rb: -------------------------------------------------------------------------------- 1 | =begin 2 | This file is part of Viewpoint; the Ruby library for Microsoft Exchange Web Services. 3 | 4 | Copyright © 2011 Dan Wanek 5 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); 7 | you may not use this file except in compliance with the License. 8 | You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | =end 18 | 19 | module Viewpoint::EWS::Types 20 | # A generic Attachment. This class should not be instantiated directly. You 21 | # should use one of the subclasses like FileAttachment or ItemAttachment. 22 | class Attachment 23 | include Viewpoint::EWS 24 | include Viewpoint::EWS::Types 25 | include Viewpoint::EWS::Types::Item 26 | 27 | ATTACH_KEY_PATHS = { 28 | :id => [:attachment_id, :attribs, :id], 29 | :parent_item_id => [:attachment_id, :attribs, :root_item_id], 30 | :parent_change_key => [:attachment_id, :attribs, :root_item_change_key], 31 | :name => [:name, :text], 32 | :content_type => [:content_type, :text], 33 | :content_id => [:content_id], 34 | :size => [:size, :text], 35 | :last_modified_time => [:last_modified_time, :text], 36 | :is_inline? => [:is_inline, :text], 37 | } 38 | 39 | ATTACH_KEY_TYPES = { 40 | is_inline?: ->(str){str.downcase == 'true'}, 41 | last_modified_type: ->(str){DateTime.parse(str)}, 42 | size: ->(str){str.to_i}, 43 | content_id: :fix_content_id, 44 | } 45 | 46 | ATTACH_KEY_ALIAS = { } 47 | 48 | # @param [Hash] attachment The attachment ews_item 49 | def initialize(item, attachment) 50 | @item = item 51 | super(item.ews, attachment) 52 | end 53 | 54 | 55 | private 56 | 57 | 58 | def key_paths 59 | @key_paths ||= ATTACH_KEY_PATHS 60 | end 61 | 62 | def key_types 63 | @key_types ||= ATTACH_KEY_TYPES 64 | end 65 | 66 | def key_alias 67 | @key_alias ||= ATTACH_KEY_ALIAS 68 | end 69 | 70 | # Sometimes the SOAP response comes back with two identical content_ids. 71 | # This method fishes them out no matter which way them come. 72 | def fix_content_id(content_id) 73 | content_id.is_a?(Array) ? content_id.last[:text] : content_id[:text] 74 | end 75 | 76 | end 77 | end 78 | -------------------------------------------------------------------------------- /lib/ews/types/attendee.rb: -------------------------------------------------------------------------------- 1 | =begin 2 | This file is part of Viewpoint; the Ruby library for Microsoft Exchange Web Services. 3 | 4 | Copyright © 2011 Dan Wanek 5 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); 7 | you may not use this file except in compliance with the License. 8 | You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | =end 18 | 19 | module Viewpoint::EWS::Types 20 | 21 | # This represents a Mailbox object in the Exchange data store 22 | # @see http://msdn.microsoft.com/en-us/library/aa565036.aspx MSDN docs 23 | # @todo Design a Class method that resolves to an Array of MailboxUsers 24 | class Attendee < MailboxUser 25 | end # Attendee 26 | 27 | end # Viewpoint::EWS::Types 28 | -------------------------------------------------------------------------------- /lib/ews/types/calendar_folder.rb: -------------------------------------------------------------------------------- 1 | module Viewpoint::EWS::Types 2 | class CalendarFolder 3 | include Viewpoint::EWS 4 | include Viewpoint::EWS::Types 5 | include Viewpoint::EWS::Types::GenericFolder 6 | 7 | # Fetch items between a given time period 8 | # @param [DateTime] start_date the time to start fetching Items from 9 | # @param [DateTime] end_date the time to stop fetching Items from 10 | def items_between(start_date, end_date, opts={}) 11 | items do |obj| 12 | obj.restriction = { :and => 13 | [ 14 | {:is_greater_than_or_equal_to => 15 | [ 16 | {:field_uRI => {:field_uRI=>'calendar:Start'}}, 17 | {:field_uRI_or_constant=>{:constant => {:value =>start_date}}} 18 | ] 19 | }, 20 | {:is_less_than_or_equal_to => 21 | [ 22 | {:field_uRI => {:field_uRI=>'calendar:End'}}, 23 | {:field_uRI_or_constant=>{:constant => {:value =>end_date}}} 24 | ] 25 | } 26 | ] 27 | } 28 | end 29 | end 30 | 31 | # Fetch items between a given time period using a calendar view. 32 | # The calendar view will include occurences of recurring calendar items 33 | # next to the regular single calendar items. 34 | # @param [DateTime] start_date the time to start fetching Items from 35 | # @param [DateTime] end_date the time to stop fetching Items from 36 | # @param opts [Hash] 37 | # @option opts :max_entries_returned [Integer] the maximum number of entries to return 38 | def items_between_calendar_view(start_date, end_date, opts={}) 39 | view_opts = {:start_date => start_date, :end_date => end_date} 40 | view_opts[:max_entries_returned] = opts.delete(:max_entries_returned) if opts[:max_entries_returned] 41 | items(opts.merge(:calendar_view => view_opts)) 42 | end 43 | 44 | # Creates a new appointment 45 | # @param attributes [Hash] Parameters of the calendar item. Some example attributes are listed below. 46 | # @option attributes :subject [String] 47 | # @option attributes :start [Time] 48 | # @option attributes :end [Time] 49 | # @return [CalendarItem] 50 | # @see Template::CalendarItem 51 | def create_item(attributes, to_ews_create_opts = {}) 52 | template = Viewpoint::EWS::Template::CalendarItem.new attributes 53 | template.saved_item_folder_id = {id: self.id, change_key: self.change_key} 54 | rm = ews.create_item(template.to_ews_create(to_ews_create_opts)).response_messages.first 55 | if rm && rm.success? 56 | CalendarItem.new ews, rm.items.first[:calendar_item][:elems].first 57 | else 58 | if rm 59 | raise EwsCreateItemError, "Could not create item in folder. #{rm.code}: #{rm.message_text}" 60 | else 61 | raise EwsCreateItemError, "Could not create item in folder." 62 | end 63 | end 64 | end 65 | 66 | end 67 | end 68 | -------------------------------------------------------------------------------- /lib/ews/types/calendar_item.rb: -------------------------------------------------------------------------------- 1 | module Viewpoint::EWS::Types 2 | class CalendarItem 3 | include Viewpoint::EWS 4 | include Viewpoint::EWS::Types 5 | include Viewpoint::EWS::Types::Item 6 | include Viewpoint::StringUtils 7 | 8 | CALENDAR_ITEM_KEY_PATHS = { 9 | recurring?: [:is_recurring, :text], 10 | meeting?: [:is_meeting, :text], 11 | cancelled?: [:is_cancelled, :text], 12 | duration: [:duration, :text], 13 | time_zone: [:time_zone, :text], 14 | start: [:start, :text], 15 | end: [:end, :text], 16 | location: [:location, :text], 17 | all_day?: [:is_all_day_event, :text], 18 | legacy_free_busy_status: [:legacy_free_busy_status, :text], 19 | my_response_type: [:my_response_type, :text], 20 | organizer: [:organizer, :elems, 0, :mailbox, :elems], 21 | optional_attendees: [:optional_attendees, :elems ], 22 | required_attendees: [:required_attendees, :elems ], 23 | recurrence: [:recurrence, :elems ], 24 | deleted_occurrences: [:deleted_occurrences, :elems ], 25 | modified_occurrences: [:modified_occurrences, :elems ] 26 | } 27 | 28 | CALENDAR_ITEM_KEY_TYPES = { 29 | start: ->(str){DateTime.parse(str)}, 30 | end: ->(str){DateTime.parse(str)}, 31 | recurring?: ->(str){str.downcase == 'true'}, 32 | meeting?: ->(str){str.downcase == 'true'}, 33 | cancelled?: ->(str){str.downcase == 'true'}, 34 | all_day?: ->(str){str.downcase == 'true'}, 35 | organizer: :build_mailbox_user, 36 | optional_attendees: :build_attendees_users, 37 | required_attendees: :build_attendees_users, 38 | deleted_occurrences: :build_deleted_occurrences, 39 | modified_occurrences: :build_modified_occurrences 40 | } 41 | CALENDAR_ITEM_KEY_ALIAS = {} 42 | 43 | # Delete this calendar item 44 | # @param deltype [Symbol] The delete type; must be :hard, :soft, or :recycle. 45 | # By default EWS will do a hard delete of this calendar item. See the= 46 | # MSDN docs for more info: http://msdn.microsoft.com/en-us/library/aa562961.aspx 47 | # @param cancel_type [String] 'SendToNone'/'SendOnlyToAll'/'SendToAllAndSaveCopy' 48 | # Default is 'SendOnlyToAll' 49 | # @return [Boolean] Whether or not the calendar item was deleted 50 | def delete!(deltype = :hard, cancel_type = 'SendOnlyToAll', opts = {}) 51 | opts = opts.merge(:send_meeting_cancellations => cancel_type) 52 | super(deltype, opts) 53 | end 54 | 55 | # Updates the specified item attributes 56 | # 57 | # Uses `SetItemField` if value is present and `DeleteItemField` if value is nil 58 | # @param updates [Hash] with (:attribute => value) 59 | # @param options [Hash] 60 | # @option options :conflict_resolution [String] one of 'NeverOverwrite', 'AutoResolve' (default) or 'AlwaysOverwrite' 61 | # @option options :send_meeting_invitations_or_cancellations [String] one of 'SendToNone' (default), 'SendOnlyToAll', 62 | # 'SendOnlyToChanged', 'SendToAllAndSaveCopy' or 'SendToChangedAndSaveCopy' 63 | # @return [CalendarItem, false] 64 | # @example Update Subject and Body 65 | # item = #... 66 | # item.update_item!(subject: 'New subject', body: 'New Body') 67 | # @see http://msdn.microsoft.com/en-us/library/exchange/aa580254.aspx 68 | # @todo AppendToItemField updates not implemented 69 | def update_item!(updates, options = {}) 70 | item_updates = [] 71 | updates.each do |attribute, value| 72 | item_field = FIELD_URIS[attribute][:text] if FIELD_URIS.include? attribute 73 | field = {field_uRI: {field_uRI: item_field}} 74 | 75 | if value.nil? && item_field 76 | # Build DeleteItemField Change 77 | item_updates << {delete_item_field: field} 78 | elsif item_field 79 | # Build SetItemField Change 80 | item = Viewpoint::EWS::Template::CalendarItem.new(attribute => value) 81 | 82 | # Remap attributes because ews_builder #dispatch_field_item! uses #build_xml! 83 | item_attributes = item.to_ews_item.map do |name, value| 84 | if value.is_a? String 85 | {name => {text: value}} 86 | elsif value.is_a? Hash 87 | node = {name => {}} 88 | value.each do |attrib_key, attrib_value| 89 | attrib_key = camel_case(attrib_key) unless attrib_key == :text 90 | node[name][attrib_key] = attrib_value 91 | end 92 | node 93 | else 94 | {name => value} 95 | end 96 | end 97 | 98 | item_updates << {set_item_field: field.merge(calendar_item: {sub_elements: item_attributes})} 99 | else 100 | # Ignore unknown attribute 101 | end 102 | end 103 | 104 | if item_updates.any? 105 | data = {} 106 | data[:conflict_resolution] = options[:conflict_resolution] || 'AutoResolve' 107 | data[:send_meeting_invitations_or_cancellations] = options[:send_meeting_invitations_or_cancellations] || 'SendToNone' 108 | data[:item_changes] = [{item_id: self.item_id, updates: item_updates}] 109 | rm = ews.update_item(data).response_messages.first 110 | if rm && rm.success? 111 | self.get_all_properties! 112 | self 113 | else 114 | if rm 115 | raise EwsCreateItemError, "Could not update calendar item. #{rm.code}: #{rm.message_text}" 116 | else 117 | raise EwsCreateItemError, "Could not update calendar item." 118 | end 119 | end 120 | end 121 | 122 | end 123 | 124 | def duration_in_seconds 125 | iso8601_duration_to_seconds(duration) 126 | end 127 | 128 | 129 | private 130 | 131 | 132 | def key_paths 133 | super.merge(CALENDAR_ITEM_KEY_PATHS) 134 | end 135 | 136 | def key_types 137 | super.merge(CALENDAR_ITEM_KEY_TYPES) 138 | end 139 | 140 | def key_alias 141 | super.merge(CALENDAR_ITEM_KEY_ALIAS) 142 | end 143 | 144 | 145 | end 146 | end 147 | -------------------------------------------------------------------------------- /lib/ews/types/contact.rb: -------------------------------------------------------------------------------- 1 | module Viewpoint::EWS::Types 2 | class Contact 3 | include Viewpoint::EWS 4 | include Viewpoint::EWS::Types 5 | include Viewpoint::EWS::Types::Item 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /lib/ews/types/contacts_folder.rb: -------------------------------------------------------------------------------- 1 | module Viewpoint::EWS::Types 2 | class ContactsFolder 3 | include Viewpoint::EWS 4 | include Viewpoint::EWS::Types 5 | include Viewpoint::EWS::Types::GenericFolder 6 | 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /lib/ews/types/copied_event.rb: -------------------------------------------------------------------------------- 1 | =begin 2 | This file is part of Viewpoint; the Ruby library for Microsoft Exchange Web Services. 3 | 4 | Copyright © 2011 Dan Wanek 5 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); 7 | you may not use this file except in compliance with the License. 8 | You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | =end 18 | 19 | module Viewpoint::EWS::Types 20 | 21 | class CopiedEvent < Event 22 | 23 | COPIED_EVENT_KEY_PATHS = { 24 | :old_item_id => [:old_item_id, :attribs], 25 | :old_folder_id => [:old_folder_id, :attribs], 26 | :old_parent_folder_id => [:old_parent_folder_id, :attribs], 27 | } 28 | 29 | COPIED_EVENT_KEY_TYPES = { 30 | } 31 | 32 | COPIED_EVENT_KEY_ALIAS = { } 33 | 34 | 35 | private 36 | 37 | 38 | def key_paths 39 | @key_paths ||= super.merge COPIED_EVENT_KEY_PATHS 40 | end 41 | 42 | def key_types 43 | @key_types ||= super.merge COPIED_EVENT_KEY_TYPES 44 | end 45 | 46 | def key_alias 47 | @key_alias ||= super.merge COPIED_EVENT_KEY_ALIAS 48 | end 49 | 50 | end 51 | end 52 | -------------------------------------------------------------------------------- /lib/ews/types/created_event.rb: -------------------------------------------------------------------------------- 1 | =begin 2 | This file is part of Viewpoint; the Ruby library for Microsoft Exchange Web Services. 3 | 4 | Copyright © 2011 Dan Wanek 5 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); 7 | you may not use this file except in compliance with the License. 8 | You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | =end 18 | 19 | module Viewpoint::EWS::Types 20 | 21 | class CreatedEvent < Event 22 | 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /lib/ews/types/deleted_event.rb: -------------------------------------------------------------------------------- 1 | =begin 2 | This file is part of Viewpoint; the Ruby library for Microsoft Exchange Web Services. 3 | 4 | Copyright © 2011 Dan Wanek 5 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); 7 | you may not use this file except in compliance with the License. 8 | You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | =end 18 | 19 | module Viewpoint::EWS::Types 20 | 21 | class DeletedEvent < Event 22 | 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /lib/ews/types/distribution_list.rb: -------------------------------------------------------------------------------- 1 | module Viewpoint::EWS::Types 2 | class DistributionList 3 | include Viewpoint::EWS 4 | include Viewpoint::EWS::Types 5 | include Viewpoint::EWS::Types::Item 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /lib/ews/types/event.rb: -------------------------------------------------------------------------------- 1 | =begin 2 | This file is part of Viewpoint; the Ruby library for Microsoft Exchange Web Services. 3 | 4 | Copyright © 2011 Dan Wanek 5 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); 7 | you may not use this file except in compliance with the License. 8 | You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | =end 18 | 19 | module Viewpoint::EWS::Types 20 | 21 | class Event 22 | include Viewpoint::EWS 23 | include Viewpoint::EWS::Types 24 | include Viewpoint::EWS::Types::Item 25 | 26 | EVENT_KEY_PATHS = { 27 | :watermark => [:watermark, :text], 28 | :timestamp => [:time_stamp, :text], 29 | :item_id => [:item_id, :attribs], 30 | :folder_id => [:folder_id, :attribs], 31 | :parent_folder_id => [:parent_folder_id, :attribs], 32 | } 33 | 34 | EVENT_KEY_TYPES = { 35 | :timestamp => ->(ts){ DateTime.iso8601(ts) } 36 | } 37 | 38 | EVENT_KEY_ALIAS = { } 39 | 40 | def initialize(ews, event) 41 | @ews = ews 42 | super(ews, event) 43 | end 44 | 45 | 46 | private 47 | 48 | 49 | def key_paths 50 | @key_paths ||= EVENT_KEY_PATHS 51 | end 52 | 53 | def key_types 54 | @key_types ||= EVENT_KEY_TYPES 55 | end 56 | 57 | def key_alias 58 | @key_alias ||= EVENT_KEY_ALIAS 59 | end 60 | 61 | end 62 | end 63 | -------------------------------------------------------------------------------- /lib/ews/types/export_items_response_message.rb: -------------------------------------------------------------------------------- 1 | module Viewpoint::EWS::Types 2 | 3 | class ExportItemsResponseMessage 4 | include Viewpoint::EWS 5 | include Viewpoint::EWS::Types 6 | include Viewpoint::EWS::Types::Item 7 | 8 | BULK_KEY_PATHS = { 9 | :id => [:item_id, :attribs, :id], 10 | :change_key => [:item_id, :attribs, :change_key], 11 | :data => [:data, :text] 12 | } 13 | 14 | BULK_KEY_TYPES = { } 15 | 16 | BULK_KEY_ALIAS = { } 17 | 18 | def initialize(ews, bulk_item) 19 | super(ews, bulk_item) 20 | @item = bulk_item 21 | @ews = ews 22 | end 23 | 24 | def id 25 | @item[:item_id][:attribs][:id] 26 | end 27 | 28 | def change_key 29 | @item[:item_id][:attribs][:change_key] 30 | end 31 | 32 | def data 33 | @item[:data][:text] 34 | end 35 | 36 | 37 | private 38 | 39 | def key_paths 40 | @key_paths ||= BULK_KEY_PATHS 41 | end 42 | 43 | def key_types 44 | @key_types ||= BULK_KEY_TYPES 45 | end 46 | 47 | def key_alias 48 | @key_alias ||= BULK_KEY_ALIAS 49 | end 50 | 51 | end 52 | end -------------------------------------------------------------------------------- /lib/ews/types/file_attachment.rb: -------------------------------------------------------------------------------- 1 | =begin 2 | This file is part of Viewpoint; the Ruby library for Microsoft Exchange Web Services. 3 | 4 | Copyright © 2011 Dan Wanek 5 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); 7 | you may not use this file except in compliance with the License. 8 | You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | =end 18 | 19 | module Viewpoint::EWS::Types 20 | class FileAttachment < Attachment 21 | 22 | FILE_ATTACH_KEY_PATHS = { 23 | :is_contact_photo? => [:is_contact_photo, :text], 24 | :content => [:content, :text], 25 | } 26 | 27 | FILE_ATTACH_KEY_TYPES = { 28 | is_contact_photo?: ->(str){str.downcase == 'true'}, 29 | } 30 | 31 | FILE_ATTACH_KEY_ALIAS = { 32 | :file_name => :name, 33 | } 34 | 35 | def get_all_properties! 36 | resp = ews.get_attachment attachment_ids: [self.id] 37 | @ews_item.merge!(parse_response(resp)) 38 | end 39 | 40 | private 41 | 42 | 43 | def key_paths 44 | super.merge(FILE_ATTACH_KEY_PATHS) 45 | end 46 | 47 | def key_types 48 | super.merge(FILE_ATTACH_KEY_TYPES) 49 | end 50 | 51 | def key_alias 52 | super.merge(FILE_ATTACH_KEY_ALIAS) 53 | end 54 | 55 | def parse_response(resp) 56 | if(resp.status == 'Success') 57 | resp.response_message[:elems][:attachments][:elems][0][:file_attachment][:elems].inject(&:merge) 58 | else 59 | raise EwsError, "Could not retrieve #{self.class}. #{resp.code}: #{resp.message}" 60 | end 61 | end 62 | 63 | end 64 | end 65 | 66 | -------------------------------------------------------------------------------- /lib/ews/types/folder.rb: -------------------------------------------------------------------------------- 1 | module Viewpoint::EWS::Types 2 | class Folder 3 | include Viewpoint::EWS 4 | include Viewpoint::EWS::Types 5 | include Viewpoint::EWS::Types::GenericFolder 6 | 7 | FOLDER_KEY_PATHS = { 8 | :unread_count => [:unread_count, :text], 9 | } 10 | FOLDER_KEY_TYPES = { 11 | :unread_count => ->(str){str.to_i}, 12 | } 13 | FOLDER_KEY_ALIAS = {} 14 | 15 | alias :messages :items 16 | 17 | def unread_messages 18 | self.items read_unread_restriction 19 | end 20 | 21 | def read_messages 22 | self.items read_unread_restriction(true) 23 | end 24 | 25 | def messages_with_attachments 26 | opts = {:restriction => 27 | {:is_equal_to => [ 28 | {:field_uRI => {:field_uRI=>'item:HasAttachments'}}, 29 | {:field_uRI_or_constant => {:constant => {:value=> true}}} 30 | ]} 31 | } 32 | self.items opts 33 | end 34 | 35 | private 36 | 37 | 38 | def read_unread_restriction(read = false) 39 | {:restriction => 40 | {:is_equal_to => [ 41 | {:field_uRI => {:field_uRI=>'message:IsRead'}}, 42 | {:field_uRI_or_constant => {:constant => {:value=> read}}} 43 | ]} 44 | } 45 | end 46 | 47 | def key_paths 48 | @key_paths ||= super.merge(FOLDER_KEY_PATHS) 49 | end 50 | 51 | def key_types 52 | @key_types ||= super.merge(FOLDER_KEY_TYPES) 53 | end 54 | 55 | def key_alias 56 | @key_alias ||= super.merge(FOLDER_KEY_ALIAS) 57 | end 58 | 59 | end 60 | end 61 | -------------------------------------------------------------------------------- /lib/ews/types/free_busy_changed_event.rb: -------------------------------------------------------------------------------- 1 | =begin 2 | This file is part of Viewpoint; the Ruby library for Microsoft Exchange Web Services. 3 | 4 | Copyright © 2011 Dan Wanek 5 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); 7 | you may not use this file except in compliance with the License. 8 | You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | =end 18 | 19 | module Viewpoint::EWS::Types 20 | 21 | class FreeBusyChangedEvent < Event 22 | 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /lib/ews/types/item_attachment.rb: -------------------------------------------------------------------------------- 1 | =begin 2 | This file is part of Viewpoint; the Ruby library for Microsoft Exchange Web Services. 3 | 4 | Copyright © 2011 Dan Wanek 5 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); 7 | you may not use this file except in compliance with the License. 8 | You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | =end 18 | 19 | module Viewpoint::EWS::Types 20 | class ItemAttachment < Attachment 21 | 22 | ITEM_ATTACH_KEY_PATHS = { 23 | item: [:item], 24 | message: [:message], 25 | calendar_item: [:calendar_item], 26 | contact: [:contact], 27 | task: [:task], 28 | meeting_message: [:meeting_message], 29 | meeting_request: [:meeting_request], 30 | meeting_response: [:meeting_response], 31 | meeting_cancellation: [:meeting_cancellation] 32 | } 33 | 34 | ITEM_ATTACH_KEY_TYPES = { 35 | message: :build_message, 36 | calendar_item: :build_calendar_item, 37 | contact: :build_contact, 38 | task: :build_task, 39 | meeting_message: :build_meeting_message, 40 | meeting_request: :build_meeting_request, 41 | meeting_response: :build_meeting_response, 42 | meeting_cancellation: :build_meeting_cancellation 43 | } 44 | 45 | ITEM_ATTACH_KEY_ALIAS = { } 46 | 47 | def get_all_properties! 48 | resp = ews.get_attachment attachment_ids: [self.id] 49 | @ews_item.merge!(parse_response(resp)) 50 | end 51 | 52 | private 53 | 54 | def self.method_missing(method, *args, &block) 55 | if method.to_s =~ /^build_(.+)$/ 56 | class_by_name($1).new(ews, args[0]) 57 | else 58 | super 59 | end 60 | end 61 | 62 | def key_paths 63 | super.merge(ITEM_ATTACH_KEY_PATHS) 64 | end 65 | 66 | def key_types 67 | super.merge(ITEM_ATTACH_KEY_TYPES) 68 | end 69 | 70 | def key_alias 71 | super.merge(ITEM_ATTACH_KEY_ALIAS) 72 | end 73 | 74 | def parse_response(resp) 75 | if(resp.status == 'Success') 76 | resp.response_message[:elems][:attachments][:elems][0][:item_attachment][:elems].inject(&:merge) 77 | else 78 | raise EwsError, "Could not retrieve #{self.class}. #{resp.code}: #{resp.message}" 79 | end 80 | end 81 | 82 | end 83 | end 84 | 85 | -------------------------------------------------------------------------------- /lib/ews/types/mailbox_user.rb: -------------------------------------------------------------------------------- 1 | =begin 2 | This file is part of Viewpoint; the Ruby library for Microsoft Exchange Web Services. 3 | 4 | Copyright © 2011 Dan Wanek 5 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); 7 | you may not use this file except in compliance with the License. 8 | You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | =end 18 | 19 | module Viewpoint::EWS::Types 20 | 21 | # This represents a Mailbox object in the Exchange data store 22 | # @see http://msdn.microsoft.com/en-us/library/aa565036.aspx MSDN docs 23 | # @todo Design a Class method that resolves to an Array of MailboxUsers 24 | class MailboxUser 25 | include Viewpoint::EWS 26 | include Viewpoint::EWS::Types 27 | 28 | MAILBOX_KEY_PATHS = { 29 | name: [:name], 30 | email_address: [:email_address], 31 | } 32 | MAILBOX_KEY_TYPES = {} 33 | MAILBOX_KEY_ALIAS = { 34 | email: :email_address, 35 | } 36 | 37 | def initialize(ews, mbox_user) 38 | @ews = ews 39 | @ews_item = mbox_user 40 | simplify! 41 | end 42 | 43 | def out_of_office_settings 44 | mailbox = {:address => self.email_address} 45 | resp = @ews.get_user_oof_settings(mailbox) 46 | ewsi = resp.response.clone 47 | ewsi.delete(:response_message) 48 | return OutOfOffice.new(self,ewsi) 49 | s = resp[:oof_settings] 50 | @oof_state = s[:oof_state][:text] 51 | @oof_ext_audience = s[:external_audience][:text] 52 | @oof_start = DateTime.parse(s[:duration][:start_time][:text]) 53 | @oof_end = DateTime.parse(s[:duration][:end_time][:text]) 54 | @oof_internal_reply = s[:internal_reply][:message][:text] 55 | @oof_external_reply = s[:internal_reply][:message][:text] 56 | true 57 | end 58 | 59 | # Get information about when the user with the given email address is available. 60 | # @param [String] email_address The email address of the person to find availability for. 61 | # @param [DateTime] start_time The start of the time range to check as an xs:dateTime. 62 | # @param [DateTime] end_time The end of the time range to check as an xs:dateTime. 63 | # @see http://msdn.microsoft.com/en-us/library/aa563800(v=exchg.140) 64 | def get_user_availability(email_address, start_time, end_time) 65 | opts = { 66 | mailbox_data: [ :email =>{:address => email_address} ], 67 | free_busy_view_options: { 68 | time_window: {start_time: start_time, end_time: end_time}, 69 | } 70 | } 71 | resp = (Viewpoint::EWS::EWS.instance).ews.get_user_availability(opts) 72 | if(resp.status == 'Success') 73 | return resp.items 74 | else 75 | raise EwsError, "GetUserAvailability produced an error: #{resp.code}: #{resp.message}" 76 | end 77 | end 78 | 79 | # Adds one or more delegates to a principal's mailbox and sets specific access permissions 80 | # @see http://msdn.microsoft.com/en-us/library/bb856527.aspx 81 | # 82 | # @param [String,MailboxUser] delegate_email The user you would like to give delegate access to. 83 | # This can either be a simple String e-mail address or you can pass in a MailboxUser object. 84 | # @param [Hash] permissions A hash of folder type keys and permission type values. An example 85 | # would be {:calendar_folder_permission_level => 'Editor'}. Possible keys are: 86 | # :calendar_folder_permission_level, :tasks_folder_permission_level, :inbox_folder_permission_level 87 | # :contacts_folder_permission_level, :notes_folder_permission_level, :journal_folder_permission_level 88 | # and possible values are: None/Editor/Reviewer/Author/Custom 89 | # @return [true] This method either returns true or raises an error with the message 90 | # as to why this operation did not succeed. 91 | def add_delegate!(delegate_email, permissions) 92 | # Use a new hash so the passed hash is not modified in case we are in a loop. 93 | # Thanks to Markus Roberts for pointing this out. 94 | formatted_perms = {} 95 | # Modify permissions so we can pass it to the builders 96 | permissions.each_pair do |k,v| 97 | formatted_perms[k] = {:text => v} 98 | end 99 | 100 | resp = (Viewpoint::EWS::EWS.instance).ews.add_delegate(self.email_address, delegate_email, formatted_perms) 101 | if(resp.status == 'Success') 102 | return true 103 | else 104 | raise EwsError, "Could not add delegate access for user #{delegate_email}: #{resp.code}, #{resp.message}" 105 | end 106 | end 107 | 108 | def update_delegate!(delegate_email, permissions) 109 | # Modify permissions so we can pass it to the builders 110 | formatted_perms = {} 111 | permissions.each_pair do |k,v| 112 | formatted_perms[k] = {:text => v} 113 | end 114 | 115 | resp = (Viewpoint::EWS::EWS.instance).ews.update_delegate(self.email_address, delegate_email, formatted_perms) 116 | if(resp.status == 'Success') 117 | return true 118 | else 119 | raise EwsError, "Could not update delegate access for user #{delegate_email}: #{resp.code}, #{resp.message}" 120 | end 121 | end 122 | 123 | def get_delegate_info() 124 | resp = (Viewpoint::EWS::EWS.instance).ews.get_delegate(self.email_address) 125 | # if(resp.status == 'Success') 126 | # return true 127 | # else 128 | # raise EwsError, "Could not update delegate access for user #{delegate_email}: #{resp.code}, #{resp.message}" 129 | # end 130 | end 131 | 132 | 133 | private 134 | 135 | 136 | def simplify! 137 | @ews_item = @ews_item.inject({}){|m,o| 138 | m[o.keys.first] = o.values.first[:text]; 139 | m 140 | } 141 | end 142 | 143 | def key_paths 144 | @key_paths ||= super.merge(MAILBOX_KEY_PATHS) 145 | end 146 | 147 | def key_types 148 | @key_types ||= super.merge(MAILBOX_KEY_TYPES) 149 | end 150 | 151 | def key_alias 152 | @key_alias ||= super.merge(MAILBOX_KEY_ALIAS) 153 | end 154 | 155 | end # MailboxUser 156 | end # Viewpoint::EWS::Types 157 | -------------------------------------------------------------------------------- /lib/ews/types/meeting_cancellation.rb: -------------------------------------------------------------------------------- 1 | module Viewpoint::EWS::Types 2 | class MeetingCancellation 3 | include Viewpoint::EWS 4 | include Viewpoint::EWS::Types 5 | include Viewpoint::EWS::Types::Item 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /lib/ews/types/meeting_message.rb: -------------------------------------------------------------------------------- 1 | module Viewpoint::EWS::Types 2 | class MeetingMessage 3 | include Viewpoint::EWS 4 | include Viewpoint::EWS::Types 5 | include Viewpoint::EWS::Types::Item 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /lib/ews/types/meeting_request.rb: -------------------------------------------------------------------------------- 1 | module Viewpoint::EWS::Types 2 | class MeetingRequest 3 | include Viewpoint::EWS 4 | include Viewpoint::EWS::Types 5 | include Viewpoint::EWS::Types::Item 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /lib/ews/types/meeting_response.rb: -------------------------------------------------------------------------------- 1 | module Viewpoint::EWS::Types 2 | class MeetingResponse 3 | include Viewpoint::EWS 4 | include Viewpoint::EWS::Types 5 | include Viewpoint::EWS::Types::Item 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /lib/ews/types/message.rb: -------------------------------------------------------------------------------- 1 | module Viewpoint::EWS::Types 2 | class Message 3 | include Viewpoint::EWS 4 | include Viewpoint::EWS::Types 5 | include Viewpoint::EWS::Types::Item 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /lib/ews/types/modified_event.rb: -------------------------------------------------------------------------------- 1 | =begin 2 | This file is part of Viewpoint; the Ruby library for Microsoft Exchange Web Services. 3 | 4 | Copyright © 2011 Dan Wanek 5 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); 7 | you may not use this file except in compliance with the License. 8 | You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | =end 18 | 19 | module Viewpoint::EWS::Types 20 | 21 | class ModifiedEvent < Event 22 | 23 | MODIFIED_EVENT_KEY_PATHS = { 24 | } 25 | 26 | MODIFIED_EVENT_KEY_TYPES = { 27 | } 28 | 29 | MODIFIED_EVENT_KEY_ALIAS = { } 30 | 31 | 32 | private 33 | 34 | 35 | def key_paths 36 | @key_paths ||= super.merge MODIFIED_EVENT_KEY_PATHS 37 | end 38 | 39 | def key_types 40 | @key_types ||= super.merge MODIFIED_EVENT_KEY_TYPES 41 | end 42 | 43 | def key_alias 44 | @key_alias ||= super.merge MODIFIED_EVENT_KEY_ALIAS 45 | end 46 | 47 | end 48 | end 49 | -------------------------------------------------------------------------------- /lib/ews/types/moved_event.rb: -------------------------------------------------------------------------------- 1 | =begin 2 | This file is part of Viewpoint; the Ruby library for Microsoft Exchange Web Services. 3 | 4 | Copyright © 2011 Dan Wanek 5 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); 7 | you may not use this file except in compliance with the License. 8 | You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | =end 18 | 19 | module Viewpoint::EWS::Types 20 | 21 | class MovedEvent < Event 22 | 23 | MOVED_EVENT_KEY_PATHS = { 24 | :old_item_id => [:old_item_id, :attribs], 25 | :old_folder_id => [:old_folder_id, :attribs], 26 | :old_parent_folder_id => [:old_parent_folder_id, :attribs], 27 | } 28 | 29 | MOVED_EVENT_KEY_TYPES = { 30 | } 31 | 32 | MOVED_EVENT_KEY_ALIAS = { } 33 | 34 | 35 | private 36 | 37 | 38 | def key_paths 39 | @key_paths ||= super.merge MOVED_EVENT_KEY_PATHS 40 | end 41 | 42 | def key_types 43 | @key_types ||= super.merge MOVED_EVENT_KEY_TYPES 44 | end 45 | 46 | def key_alias 47 | @key_alias ||= super.merge MOVED_EVENT_KEY_ALIAS 48 | end 49 | 50 | end 51 | end 52 | -------------------------------------------------------------------------------- /lib/ews/types/new_mail_event.rb: -------------------------------------------------------------------------------- 1 | =begin 2 | This file is part of Viewpoint; the Ruby library for Microsoft Exchange Web Services. 3 | 4 | Copyright © 2011 Dan Wanek 5 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); 7 | you may not use this file except in compliance with the License. 8 | You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | =end 18 | 19 | module Viewpoint::EWS::Types 20 | 21 | class NewMailEvent < Event 22 | 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /lib/ews/types/out_of_office.rb: -------------------------------------------------------------------------------- 1 | =begin 2 | This file is part of Viewpoint; the Ruby library for Microsoft Exchange Web Services. 3 | 4 | Copyright © 2011 Dan Wanek 5 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); 7 | you may not use this file except in compliance with the License. 8 | You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | =end 18 | 19 | module Viewpoint::EWS::Types 20 | 21 | OOF_KEY_PATHS = { 22 | :enabled? => [:oof_settings, :oof_state], 23 | :scheduled? => [:oof_settings, :oof_state], 24 | :duration => [:oof_settings, :duration], 25 | } 26 | 27 | OOF_KEY_TYPES = { 28 | :enabled? => ->(str){str == :enabled}, 29 | :scheduled? => ->(str){str == :scheduled}, 30 | :duration => ->(hsh){ hsh[:start_time]..hsh[:end_time] }, 31 | } 32 | 33 | OOF_KEY_ALIAS = {} 34 | 35 | # This represents OutOfOffice settings 36 | # @see http://msdn.microsoft.com/en-us/library/aa563465.aspx 37 | class OutOfOffice 38 | include Viewpoint::EWS 39 | include Viewpoint::EWS::Types 40 | 41 | attr_reader :user 42 | 43 | # @param [MailboxUser] user 44 | # @param [Hash] ews_item 45 | def initialize(user, ews_item) 46 | @ews = user.ews 47 | @user = user 48 | @ews_item = ews_item 49 | @changed = false 50 | simplify! 51 | end 52 | 53 | def changed? 54 | @changed 55 | end 56 | 57 | def save! 58 | return true unless changed? 59 | opts = { mailbox: {address: user.email_address} }.merge(@ews_item[:oof_settings]) 60 | resp = @ews.set_user_oof_settings(opts) 61 | if resp.success? 62 | @changed = false 63 | true 64 | else 65 | raise SaveFailed, "Could not save #{self.class}. #{resp.code}: #{resp.message}" 66 | end 67 | end 68 | 69 | def enable 70 | return true if enabled? 71 | @changed = true 72 | @ews_item[:oof_settings][:oof_state] = :enabled 73 | end 74 | 75 | def disable 76 | return true unless enabled? || scheduled? 77 | @changed = true 78 | @ews_item[:oof_settings][:oof_state] = :disabled 79 | end 80 | 81 | # Schedule an out of office. 82 | # @param [DateTime] start_time 83 | # @param [DateTime] end_time 84 | def schedule(start_time, end_time) 85 | @changed = true 86 | @ews_item[:oof_settings][:oof_state] = :scheduled 87 | set_duration start_time, end_time 88 | end 89 | 90 | # Specify a duration for this Out Of Office setting 91 | # @param [DateTime] start_time 92 | # @param [DateTime] end_time 93 | def set_duration(start_time, end_time) 94 | @changed = true 95 | @ews_item[:oof_settings][:duration][:start_time] = start_time 96 | @ews_item[:oof_settings][:duration][:end_time] = end_time 97 | end 98 | 99 | # A message to send to internal users 100 | # @param [String] message 101 | def internal_reply=(message) 102 | @changed = true 103 | @ews_item[:oof_settings][:internal_reply] = message 104 | end 105 | 106 | # A message to send to external users 107 | # @param [String] message 108 | def external_reply=(message) 109 | @changed = true 110 | @ews_item[:oof_settings][:external_reply] = message 111 | end 112 | 113 | 114 | private 115 | 116 | def key_paths 117 | @key_paths ||= super.merge(OOF_KEY_PATHS) 118 | end 119 | 120 | def key_types 121 | @key_types ||= super.merge(OOF_KEY_TYPES) 122 | end 123 | 124 | def key_alias 125 | @key_alias ||= super.merge(OOF_KEY_ALIAS) 126 | end 127 | 128 | def simplify! 129 | oof_settings = @ews_item[:oof_settings][:elems].inject(:merge) 130 | oof_settings[:oof_state] = oof_settings[:oof_state][:text].downcase.to_sym 131 | oof_settings[:external_audience] = oof_settings[:external_audience][:text] 132 | if oof_settings[:duration] 133 | dur = oof_settings[:duration][:elems].inject(:merge) 134 | oof_settings[:duration] = { 135 | start_time: DateTime.iso8601(dur[:start_time][:text]), 136 | end_time: DateTime.iso8601(dur[:end_time][:text]) 137 | } 138 | end 139 | oof_settings[:internal_reply] = oof_settings[:internal_reply][:elems][0][:message][:text] || "" 140 | oof_settings[:external_reply] = oof_settings[:external_reply][:elems][0][:message][:text] || "" 141 | @ews_item[:oof_settings] = oof_settings 142 | @ews_item[:allow_external_oof] = @ews_item[:allow_external_oof][:text] 143 | end 144 | 145 | end #OutOfOffice 146 | 147 | end 148 | -------------------------------------------------------------------------------- /lib/ews/types/post_item.rb: -------------------------------------------------------------------------------- 1 | module Viewpoint::EWS::Types 2 | class PostItem 3 | include Viewpoint::EWS 4 | include Viewpoint::EWS::Types 5 | include Viewpoint::EWS::Types::Item 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /lib/ews/types/search_folder.rb: -------------------------------------------------------------------------------- 1 | module Viewpoint::EWS::Types 2 | class SearchFolder 3 | include Viewpoint::EWS 4 | include Viewpoint::EWS::Types 5 | include Viewpoint::EWS::Types::GenericFolder 6 | 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /lib/ews/types/status_event.rb: -------------------------------------------------------------------------------- 1 | =begin 2 | This file is part of Viewpoint; the Ruby library for Microsoft Exchange Web Services. 3 | 4 | Copyright © 2011 Dan Wanek 5 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); 7 | you may not use this file except in compliance with the License. 8 | You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | =end 18 | 19 | module Viewpoint::EWS::Types 20 | 21 | class StatusEvent 22 | include Viewpoint::EWS 23 | include Viewpoint::EWS::Types 24 | include Viewpoint::EWS::Types::Item 25 | 26 | STATUS_EVENT_KEY_PATHS = { 27 | :watermark => [:watermark, :text], 28 | } 29 | 30 | 31 | private 32 | 33 | 34 | def key_paths 35 | @key_paths ||= STATUS_EVENT_KEY_PATHS 36 | end 37 | 38 | end 39 | end 40 | -------------------------------------------------------------------------------- /lib/ews/types/task.rb: -------------------------------------------------------------------------------- 1 | module Viewpoint::EWS::Types 2 | class Task 3 | include Viewpoint::EWS 4 | include Viewpoint::EWS::Types 5 | include Viewpoint::EWS::Types::Item 6 | 7 | TASK_KEY_PATHS = { 8 | complete?: [:is_complete, :text], 9 | recurring?: [:is_recurring, :text], 10 | start_date: [:start_date, :text], 11 | due_date: [:end_date, :text], 12 | reminder_due_by: [:reminder_due_by, :text], 13 | reminder?: [:reminder_is_set, :text], 14 | percent_complete: [:percent_complete, :text], 15 | status: [:status, :text], 16 | } 17 | 18 | TASK_KEY_TYPES = { 19 | recurring?: ->(str){str.downcase == 'true'}, 20 | complete?: ->(str){str.downcase == 'true'}, 21 | reminder?: ->(str){str.downcase == 'true'}, 22 | percent_complete: ->(str){str.to_i}, 23 | } 24 | TASK_KEY_ALIAS = {} 25 | 26 | private 27 | 28 | def key_paths 29 | super.merge(TASK_KEY_PATHS) 30 | end 31 | 32 | def key_types 33 | super.merge(TASK_KEY_TYPES) 34 | end 35 | 36 | def key_alias 37 | super.merge(TASK_KEY_ALIAS) 38 | end 39 | 40 | end 41 | end 42 | -------------------------------------------------------------------------------- /lib/ews/types/tasks_folder.rb: -------------------------------------------------------------------------------- 1 | module Viewpoint::EWS::Types 2 | class TasksFolder 3 | include Viewpoint::EWS 4 | include Viewpoint::EWS::Types 5 | include Viewpoint::EWS::Types::GenericFolder 6 | 7 | # Creates a new task 8 | # @param attributes [Hash] Parameters of the task. Some example attributes are listed below. 9 | # @option attributes :subject [String] 10 | # @option attributes :start_date [Time] 11 | # @option attributes :due_date [Time] 12 | # @option attributes :reminder_due_by [Time] 13 | # @option attributes :reminder_is_set [Boolean] 14 | # @return [Task] 15 | # @see Template::Task 16 | def create_item(attributes) 17 | template = Viewpoint::EWS::Template::Task.new attributes 18 | template.saved_item_folder_id = {id: self.id, change_key: self.change_key} 19 | rm = ews.create_item(template.to_ews_create).response_messages.first 20 | if rm && rm.success? 21 | Task.new ews, rm.items.first[:task][:elems].first 22 | else 23 | if rm 24 | raise EwsCreateItemError, "Could not create item in folder. #{rm.code}: #{rm.message_text}" 25 | else 26 | raise EwsCreateItemError, "Could not create item in folder." 27 | end 28 | end 29 | end 30 | end 31 | end 32 | -------------------------------------------------------------------------------- /lib/viewpoint.rb: -------------------------------------------------------------------------------- 1 | =begin 2 | This file is part of Viewpoint; the Ruby library for Microsoft Exchange Web Services. 3 | 4 | Copyright © 2011 Dan Wanek 5 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); 7 | you may not use this file except in compliance with the License. 8 | You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | =end 18 | 19 | require 'kconv' if(RUBY_VERSION.start_with? '1.9') # bug in rubyntlm with ruby 1.9.x 20 | require 'date' 21 | require 'base64' 22 | require 'nokogiri' 23 | require 'ostruct' 24 | require 'logging' 25 | 26 | # String utilities 27 | require 'viewpoint/string_utils' 28 | 29 | # Load the logging setup 30 | require 'viewpoint/logging' 31 | 32 | # Load the Exception classes 33 | require 'ews/exceptions/exceptions' 34 | 35 | # Load the backend SOAP / EWS infrastructure. 36 | require 'ews/soap' 37 | require 'ews/soap/response_message' 38 | require 'ews/soap/ews_response' 39 | require 'ews/soap/ews_soap_response' 40 | require 'ews/soap/ews_soap_availability_response' 41 | require 'ews/soap/ews_soap_free_busy_response' 42 | require 'ews/soap/ews_soap_room_response' 43 | require 'ews/soap/ews_soap_roomlist_response' 44 | require 'ews/soap/builders/ews_builder' 45 | require 'ews/soap/parsers/ews_parser' 46 | require 'ews/soap/parsers/ews_sax_document' 47 | # Mix-ins for the ExchangeWebService 48 | require 'ews/soap/exchange_data_services' 49 | require 'ews/soap/exchange_notification' 50 | require 'ews/soap/exchange_synchronization' 51 | require 'ews/soap/exchange_availability' 52 | require 'ews/soap/exchange_user_configuration' 53 | require 'ews/soap/exchange_time_zones' 54 | require 'ews/soap/exchange_web_service' 55 | 56 | require 'ews/errors' 57 | require 'ews/connection_helper' 58 | require 'ews/connection' 59 | 60 | require 'ews/impersonation' 61 | 62 | # Base Types 63 | require 'ews/types' 64 | require 'ews/types/item_field_uri_map' 65 | require 'ews/types/generic_folder' 66 | require 'ews/types/item' 67 | # Folders 68 | require 'ews/types/folder' 69 | require 'ews/types/calendar_folder' 70 | require 'ews/types/contacts_folder' 71 | require 'ews/types/tasks_folder' 72 | require 'ews/types/search_folder' 73 | # Items 74 | require 'ews/types/message' 75 | require 'ews/types/calendar_item' 76 | require 'ews/types/contact' 77 | require 'ews/types/distribution_list' 78 | require 'ews/types/meeting_message' 79 | require 'ews/types/meeting_request' 80 | require 'ews/types/meeting_response' 81 | require 'ews/types/meeting_cancellation' 82 | require 'ews/types/task' 83 | require 'ews/types/attachment' 84 | require 'ews/types/file_attachment' 85 | require 'ews/types/item_attachment' 86 | require 'ews/types/mailbox_user' 87 | require 'ews/types/out_of_office' 88 | require 'ews/types/export_items_response_message' 89 | require 'ews/types/post_item' 90 | 91 | # Events 92 | require 'ews/types/event' 93 | require 'ews/types/copied_event' 94 | require 'ews/types/created_event' 95 | require 'ews/types/deleted_event' 96 | require 'ews/types/free_busy_changed_event' 97 | require 'ews/types/modified_event' 98 | require 'ews/types/moved_event' 99 | require 'ews/types/new_mail_event' 100 | require 'ews/types/status_event' 101 | 102 | # Template Objects 103 | require 'ews/templates/message' 104 | require 'ews/templates/forward_item' 105 | require 'ews/templates/reply_to_item' 106 | require 'ews/templates/calendar_item' 107 | require 'ews/templates/task' 108 | 109 | # The proxy between the models and the web service 110 | require 'ews/ews_client' 111 | -------------------------------------------------------------------------------- /lib/viewpoint/logging.rb: -------------------------------------------------------------------------------- 1 | =begin 2 | This file is part of Viewpoint; the Ruby library for Microsoft Exchange Web Services. 3 | 4 | Copyright © 2011 Dan Wanek 5 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); 7 | you may not use this file except in compliance with the License. 8 | You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | =end 18 | 19 | module Viewpoint 20 | module EWS 21 | attr_reader :logger 22 | 23 | def self.root_logger 24 | Logging.logger.root 25 | end 26 | end # EWS 27 | end 28 | -------------------------------------------------------------------------------- /lib/viewpoint/logging/config.rb: -------------------------------------------------------------------------------- 1 | =begin 2 | This file is part of Viewpoint; the Ruby library for Microsoft Exchange Web Services. 3 | 4 | Copyright © 2011 Dan Wanek 5 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); 7 | you may not use this file except in compliance with the License. 8 | You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | =end 18 | 19 | module Viewpoint 20 | module EWS 21 | Logging.logger.root.level = :debug 22 | Logging.logger.root.appenders = Logging.appenders.stdout 23 | end # EWS 24 | end 25 | -------------------------------------------------------------------------------- /lib/viewpoint/string_utils.rb: -------------------------------------------------------------------------------- 1 | =begin 2 | This file is part of Viewpoint; the Ruby library for Microsoft Exchange Web Services. 3 | 4 | Copyright © 2011 Dan Wanek 5 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); 7 | you may not use this file except in compliance with the License. 8 | You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | =end 18 | 19 | module Viewpoint 20 | 21 | class StringFormatException < ::Exception; end 22 | 23 | # Collection of utility methods for working with Strings 24 | module StringUtils 25 | 26 | DURATION_RE = / 27 | (?P) 28 | ((?\d+)W)? 29 | ((?\d+)D)? 30 | (?