viewpoint 0.0.5 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. data/README +84 -45
  2. data/Rakefile +7 -5
  3. data/TODO +6 -0
  4. data/VERSION +1 -1
  5. data/lib/exceptions/exceptions.rb +34 -0
  6. data/lib/extensions/string.rb +37 -0
  7. data/lib/model/calendar_folder.rb +45 -0
  8. data/lib/model/calendar_item.rb +145 -0
  9. data/lib/model/contact.rb +58 -0
  10. data/lib/model/contacts_folder.rb +35 -0
  11. data/lib/model/distribution_list.rb +26 -0
  12. data/lib/model/event.rb +118 -0
  13. data/lib/model/folder.rb +36 -0
  14. data/lib/model/generic_folder.rb +302 -0
  15. data/lib/model/item.rb +126 -0
  16. data/lib/model/mailbox_user.rb +107 -0
  17. data/lib/model/meeting_cancellation.rb +28 -0
  18. data/lib/{viewpoint/errors.rb → model/meeting_message.rb} +10 -14
  19. data/lib/model/meeting_request.rb +26 -0
  20. data/lib/model/meeting_response.rb +26 -0
  21. data/lib/model/message.rb +73 -0
  22. data/lib/model/model.rb +161 -0
  23. data/lib/model/search_folder.rb +36 -0
  24. data/lib/model/task.rb +62 -0
  25. data/lib/model/task_list.rb +19 -0
  26. data/lib/model/tasks_folder.rb +33 -0
  27. data/lib/soap/handsoap/builder.rb +22 -0
  28. data/lib/soap/handsoap/builders/ews_build_helpers.rb +317 -0
  29. data/lib/soap/handsoap/builders/ews_builder.rb +86 -0
  30. data/lib/soap/handsoap/ews_service.rb +646 -0
  31. data/lib/soap/handsoap/parser.rb +106 -0
  32. data/lib/soap/handsoap/parsers/ews_parser.rb +165 -0
  33. data/lib/soap/soap_provider.rb +75 -0
  34. data/lib/viewpoint.rb +98 -3
  35. data/preamble +1 -1
  36. data/test/spec/basic_functions.spec +51 -0
  37. data/test/spec/folder_subscriptions.spec +35 -0
  38. data/test/spec/folder_synchronization.spec +28 -0
  39. data/utils/ewsWSDL2rb.rb +29 -0
  40. metadata +101 -43
  41. data/lib/exchwebserv.rb +0 -6
  42. data/lib/soap/viewpoint.conf +0 -3
  43. data/lib/viewpoint/calendar.rb +0 -128
  44. data/lib/viewpoint/calendar_item.rb +0 -118
  45. data/lib/viewpoint/event.rb +0 -0
  46. data/lib/viewpoint/exchange_headers.rb +0 -49
  47. data/lib/viewpoint/exchwebserv.rb +0 -236
  48. data/lib/viewpoint/folder.rb +0 -358
  49. data/lib/viewpoint/item.rb +0 -101
  50. data/lib/viewpoint/mail.rb +0 -117
  51. data/lib/viewpoint/message.rb +0 -132
  52. data/lib/viewpoint/task.rb +0 -0
  53. data/lib/viewpoint/tasks.rb +0 -0
  54. data/lib/wsdl/defaultMappingRegistry.rb +0 -10680
  55. data/lib/wsdl/exchangeServiceBinding.rb +0 -349
  56. data/lib/wsdl/exchangeServiceTypes.rb +0 -11013
  57. data/test/spec/basic_features_spec.rb +0 -37
  58. data/test/test_client.rb +0 -13
  59. data/test/testrestrict.rb +0 -75
data/README CHANGED
@@ -3,67 +3,106 @@
3
3
  --------------------------------------------------------------------------
4
4
  This program attempts to create a client access library for Exchange Web
5
5
  Services (EWS) in Ruby.
6
- --------------------------------------------------------------------------
7
- TO USE:
8
- require 'rubygems'
9
- require 'viewpoint'
10
- # See REQUIRED GEMS below
11
6
 
12
- REQUIRED GEMS:
13
-
14
- # Current SOAP4R ( http://dev.ctor.org/soap4r )
15
- gem install -r soap4r
16
- # NTLM isn't an automatic dependency so you may need this if you are having issues.
17
- gem install -r rubyntlm
7
+ !!!CAUTION!!! This is currently BETA code and has changed dramatically from
8
+ the original version of Viewpoint which was based on Soap4r. This version
9
+ has essentially been gutted and written on top of Handsoap. Development
10
+ has been much more flexible, but the interface to Viewpoint has changed
11
+ quite a bit. I have tried to write good code comments and I will keep
12
+ enhancing this. I will also try and post examples on my blog as I write
13
+ them or they are asked for.
18
14
 
15
+ BLOG: http://distributed-frostbite.blogspot.com/
16
+ Add me in LinkedIn: http://www.linkedin.com/in/danwanek
19
17
 
20
- # iCalendar
21
- gem install -r icalendar
18
+ --------------------------------------------------------------------------
19
+ MAJOR CHANGES TO THE FIRST VERSION:
22
20
 
23
- CONFIGURATION:
24
- Configure your user/pass and EWS endpoint in lib/soap/viewpoint.conf
25
- or $HOME/.viewpointrc. If the file $HOME/.viewpointrc exists it takes
26
- presidence. See the sample in lib/soap/viewpoint.conf for how this
27
- file should be configured.
21
+ New SOAP backend
22
+ Viewpoint now uses Handsoap as its back-end instead of soap4r. While
23
+ soap4r does some very nice things for you automatically, it ends up
24
+ making your code base fairly large and it complicates any customizations
25
+ that you might want to make. One example is adding custom headers. Soap4r
26
+ required you to create a subclass to use as a sort of hook. I can do the
27
+ same thing in Handsoap with a one-liner in the services #on_create_document
28
+ method.
28
29
 
30
+ Models are completely rewritten
31
+ The models are completely new and not backward compatible with the old
32
+ version of Viewpoint. Some of the methods still exist, but don't count
33
+ on them. I've tried to make this version much more extensible than the
34
+ last.
29
35
 
30
- Running Examples:
31
- To run the FuseFS example you need the 'fusefs' gem
36
+ Delegate access is supported
37
+ One thing that was often asked for, but missing from the previous version
38
+ was delegate access to mailboxes and calendars. This is now supported via
39
+ the 'act_as' parameter to the GenericFolder::get_folder method. For example:
40
+ ofolder = Folder.get_folder(:inbox,'otheruser@test.com')
41
+ If your user has delegate access to the Inbox for otheruser@test.com this
42
+ operation will retrieve their inbox and allow you to manipulate it as you
43
+ would with your own Inbox.
32
44
 
45
+ There is also some support for manipulation of delegate access itself via
46
+ the methods MailboxUser#add_delegate!, MailboxUser#update_delegate!, and
47
+ MailboxUser#get_delegate_info.
33
48
 
34
- ******************** EXAMPLES *********************
35
- # In the following examples the following are used:
36
- # "item" is a type of Viewpoint::Item
37
- # "folder" is a type of Viewpoint::Folder
38
- # "new_folder" is a type of Viewpoint::Folder
49
+ Misc other changes
50
+ Since it's a complete rewrite there are tons of other changes that you'll
51
+ notice. I've tried to keep the code comments coming so stay tuned to the
52
+ API docs for library information. I'll also be posting more examples to
53
+ my blog.
39
54
 
40
- # === Convert your Exchange Calendar to a Icalendar::Calendar object ===
55
+ --------------------------------------------------------------------------
56
+ TO USE:
41
57
  require 'rubygems'
42
58
  require 'viewpoint'
43
- vp = Viewpoint::ExchWebServ.instance
44
- vp.authenticate
45
- vp.find_folders
46
- cal = vp.get_folder("Calendar")
47
- ical = cal.to_ical
48
- puts ical.to_ical
59
+ # See REQUIRED GEMS below
60
+
61
+ REQUIRED GEMS:
62
+
63
+ # Handsoap (Thanks jrun for pointing me this way!)
64
+ gem install -r handsoap
65
+ # Nokogiri XML Parser
66
+ gem install -r nokogiri
67
+ # HttpClient
68
+ gem install -r httpclient
69
+ # NTLM Library
70
+ gem install -r rubyntlm
49
71
 
50
- # === Get a listing of todays messages ===
51
- # See test/test_client.rb
72
+ # iCalendar (still forthcoming in this release)
73
+ gem install -r icalendar
52
74
 
53
- # === Moving an item ===
54
- item.move_to!(new_folder)
75
+ --------------------------------------------------------------------------
76
+ DESIGN GOALS/GUIDELINES:
55
77
 
56
- # === Deleting an item ===
57
- item.delete!
58
- item.recycle! # Move to "Deleted Items"
78
+ 1. The SOAP back-end should not know about the Model.
79
+ I went around and around on this one for awhile. There are some
80
+ simplicity advantages to creating Model objects within the SOAP
81
+ responses, but I ultimately decided against it so that one could use
82
+ the SOAP back-end without the Model. Essentially the SOAP classes
83
+ pass back a Hash that the Model uses to create its own objects.
59
84
 
85
+ 2. The use of Hashes is not a crime.
86
+ While some people decidedly do not like Hashes and believe complex
87
+ hashing should be in the form of objects, there are some instances
88
+ where hashing is just plain simpler and flexible. To that end, I use
89
+ hashes pretty extensively in Viewpoint, both for objects being passed
90
+ to the SOAP back-end and returned from it.
91
+
92
+ 3. Follow EWS naming conventions where it makes sense.
93
+ I try and follow the naming conventions of the Exchange Web Service
94
+ operations as much as it makes sense. There are some things howerver
95
+ where they do not and I have deviated somewhat. For example,
96
+ an instance method named delete_folder doesn't make much sense, but
97
+ an instance method named delete! is pretty clear what it deletes.
60
98
 
61
99
  --------------------------------------------------------------------------
62
- DISCLAIMER: I am by no means a Ruby or EWS expert. There may be better
63
- means of doing what I am attempting to do. If you see something that
64
- could be done better or would like to help out in the development of this
65
- code please feel free to clone the 'git' repository:
66
- git clone git://github.com/zenchild/Viewpoint-for-MS-Exchange.git
100
+ DISCLAIMER: If you see something that could be done better or would like
101
+ to help out in the development of this code please feel free to clone the
102
+ 'git' repository and send me patches:
103
+ git clone git://github.com/zenchild/Viewpoint.git
67
104
  or add an issue on GitHub:
68
- http://github.com/zenchild/Viewpoint-for-MS-Exchange/issues
105
+ http://github.com/zenchild/Viewpoint/issues
106
+
107
+ Cheers!
69
108
  --------------------------------------------------------------------------
data/Rakefile CHANGED
@@ -1,6 +1,7 @@
1
1
  require 'rubygems'
2
2
  require 'rake/clean'
3
3
  require 'rake/gempackagetask'
4
+ require 'date'
4
5
 
5
6
  CLEAN.include("pkg")
6
7
  CLEAN.include("doc")
@@ -18,19 +19,20 @@ GEMSPEC = Gem::Specification.new do |gem|
18
19
 
19
20
  gem.summary = "A Ruby client access library for Microsoft Exchange Web Services (EWS)"
20
21
  gem.description = <<-EOF
21
- A Ruby client access library for Microsoft Exchange Web Services (EWS). It is a work in progress. Methods are still being added from the EWS API docs. Please see them for further information: http://msdn.microsoft.com/en-us/library/bb204119.aspx
22
+ A Ruby client access library for Microsoft Exchange Web Services (EWS). Examples can be found here: http://distributed-frostbite.blogspot.com
22
23
  EOF
23
24
 
24
25
  gem.files = `git ls-files`.split(/\n/)
25
26
  gem.require_path = "lib"
26
- gem.rdoc_options = %w(-x wsdl/ -x test/ -x examples/)
27
+ gem.rdoc_options = %w(-x test/ -x examples/)
27
28
  gem.extra_rdoc_files = %w(README COPYING.txt)
28
29
 
29
30
  gem.required_ruby_version = '>= 1.8.7'
30
- gem.add_runtime_dependency 'soap4r', '>=1.5.8'
31
+ gem.add_runtime_dependency 'handsoap'
32
+ gem.add_runtime_dependency 'nokogiri'
33
+ gem.add_runtime_dependency 'httpclient'
34
+ gem.add_runtime_dependency 'rubyntlm'
31
35
  gem.add_runtime_dependency 'icalendar'
32
- gem.add_runtime_dependency 'rubyntlm', '>=0.1.1'
33
- gem.post_install_message = "Don't forget to create .viewpointrc. See README"
34
36
  end
35
37
 
36
38
  Rake::GemPackageTask.new(GEMSPEC) do |pkg|
data/TODO ADDED
@@ -0,0 +1,6 @@
1
+
2
+ - Automate "deepening" of Model objects by over-riding method_missing
3
+ … if object.is_shallow? && all_methods.index(method)
4
+ deepen!
5
+ else
6
+ raise the NoMethod error
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.5
1
+ 0.1.0
@@ -0,0 +1,34 @@
1
+ #############################################################################
2
+ # Copyright © 2010 Dan Wanek <dan.wanek@gmail.com>
3
+ #
4
+ #
5
+ # This file is part of Viewpoint.
6
+ #
7
+ # Viewpoint is free software: you can redistribute it and/or
8
+ # modify it under the terms of the GNU General Public License as published
9
+ # by the Free Software Foundation, either version 3 of the License, or (at
10
+ # your option) any later version.
11
+ #
12
+ # Viewpoint is distributed in the hope that it will be useful,
13
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
15
+ # Public License for more details.
16
+ #
17
+ # You should have received a copy of the GNU General Public License along
18
+ # with Viewpoint. If not, see <http://www.gnu.org/licenses/>.
19
+ #############################################################################
20
+ module Viewpoint
21
+ module EWS
22
+
23
+ # Generic Ews Error
24
+ class EwsError < StandardError
25
+ end
26
+
27
+ # Raised when a user tries to query a folder subscription after the
28
+ # subscription has timed out.
29
+ class EwsSubscriptionTimeout < StandardError
30
+ end
31
+
32
+ end # EWS
33
+ end # Viewpoint
34
+
@@ -0,0 +1,37 @@
1
+ #############################################################################
2
+ # Copyright © 2010 Dan Wanek <dan.wanek@gmail.com>
3
+ #
4
+ #
5
+ # This file is part of Viewpoint.
6
+ #
7
+ # Viewpoint is free software: you can redistribute it and/or
8
+ # modify it under the terms of the GNU General Public License as published
9
+ # by the Free Software Foundation, either version 3 of the License, or (at
10
+ # your option) any later version.
11
+ #
12
+ # Viewpoint is distributed in the hope that it will be useful,
13
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
15
+ # Public License for more details.
16
+ #
17
+ # You should have received a copy of the GNU General Public License along
18
+ # with Viewpoint. If not, see <http://www.gnu.org/licenses/>.
19
+ #############################################################################
20
+
21
+ # Custom extensions to the class String
22
+ class String
23
+ # Change CamelCased strings to ruby_cased strings
24
+ # It uses the lookahead assertion ?= In this case it basically says match
25
+ # anything followed by a capital letter, but not the capital letter itself.
26
+ # @see http://www.pcre.org/pcre.txt The PCRE guide for more details
27
+ def ruby_case
28
+ self.split(/(?=[A-Z])/).join('_').downcase
29
+ end
30
+
31
+ # Change a ruby_cased string to CamelCased
32
+ def camel_case
33
+ self.split(/_/).map { |i|
34
+ i.sub(/^./) { |s| s.upcase }
35
+ }.join
36
+ end
37
+ end # String
@@ -0,0 +1,45 @@
1
+ #############################################################################
2
+ # Copyright © 2010 Dan Wanek <dan.wanek@gmail.com>
3
+ #
4
+ #
5
+ # This file is part of Viewpoint.
6
+ #
7
+ # Viewpoint is free software: you can redistribute it and/or
8
+ # modify it under the terms of the GNU General Public License as published
9
+ # by the Free Software Foundation, either version 3 of the License, or (at
10
+ # your option) any later version.
11
+ #
12
+ # Viewpoint is distributed in the hope that it will be useful,
13
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
15
+ # Public License for more details.
16
+ #
17
+ # You should have received a copy of the GNU General Public License along
18
+ # with Viewpoint. If not, see <http://www.gnu.org/licenses/>.
19
+ #############################################################################
20
+
21
+ module Viewpoint
22
+ module EWS
23
+ class CalendarFolder < GenericFolder
24
+
25
+ # initialize with an item of CalendarFolderType
26
+ def initialize(folder)
27
+ super(folder)
28
+
29
+ # @todo Handle:
30
+ # <SharingEffectiveRights/>
31
+ end
32
+
33
+ # Find Items
34
+ # @see GenericFolder#find_items
35
+ def find_items(start_date = nil, end_date = nil)
36
+ opts ||= {}
37
+ if(!start_date.nil? && !end_date.nil?)
38
+ opts = {:calendar_view => {:max_entries_returned => 256, :start_date => start_date, :end_date => end_date}}
39
+ end
40
+ super(opts)
41
+ end
42
+
43
+ end # CalendarFolder
44
+ end # EWS
45
+ end # Viewpoint
@@ -0,0 +1,145 @@
1
+ #############################################################################
2
+ # Copyright © 2010 Dan Wanek <dan.wanek@gmail.com>
3
+ #
4
+ #
5
+ # This file is part of Viewpoint.
6
+ #
7
+ # Viewpoint is free software: you can redistribute it and/or
8
+ # modify it under the terms of the GNU General Public License as published
9
+ # by the Free Software Foundation, either version 3 of the License, or (at
10
+ # your option) any later version.
11
+ #
12
+ # Viewpoint is distributed in the hope that it will be useful,
13
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
15
+ # Public License for more details.
16
+ #
17
+ # You should have received a copy of the GNU General Public License along
18
+ # with Viewpoint. If not, see <http://www.gnu.org/licenses/>.
19
+ #############################################################################
20
+
21
+ module Viewpoint
22
+ module EWS
23
+ class CalendarItem < Message
24
+
25
+ # This is a class method that creates a new CalendarItem in the Exchange Data Store.
26
+ # @param [Hash] item A Hash of values based on values found here:
27
+ # http://msdn.microsoft.com/en-us/library/aa564765.aspx
28
+ # @param [String, Symbol] folder_id The folder to create this item in. Either a
29
+ # DistinguishedFolderId (must me a Symbol) or a FolderId (String)
30
+ # @param [String] send_invites "SendToNone/SendOnlyToAll/SendToAllAndSaveCopy"
31
+ # See: http://msdn.microsoft.com/en-us/library/aa565209.aspx
32
+ # @example Typical Usage
33
+ # item = { :subject => {:text => 'Planning'},
34
+ # :body => {:body_type => 'Text', :text => 'This is a test'},
35
+ # :start => {:text => '2010-07-29T14:00:00'},
36
+ # :end => {:text => '2010-07-29T15:00:00'},
37
+ # :is_all_day_event => {:text => 'false'},
38
+ # :location => {:text => 'Room 234'},
39
+ # :required_attendees => {:attendee => {:mailbox => {:email_address => {:text => 'test@test.com'}}}}
40
+ # }
41
+ # @example Minimal Usage
42
+ # item = { :subject => {:text => 'Planning'},
43
+ # :start => {:text => '2010-07-29T14:00:00'},
44
+ # :end => {:text => '2010-07-29T15:00:00'}
45
+ # }
46
+ def self.create_item_from_hash(item, folder_id = :calendar, send_invites = 'SendToAllAndSaveCopy')
47
+ conn = Viewpoint::EWS::EWS.instance
48
+ resp = conn.ews.create_calendar_item(folder_id, item, send_invites)
49
+ if(resp.status == 'Success')
50
+ resp = resp.items.shift
51
+ self.new(resp[resp.keys.first])
52
+ else
53
+ raise EwsError, "Could not create CalendarItem. #{resp.code}: #{resp.message}"
54
+ end
55
+ end
56
+
57
+ # Create a new CalendarItem.
58
+ # @param [DateTime] v_start The date and time when the CalendarItem begins
59
+ # @param [DateTime] v_end The date and time when the CalendarItem ends
60
+ # @param [String] subject The subject of this Item
61
+ # @param [String,optional] body The body of this object
62
+ # @param [String,optional] location The location where this calendar item will ocurr
63
+ # @param [Array<String>,optional] required_attendees An Array of e-mail addresses of required attendees
64
+ # @param [Array<String>,optional] optional_attendees An Array of e-mail addresses of optional attendees
65
+ # @param [Array<String>,optional] resources An Array of e-mail addresses of resources
66
+ def self.create_item(v_start, v_end, subject, body = nil, location = nil, required_attendees=[], optional_attendees=[], resources=[])
67
+ item = {}
68
+ item[:start] = {:text => v_start.to_s}
69
+ item[:end] = {:text => v_end.to_s}
70
+ item[:subject] = {:text => subject}
71
+ item[:body] = {:text => body, :body_type => 'Text'} unless body.nil?
72
+ item[:location] = {:text => location} unless location.nil?
73
+ required_attendees.each do |a|
74
+ item[:required_attendees] = [] unless item[:required_attendees].is_a?(Array)
75
+ item[:required_attendees] << {:attendee => {:mailbox => {:email_address => {:text => a}}}}
76
+ end
77
+ optional_attendees.each do |a|
78
+ item[:optional_attendees] = [] unless item[:optional_attendees].is_a?(Array)
79
+ item[:optional_attendees] << {:attendee => {:mailbox => {:email_address => {:text => a}}}}
80
+ end
81
+ resources.each do |a|
82
+ item[:resources] = [] unless item[:resources].is_a?(Array)
83
+ item[:resources] << {:attendee => {:mailbox => {:email_address => {:text => a}}}}
84
+ end
85
+ puts item
86
+ self.create_item_from_hash(item)
87
+ end
88
+
89
+ # Initialize an Exchange Web Services item of type CalendarItem
90
+ def initialize(ews_item)
91
+ super(ews_item)
92
+ end
93
+
94
+ # Delete this item
95
+ # @param [Boolean] soft Whether or not to do a soft delete. By default EWS will do a
96
+ # hard delete of this item. See the MSDN docs for more info:
97
+ # http://msdn.microsoft.com/en-us/library/aa562961.aspx
98
+ # @param [String] cancel_type "SendToNone/SendOnlyToAll/SendToAllAndSaveCopy"
99
+ # Default is SendOnlyToAll
100
+ # @return [Boolean] Whether or not the item was deleted
101
+ # @todo Add exception handling for failed deletes
102
+ #
103
+ def delete!(soft=false, cancel_type='SendOnlyToAll')
104
+ deltype = soft ? 'SoftDelete' : 'HardDelete'
105
+ resp = (Viewpoint::EWS::EWS.instance).ews.delete_item([@item_id], deltype, cancel_type)
106
+ self.clear_object!
107
+ resp.status == 'Success'
108
+ end
109
+
110
+ # Delete this item by moving it to the Deleted Items folder
111
+ # @see http://msdn.microsoft.com/en-us/library/aa562961.aspx
112
+ # @return [Boolean] Whether or not the item was deleted
113
+ # @todo Add exception handling for failed deletes
114
+ def recycle!(cancel_type='SendOnlyToAll')
115
+ resp = (Viewpoint::EWS::EWS.instance).ews.delete_item([@item_id], 'MoveToDeletedItems', cancel_type)
116
+ self.clear_object!
117
+ resp.status == 'Success'
118
+ end
119
+
120
+
121
+
122
+ private
123
+
124
+ def init_methods
125
+ super
126
+ define_str_var :calendar_item_type, :duration, :time_zone, :when, :location
127
+ define_str_var :legacy_free_busy_status, :my_response_type, :meeting_workspace_url, :net_show_url
128
+ define_int_var :adjacent_meeting_count, :appointment_sequence_number, :appointment_state
129
+ define_int_var :conference_type, :conflicting_meeting_count
130
+ define_mbox_user :organizer
131
+ define_bool_var :is_all_day_event, :is_cancelled, :is_meeting, :is_online_meeting, :is_recurring
132
+ define_bool_var :allow_new_time_proposal, :meeting_request_was_sent
133
+ define_datetime_var :appointment_reply_time, :start, :end, :original_start
134
+
135
+ # @todo Handle:
136
+ # <AdjacentMeetings/> <ConflictingMeetings/> <DeletedOccurrences/>
137
+ # <FirstOccurrence/> <LastOccurrence/> <ModifiedOccurrences/>
138
+ # <StartTimeZone/> <EndTimeZone/> <MeetingTimeZone/>
139
+ # <OptionalAttendees/> <RequiredAttendees/> <Resources/>
140
+ # <Recurrence/>
141
+ end
142
+
143
+ end # CalendarItem
144
+ end # EWS
145
+ end # Viewpoint