viewpoint 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. data/TODO +2 -0
  2. data/VERSION +1 -1
  3. data/lib/model/generic_folder.rb +34 -1
  4. data/lib/model/item.rb +51 -3
  5. data/lib/model/message.rb +30 -7
  6. data/lib/soap/handsoap/builders/ews_build_helpers.rb +39 -14
  7. data/lib/soap/handsoap/ews_service.rb +66 -18
  8. data/lib/soap/handsoap/parsers/ews_parser.rb +38 -0
  9. data/lib/viewpoint.rb +18 -0
  10. data/test/spec/basic_functions.spec +18 -0
  11. data/test/spec/item_tests.spec +43 -0
  12. data/test/spec/spec.opts +7 -0
  13. metadata +5 -50
  14. data/examples/cal2ical.rb +0 -29
  15. data/examples/ews_fusefs.rb +0 -363
  16. data/examples/webclient/.gems +0 -2
  17. data/examples/webclient/README +0 -1
  18. data/examples/webclient/config.ru +0 -26
  19. data/examples/webclient/ews_access_handler.rb +0 -42
  20. data/examples/webclient/public/css/mail.css +0 -33
  21. data/examples/webclient/public/css/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
  22. data/examples/webclient/public/css/smoothness/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
  23. data/examples/webclient/public/css/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
  24. data/examples/webclient/public/css/smoothness/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  25. data/examples/webclient/public/css/smoothness/images/ui-bg_glass_75_dadada_1x400.png +0 -0
  26. data/examples/webclient/public/css/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
  27. data/examples/webclient/public/css/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
  28. data/examples/webclient/public/css/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
  29. data/examples/webclient/public/css/smoothness/images/ui-icons_222222_256x240.png +0 -0
  30. data/examples/webclient/public/css/smoothness/images/ui-icons_2e83ff_256x240.png +0 -0
  31. data/examples/webclient/public/css/smoothness/images/ui-icons_454545_256x240.png +0 -0
  32. data/examples/webclient/public/css/smoothness/images/ui-icons_888888_256x240.png +0 -0
  33. data/examples/webclient/public/css/smoothness/images/ui-icons_cd0a0a_256x240.png +0 -0
  34. data/examples/webclient/public/css/smoothness/jquery-ui-1.7.2.custom.css +0 -406
  35. data/examples/webclient/public/css/ui-lightness/images/ui-bg_diagonals-thick_18_b81900_40x40.png +0 -0
  36. data/examples/webclient/public/css/ui-lightness/images/ui-bg_diagonals-thick_20_666666_40x40.png +0 -0
  37. data/examples/webclient/public/css/ui-lightness/images/ui-bg_flat_10_000000_40x100.png +0 -0
  38. data/examples/webclient/public/css/ui-lightness/images/ui-bg_glass_100_f6f6f6_1x400.png +0 -0
  39. data/examples/webclient/public/css/ui-lightness/images/ui-bg_glass_100_fdf5ce_1x400.png +0 -0
  40. data/examples/webclient/public/css/ui-lightness/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  41. data/examples/webclient/public/css/ui-lightness/images/ui-bg_gloss-wave_35_f6a828_500x100.png +0 -0
  42. data/examples/webclient/public/css/ui-lightness/images/ui-bg_highlight-soft_100_eeeeee_1x100.png +0 -0
  43. data/examples/webclient/public/css/ui-lightness/images/ui-bg_highlight-soft_75_ffe45c_1x100.png +0 -0
  44. data/examples/webclient/public/css/ui-lightness/images/ui-icons_222222_256x240.png +0 -0
  45. data/examples/webclient/public/css/ui-lightness/images/ui-icons_228ef1_256x240.png +0 -0
  46. data/examples/webclient/public/css/ui-lightness/images/ui-icons_ef8c08_256x240.png +0 -0
  47. data/examples/webclient/public/css/ui-lightness/images/ui-icons_ffd27a_256x240.png +0 -0
  48. data/examples/webclient/public/css/ui-lightness/images/ui-icons_ffffff_256x240.png +0 -0
  49. data/examples/webclient/public/css/ui-lightness/jquery-ui-1.7.2.custom.css +0 -406
  50. data/examples/webclient/public/js/jquery-1.3.2.min.js +0 -19
  51. data/examples/webclient/public/js/jquery-ui-1.7.2.custom.min.js +0 -145
  52. data/examples/webclient/viewpoint_web.rb +0 -295
  53. data/examples/webclient/views/_footer.haml +0 -1
  54. data/examples/webclient/views/_header.haml +0 -11
  55. data/examples/webclient/views/_tagline.haml +0 -1
  56. data/examples/webclient/views/index.haml +0 -20
  57. data/examples/webclient/views/layout.haml +0 -42
  58. data/examples/webclient/views/mail.haml +0 -45
  59. data/examples/webclient/views/welcome.haml +0 -0
  60. data/lib/model/task_list.rb +0 -19
data/TODO CHANGED
@@ -4,3 +4,5 @@
4
4
  deepen!
5
5
  else
6
6
  raise the NoMethod error
7
+
8
+ - Clean-up exceptions. There is exception raising in the Model that will never ocurr because it is already being checked for in the Parser
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.0
1
+ 0.1.1
@@ -57,7 +57,7 @@ module Viewpoint
57
57
  # or a FolderId (String)
58
58
  # @param [String] traversal Shallow/Deep/SoftDeleted
59
59
  # @return [Array] Returns an Array of Folder or subclasses of Folder
60
- def self.find_folders(root = :root, traversal = 'Shallow')
60
+ def self.find_folders(root = :msgfolderroot, traversal = 'Shallow')
61
61
  resp = (Viewpoint::EWS::EWS.instance).ews.find_folder( [normalize_id(root)], traversal )
62
62
  if(resp.status == 'Success')
63
63
  folders = []
@@ -71,6 +71,39 @@ module Viewpoint
71
71
  end
72
72
  end
73
73
 
74
+ # Return a list of folder names
75
+ # @return [Array<String>] Return an Array of folder names.
76
+ def self.folder_names
77
+ resp = (Viewpoint::EWS::EWS.instance).ews.find_folder([:msgfolderroot], 'Shallow')
78
+ if(resp.status == 'Success')
79
+ flds = []
80
+ resp.items.each do |f|
81
+ flds << f[f.keys.first][:display_name][:text]
82
+ end
83
+ flds
84
+ else
85
+ raise EwsError, "Could not retrieve folders. #{resp.code}: #{resp.message}"
86
+ end
87
+ end
88
+
89
+ # Gets a folder by name. This name must match the folder name exactly.
90
+ # @param [String] name The name of the folder to fetch.
91
+ def self.get_folder_by_name(name)
92
+ # For now the :field_uRI and :field_uRI_or_constant must be in an Array for Ruby 1.8.7 because Hashes
93
+ # are not positional at insertion until 1.9
94
+ restr = {:restriction =>
95
+ {:is_equal_to =>
96
+ [{:field_uRI => {:field_uRI=>'folder:DisplayName'}}, {:field_uRI_or_constant =>{:constant => {:value=>name}}}]}}
97
+ resp = (Viewpoint::EWS::EWS.instance).ews.find_folder([:msgfolderroot], 'Shallow', {:base_shape => 'Default'}, restr)
98
+ if(resp.status == 'Success')
99
+ f = resp.items.first
100
+ f_type = f.keys.first.to_s.camel_case
101
+ eval "#{f_type}.new(f[f.keys.first])"
102
+ else
103
+ raise EwsError, "Could not retrieve folder. #{resp.code}: #{resp.message}"
104
+ end
105
+ end
106
+
74
107
  attr_accessor :folder_id, :change_key, :parent_id
75
108
  attr_reader :subscription_id, :watermark, :sync_state
76
109
  alias :id :folder_id
data/lib/model/item.rb CHANGED
@@ -39,7 +39,23 @@ module Viewpoint
39
39
  self.new(resp[resp.keys.first])
40
40
  end
41
41
 
42
- attr_reader :item_id, :body_type
42
+ # Add attachments to the passed in ParentId
43
+ # @param [String,Hash] parent_id Either a String ItemId or a Hash ItemId with a ChangeKey
44
+ # @option parent_id [String] :id The Id
45
+ # @option parent_id [String] :change_key The ChangeKey
46
+ # @param [Array<File>] attachments An Array of File objects to read in.
47
+ def self.add_attachments(parent_id, attachments)
48
+ conn = Viewpoint::EWS::EWS.instance
49
+ b64attach = []
50
+ attachments.each do |a|
51
+ b64attach << {:name => {:text =>(File.basename a.path)}, :content => {:text => Base64.encode64(a.read)}}
52
+ end
53
+ resp = conn.ews.create_attachment(parent_id, b64attach)
54
+ (resp.status == 'Success') || (raise EwsError, "Could not create attachments. #{resp.code}: #{resp.message}")
55
+ {:id => resp.items.first[:attachment_id][:root_item_id], :change_key => resp.items.first[:attachment_id][:root_item_change_key]}
56
+ end
57
+
58
+ attr_reader :item_id, :change_key, :body_type
43
59
  alias :id :item_id
44
60
 
45
61
  # Initialize an Exchange Web Services item
@@ -50,6 +66,7 @@ module Viewpoint
50
66
  @ews_item = ews_item
51
67
  @shallow = shallow
52
68
  @item_id = ews_item[:item_id][:id]
69
+ @change_key = ews_item[:item_id][:change_key]
53
70
 
54
71
  init_methods
55
72
  end
@@ -65,6 +82,37 @@ module Viewpoint
65
82
  init_methods
66
83
  end
67
84
 
85
+ # Move this item to a new folder
86
+ # @param [String,Symbol,GenericFolder] new_folder The new folder to move it to. This should
87
+ # be a subclass of GenericFolder, a DistinguishedFolderId (must me a Symbol) or a FolderId (String)
88
+ def move!(new_folder)
89
+ new_folder = new_folder.id if new_folder.kind_of?(GenericFolder)
90
+ resp = (Viewpoint::EWS::EWS.instance).ews.move_item([@item_id], new_folder)
91
+ if(resp.status == 'Success')
92
+ @item_id = resp.items.first[resp.items.first.keys.first][:item_id][:id]
93
+ @change_key = resp.items.first[resp.items.first.keys.first][:item_id][:change_key]
94
+ true
95
+ else
96
+ raise EwsError, "Could not move item. #{resp.code}: #{resp.message}"
97
+ end
98
+ end
99
+
100
+ # Copy this item to a new folder
101
+ # @param [String,Symbol,GenericFolder] new_folder The new folder to move it to. This should
102
+ # be a subclass of GenericFolder, a DistinguishedFolderId (must me a Symbol) or a FolderId (String)
103
+ # @return [Item] The Item object of the copy
104
+ def copy(new_folder)
105
+ new_folder = new_folder.id if new_folder.kind_of?(GenericFolder)
106
+ resp = (Viewpoint::EWS::EWS.instance).ews.copy_item([@item_id], new_folder)
107
+ if(resp.status == 'Success')
108
+ item = resp.items.first
109
+ i_type = item.keys.first.to_s.camel_case
110
+ return(eval "#{i_type}.new(item[item.keys.first])")
111
+ else
112
+ raise EwsError, "Could not copy item. #{resp.code}: #{resp.message}"
113
+ end
114
+ end
115
+
68
116
  # Delete this item
69
117
  # @param [Boolean] soft Whether or not to do a soft delete. By default EWS will do a
70
118
  # hard delete of this item. See the MSDN docs for more info:
@@ -75,7 +123,7 @@ module Viewpoint
75
123
  deltype = soft ? 'SoftDelete' : 'HardDelete'
76
124
  resp = (Viewpoint::EWS::EWS.instance).ews.delete_item([@item_id], deltype)
77
125
  self.clear_object!
78
- resp.status == 'Success'
126
+ (resp.status == 'Success') || (raise EwsError, "Could not delete message. #{resp.code}: #{resp.message}")
79
127
  end
80
128
 
81
129
  # Delete this item by moving it to the Deleted Items folder
@@ -85,7 +133,7 @@ module Viewpoint
85
133
  def recycle!
86
134
  resp = (Viewpoint::EWS::EWS.instance).ews.delete_item([@item_id], 'MoveToDeletedItems')
87
135
  self.clear_object!
88
- resp.status == 'Success'
136
+ (resp.status == 'Success') || (raise EwsError, "Could not recycle message. #{resp.code}: #{resp.message}")
89
137
  end
90
138
 
91
139
  private
data/lib/model/message.rb CHANGED
@@ -29,9 +29,11 @@ module Viewpoint
29
29
  # @param [Array] to_recipients An array of e-mail addresses to send to
30
30
  # @param [Array] cc_recipients An array of e-mail addresses to send to
31
31
  # @param [Array] bcc_recipients An array of e-mail addresses to send to
32
- # @return [true] Returns true on successful send or it raises an error with
33
- # a message stating why the e-mail could not be sent.
34
- def self.send(subject, body, to_recipients, cc_recipients=[], bcc_recipients=[])
32
+ # @param [Array<File>] file_attachments An array of File objects to read data from that
33
+ # will attach to this message.
34
+ # @return [Message,true] Returns true if the message is sent, if draft is true it will return the Message object
35
+ # or it raises an error with a message stating why the e-mail could not be sent.
36
+ def self.send(subject, body, to_recipients, cc_recipients=[], bcc_recipients=[], file_attachments=nil, draft=false)
35
37
  item = {}
36
38
  item[:subject] = {:text => subject}
37
39
  item[:body] = {:text => body, :body_type => 'Text'} unless body.nil?
@@ -42,15 +44,24 @@ module Viewpoint
42
44
  cc_recipients.each do |a|
43
45
  item[:cc_recipients] = [] unless item[:cc_recipients].is_a?(Array)
44
46
  item[:cc_recipients] << {:mailbox => {:email_address => {:text => a}}}
45
- end
47
+ end unless cc_recipients.nil?
46
48
  bcc_recipients.each do |a|
47
49
  item[:bcc_recipients] = [] unless item[:bcc_recipients].is_a?(Array)
48
50
  item[:bcc_recipients] << {:mailbox => {:email_address => {:text => a}}}
49
- end
51
+ end unless bcc_recipients.nil?
50
52
 
51
53
  conn = Viewpoint::EWS::EWS.instance
52
- resp = conn.ews.create_message_item(:sentitems, item, 'SendAndSaveCopy')
53
- (resp.status == 'Success') || (raise EwsError, "Could not retrieve item. #{resp.code}: #{resp.message}")
54
+ resp = conn.ews.create_message_item(:drafts, item, 'SaveOnly')
55
+ (resp.status == 'Success') || (raise EwsError, "Could not send message. #{resp.code}: #{resp.message}")
56
+ msg_key = resp.items.first.keys.first
57
+ msg_id = resp.items.first[msg_key][:item_id]
58
+ msg_id = add_attachments(msg_id, file_attachments) unless file_attachments.nil?
59
+ if !draft
60
+ resp = conn.ews.send_item([msg_id])
61
+ (resp.status == 'Success') || (raise EwsError, "Could not send message. #{resp.code}: #{resp.message}")
62
+ else
63
+ self.new({:item_id => msg_id})
64
+ end
54
65
  end
55
66
 
56
67
  # Initialize an Exchange Web Services item of type Message
@@ -58,6 +69,18 @@ module Viewpoint
58
69
  super(ews_item)
59
70
  end
60
71
 
72
+ def headers
73
+ deepen! if @shallow
74
+ return @headers if defined?(@headers) && !@headers.empty?
75
+ @headers = {}
76
+ # @todo When ruby 1.9 becomes more pervasive the Enumerator#each_with_object
77
+ #@headers ||= @ews_item[:internet_message_headers][:internet_message_header].each_with_object({}) do |h,obj|
78
+ @ews_item[:internet_message_headers][:internet_message_header].each do |h|
79
+ @headers[h[:header_name]] = h[:text]
80
+ end
81
+ @headers
82
+ end
83
+
61
84
  private
62
85
 
63
86
  def init_methods
@@ -52,19 +52,42 @@ module Viewpoint
52
52
  end
53
53
  end
54
54
 
55
-
56
55
  # For now this is the same as folder_ids! so just use that method
57
56
  def parent_folder_ids!(node, folder_ids)
58
57
  folder_ids!(node, folder_ids, nil, "#{NS_EWS_MESSAGES}:ParentFolderIds")
59
58
  end
60
59
 
60
+ # @see http://msdn.microsoft.com/en-us/library/aa565020.aspx
61
+ def to_folder_id!(node, folder_id)
62
+ node.add("#{NS_EWS_MESSAGES}:ToFolderId") do |tfi|
63
+ folder_id!(tfi, folder_id)
64
+ end
65
+ end
61
66
 
67
+ # Create the ItemIds Element
68
+ # @param [Element] node The node we are adding Mailbox elements to.
69
+ # @param [Array] item_ids The item ids to add in.
62
70
  def item_ids!(node, item_ids)
63
71
  node.add("#{NS_EWS_MESSAGES}:ItemIds") do |ids|
64
72
  item_ids.each do |id|
65
- ids.add("#{NS_EWS_TYPES}:ItemId") do |iid|
66
- iid.set_attr('Id',id)
67
- end
73
+ item_id!(ids,id)
74
+ end
75
+ end
76
+ end
77
+
78
+ # Builds an ItemId element out of a String or Hash object
79
+ # @param [Element] node The node we are adding Mailbox elements to.
80
+ # @param [String,Hash] item_id The id of the Item. If this is a Hash
81
+ # it should contain the Id and the ChangeKey.
82
+ # @option item_ids [String] :id The item Id
83
+ # @option item_ids [String] :change_key The ChangeKey
84
+ def item_id!(node, item_id, element_name="#{NS_EWS_TYPES}:ItemId")
85
+ node.add(element_name) do |iid|
86
+ if(item_id.is_a?(String))
87
+ iid.set_attr('Id',item_id)
88
+ else
89
+ iid.set_attr('Id',item_id[:id])
90
+ iid.set_attr('ChangeKey',item_id[:change_key])
68
91
  end
69
92
  end
70
93
  end
@@ -94,19 +117,10 @@ module Viewpoint
94
117
 
95
118
  def saved_item_folder_id!(node, folder_id)
96
119
  node.add("#{NS_EWS_MESSAGES}:SavedItemFolderId") do |sfid|
97
- if( folder_id.is_a?(Symbol) )
98
- # @todo add change_key support to DistinguishedFolderId
99
- sfid.add("#{NS_EWS_TYPES}:DistinguishedFolderId") do |df|
100
- df.set_attr('Id', folder_id.to_s)
101
- end
102
- else
103
- # @todo add change_key support to FolderId
104
- sfid.add("#{NS_EWS_TYPES}:FolderId",folder_id)
105
- end
120
+ folder_id!(sfid, folder_id)
106
121
  end
107
122
  end
108
123
 
109
-
110
124
  # @todo This only supports the FieldURI extended property right now
111
125
  def folder_shape!(node, folder_shape)
112
126
  node.add("#{NS_EWS_MESSAGES}:FolderShape") do |fshape|
@@ -284,6 +298,17 @@ module Viewpoint
284
298
  node.add("#{NS_EWS_MESSAGES}:SyncState", sync_state)
285
299
  end
286
300
 
301
+ # @todo Add support of ItemAttachment
302
+ def attachments!(node, files, items)
303
+ node.add("#{NS_EWS_MESSAGES}:Attachments") do |att|
304
+ files.each do |f|
305
+ att.add("#{NS_EWS_TYPES}:FileAttachment") do |fatt|
306
+ add_hierarchy!(fatt, f)
307
+ end
308
+ end
309
+ end
310
+ end
311
+
287
312
  # Add a hierarchy of elements from hash data
288
313
  # @example Hash to XML
289
314
  # {:this => {:text =>'that'},'top' => {:id => '32fss', :text => 'TestText', {'middle' => 'bottom'}}}
@@ -29,6 +29,7 @@ module Viewpoint
29
29
  module EWS
30
30
  module SOAP
31
31
  class ExchangeWebService < Handsoap::Service
32
+ include Viewpoint::EWS::SOAP
32
33
 
33
34
  SOAP_ACTION_PREFIX = "http://schemas.microsoft.com/exchange/services/2006/messages"
34
35
 
@@ -133,8 +134,12 @@ module Viewpoint
133
134
  action = "#{SOAP_ACTION_PREFIX}/FindFolder"
134
135
  resp = invoke("#{NS_EWS_MESSAGES}:FindFolder", :soap_action => action) do |root|
135
136
  build!(root) do
137
+ restriction = opts.delete(:restriction)
136
138
  root.set_attr('Traversal', traversal)
137
139
  folder_shape!(root, folder_shape)
140
+ root.add("#{NS_EWS_MESSAGES}:Restriction") do |r|
141
+ add_hierarchy!(r, restriction)
142
+ end unless restriction.nil?
138
143
  parent_folder_ids!(root, parent_folder_ids)
139
144
  end
140
145
  end
@@ -245,8 +250,8 @@ module Viewpoint
245
250
  def delete_folder(folder_id, delete_type = 'MoveToDeletedItems')
246
251
  action = "#{SOAP_ACTION_PREFIX}/DeleteFolder"
247
252
  resp = invoke("#{NS_EWS_MESSAGES}:DeleteFolder", :soap_action => action) do |root|
248
- root.set_attr('DeleteType', delete_type)
249
253
  build!(root) do
254
+ root.set_attr('DeleteType', delete_type)
250
255
  folder_id = (folder_id.is_a?(Array)) ? folder_id : [folder_id]
251
256
  folder_ids!(root, folder_id)
252
257
  end
@@ -481,36 +486,77 @@ module Viewpoint
481
486
  parse_update_item(resp)
482
487
  end
483
488
 
484
- def send_item
489
+ # Used to send e-mail messages that are located in the Exchange store.
490
+ # @see http://msdn.microsoft.com/en-us/library/aa580238.aspx
491
+ # @param [Array<Hash>] item_ids An Array of item ids. These item_ids should be a Hash of
492
+ # :id and :change_key.
493
+ # @param [Boolean] save_item Save item after sending (Think sent-items)
494
+ # @param [String, Symbol,nil] saved_item_folder The folder to save this item in. Either a
495
+ # DistinguishedFolderId (must me a Symbol) or a FolderId (String). Just leave
496
+ # it blank for the default :sentitems
497
+ def send_item(item_ids, save_item=true, saved_item_folder=nil)
485
498
  action = "#{SOAP_ACTION_PREFIX}/SendItem"
486
- resp = invoke("#{NS_EWS_MESSAGES}:SendItem", :soap_action => action) do |send_item|
487
- build_send_item!(send_item)
499
+ resp = invoke("#{NS_EWS_MESSAGES}:SendItem", :soap_action => action) do |root|
500
+ build!(root) do
501
+ root.set_attr('SaveItemToFolder', save_item)
502
+ item_ids!(root,item_ids)
503
+ saved_item_folder_id!(root,saved_item_folder) unless saved_item_folder.nil?
504
+ end
488
505
  end
489
- parse_send_item(resp)
506
+ parse!(resp)
490
507
  end
491
508
 
492
- def move_item
509
+ # Used to move one or more items to a single destination folder.
510
+ # @see http://msdn.microsoft.com/en-us/library/aa565781.aspx
511
+ # @param [Array] item_ids An Array of item ids
512
+ # @param [String, Symbol] folder_id either a DistinguishedFolderId
513
+ # (must me a Symbol) or a FolderId (String)
514
+ def move_item(item_ids, folder_id)
493
515
  action = "#{SOAP_ACTION_PREFIX}/MoveItem"
494
- resp = invoke("#{NS_EWS_MESSAGES}:MoveItem", :soap_action => action) do |move_item|
495
- build_move_item!(move_item)
516
+ resp = invoke("#{NS_EWS_MESSAGES}:MoveItem", :soap_action => action) do |root|
517
+ build!(root) do
518
+ to_folder_id!(root, folder_id)
519
+ item_ids!(root, item_ids)
520
+ end
496
521
  end
497
- parse_move_item(resp)
522
+ parse!(resp)
498
523
  end
499
524
 
500
- def copy_item
525
+ # Copies items and puts the items in a different folder
526
+ # @see http://msdn.microsoft.com/en-us/library/aa565012.aspx
527
+ # @param [Array] item_ids An Array of item ids
528
+ # @param [String, Symbol] folder_id either a DistinguishedFolderId
529
+ # (must me a Symbol) or a FolderId (String)
530
+ def copy_item(item_ids, folder_id)
501
531
  action = "#{SOAP_ACTION_PREFIX}/CopyItem"
502
- resp = invoke("#{NS_EWS_MESSAGES}:CopyItem", :soap_action => action) do |copy_item|
503
- build_copy_item!(copy_item)
532
+ resp = invoke("#{NS_EWS_MESSAGES}:CopyItem", :soap_action => action) do |root|
533
+ build!(root) do
534
+ to_folder_id!(root, folder_id)
535
+ item_ids!(root, item_ids)
536
+ end
504
537
  end
505
- parse_copy_item(resp)
538
+ parse!(resp)
506
539
  end
507
540
 
508
- def create_attachment
541
+ # Creates either an item or file attachment and attaches it to the specified item.
542
+ # @see http://msdn.microsoft.com/en-us/library/aa565877.aspx
543
+ # @param [String,Hash] parent_id The id of the Item. If this is a Hash
544
+ # it should contain the Id and the ChangeKey.
545
+ # @option parent_id [String] :id The item Id
546
+ # @option parent_id [String] :change_key The ChangeKey
547
+ # @param [Array<Hash>] files An Array of Base64 encoded Strings with an associated name
548
+ # hash format= :name => <name>, :content => <Base64 encoded string>
549
+ # @param [Array] items Exchange Items to attach to this Item
550
+ # @todo Need to implement attachment of Item types
551
+ def create_attachment(parent_id, files = [], items = [])
509
552
  action = "#{SOAP_ACTION_PREFIX}/CreateAttachment"
510
- resp = invoke("#{NS_EWS_MESSAGES}:CreateAttachment", :soap_action => action) do |create_attachment|
511
- build_create_attachment!(create_attachment)
553
+ resp = invoke("#{NS_EWS_MESSAGES}:CreateAttachment", :soap_action => action) do |root|
554
+ build!(root) do
555
+ item_id!(root, parent_id, "#{NS_EWS_MESSAGES}:ParentItemId")
556
+ attachments!(root, files, items)
557
+ end
512
558
  end
513
- parse_create_attachment(resp)
559
+ parse!(resp)
514
560
  end
515
561
 
516
562
  def delete_attachment
@@ -601,6 +647,9 @@ module Viewpoint
601
647
  parse!(resp)
602
648
  end
603
649
 
650
+ # Provides detailed information about the availability of a set of users, rooms, and resources
651
+ # within a specified time window.
652
+ # @see http://msdn.microsoft.com/en-us/library/aa564001.aspx
604
653
  def get_user_availability
605
654
  action = "#{SOAP_ACTION_PREFIX}/GetUserAvailability"
606
655
  resp = invoke("#{NS_EWS_MESSAGES}:GetUserAvailability", :soap_action => action) do |get_user_availability|
@@ -630,7 +679,6 @@ module Viewpoint
630
679
  # Private Methods (Builders and Parsers)
631
680
  private
632
681
 
633
-
634
682
  def build!(node, opts = {}, &block)
635
683
  EwsBuilder.new(node, opts, &block)
636
684
  end
@@ -99,6 +99,22 @@ module Viewpoint
99
99
  end
100
100
  end
101
101
 
102
+ def copy_item_response(opts)
103
+ if(@response_message.status == 'Success')
104
+ @response_message.items << xml_to_hash!((@response/"//#{NS_EWS_MESSAGES}:Items/*").first.native_element)
105
+ else
106
+ raise EwsError, "#{@response_message.code}: #{@response_message.message}"
107
+ end
108
+ end
109
+
110
+ def move_item_response(opts)
111
+ if(@response_message.status == 'Success')
112
+ @response_message.items << xml_to_hash!((@response/"//#{NS_EWS_MESSAGES}:Items/*").first.native_element)
113
+ else
114
+ raise EwsError, "#{@response_message.code}: #{@response_message.message}"
115
+ end
116
+ end
117
+
102
118
  # @todo need to find out out to us XPath to get ItemId. It doesn't seem to work now.
103
119
  def create_item_response(opts)
104
120
  if(@response_message.status == 'Success')
@@ -111,6 +127,28 @@ module Viewpoint
111
127
  raise EwsError, "#{@response_message.code}: #{@response_message.message}"
112
128
  end
113
129
  end
130
+
131
+ def send_item_response(opts)
132
+ if(@response_message.status == 'Success')
133
+ items = []
134
+ (@response/"//#{NS_EWS_MESSAGES}:Items/*").each do |i|
135
+ items << xml_to_hash!(i.native_element)
136
+ end
137
+ @response_message.items = items
138
+ else
139
+ raise EwsError, "#{@response_message.code}: #{@response_message.message}"
140
+ end
141
+ end
142
+
143
+ def create_attachment_response(opts)
144
+ if(@response_message.status == 'Success')
145
+ att_id = (@response/"//#{NS_EWS_TYPES}:FileAttachment/*").last
146
+ att_id = xml_to_hash!(att_id.native_element)
147
+ @response_message.items = [att_id]
148
+ else
149
+ raise EwsError, "#{@response_message.code}: #{@response_message.message}"
150
+ end
151
+ end
114
152
 
115
153
  def sync_folder_items_response(opts)
116
154
  if(@response_message.status == 'Success')