viewpoint 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
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')