viewpoint 0.1.2 → 0.1.3
Sign up to get free protection for your applications and to get access to all the features.
- data/README +2 -0
- data/Rakefile +9 -0
- data/TODO +2 -0
- data/VERSION +1 -1
- data/lib/exceptions/exceptions.rb +4 -0
- data/lib/model/attachment.rb +33 -0
- data/lib/model/calendar_folder.rb +24 -0
- data/lib/model/calendar_item.rb +0 -1
- data/lib/model/file_attachment.rb +54 -0
- data/lib/model/folder.rb +24 -0
- data/lib/model/generic_folder.rb +5 -5
- data/lib/model/item.rb +27 -1
- data/lib/model/item_attachment.rb +34 -0
- data/lib/model/mailbox_user.rb +13 -0
- data/lib/model/task.rb +31 -0
- data/lib/model/tasks_folder.rb +25 -0
- data/lib/soap/handsoap/builders/ews_build_helpers.rb +12 -0
- data/lib/soap/handsoap/builders/ews_builder.rb +11 -0
- data/lib/soap/handsoap/ews_service.rb +62 -14
- data/lib/soap/handsoap/parser.rb +1 -2
- data/lib/soap/handsoap/parsers/ews_parser.rb +17 -0
- data/lib/soap/soap_provider.rb +0 -7
- data/lib/viewpoint.rb +3 -0
- data/test/{spec/spec.opts → .rspec} +0 -0
- metadata +7 -4
data/README
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
--------------------------------------------------------------------------
|
2
2
|
Viewpoint for Exchange Web Services
|
3
|
+
http://github.com/zenchild/Viewpoint/wiki
|
3
4
|
--------------------------------------------------------------------------
|
4
5
|
This program attempts to create a client access library for Exchange Web
|
5
6
|
Services (EWS) in Ruby.
|
@@ -14,6 +15,7 @@ them or they are asked for.
|
|
14
15
|
|
15
16
|
BLOG: http://distributed-frostbite.blogspot.com/
|
16
17
|
Add me in LinkedIn: http://www.linkedin.com/in/danwanek
|
18
|
+
Find me on irc.freenode.net in #ruby-lang (zenChild)
|
17
19
|
|
18
20
|
--------------------------------------------------------------------------
|
19
21
|
MAJOR CHANGES TO THE FIRST VERSION:
|
data/Rakefile
CHANGED
@@ -2,6 +2,7 @@ require 'rubygems'
|
|
2
2
|
require 'rake/clean'
|
3
3
|
require 'rake/gempackagetask'
|
4
4
|
require 'date'
|
5
|
+
require 'metric_fu'
|
5
6
|
|
6
7
|
CLEAN.include("pkg")
|
7
8
|
CLEAN.include("doc")
|
@@ -67,3 +68,11 @@ def up_min_version
|
|
67
68
|
f.write(ver)
|
68
69
|
ver
|
69
70
|
end
|
71
|
+
|
72
|
+
MetricFu::Configuration.run do |config|
|
73
|
+
#define which metrics you want to use
|
74
|
+
# config.metrics = [:churn, :saikuro, :stats, :flog, :flay]
|
75
|
+
config.metrics = [:flog, :flay]
|
76
|
+
config.graphs = [:flog, :flay]
|
77
|
+
end
|
78
|
+
|
data/TODO
CHANGED
@@ -6,3 +6,5 @@
|
|
6
6
|
raise the NoMethod error
|
7
7
|
|
8
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
|
9
|
+
|
10
|
+
- Refactor #find_folders methods. There is a lot of duplicate code right now and it could be simplified quite a bit.
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.1.
|
1
|
+
0.1.3
|
@@ -0,0 +1,33 @@
|
|
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
|
+
# A generic Attachment. This class should not be instantiated directly. You
|
24
|
+
# should use one of the subclasses like FileAttachment or ItemAttachment.
|
25
|
+
class Attachment
|
26
|
+
include Model
|
27
|
+
|
28
|
+
# All Attachment types will have an id.
|
29
|
+
attr_reader :id
|
30
|
+
|
31
|
+
end # Attachment
|
32
|
+
end # EWS
|
33
|
+
end # Viewpoint
|
@@ -22,6 +22,30 @@ module Viewpoint
|
|
22
22
|
module EWS
|
23
23
|
class CalendarFolder < GenericFolder
|
24
24
|
|
25
|
+
# Find Calendar subfolders of the passed root folder. If no parameters are passed
|
26
|
+
# this method will search from the Root folder.
|
27
|
+
# @param [Str] root An folder id, either a DistinguishedFolderId (must me a Symbol)
|
28
|
+
# or a FolderId (String)
|
29
|
+
# @param [String] traversal Shallow/Deep/SoftDeleted
|
30
|
+
# @return [Array] Returns an Array of Folder or subclasses of Folder
|
31
|
+
def self.find_folders(root = :msgfolderroot, traversal = 'Deep', shape = 'Default')
|
32
|
+
restr = {:restriction =>
|
33
|
+
{:is_equal_to => {:field_uRI => {:field_uRI=>'folder:FolderClass'},:field_uRI_or_constant=>{:constant => {:value => 'IPF.Appointment'}}}}
|
34
|
+
}
|
35
|
+
resp = (Viewpoint::EWS::EWS.instance).ews.find_folder( [normalize_id(root)], traversal, {:base_shape => shape}, restr)
|
36
|
+
if(resp.status == 'Success')
|
37
|
+
folders = []
|
38
|
+
resp.items.each do |f|
|
39
|
+
f_type = f.keys.first.to_s.camel_case
|
40
|
+
folders << (eval "#{f_type}.new(f[f.keys.first])")
|
41
|
+
end
|
42
|
+
return folders
|
43
|
+
else
|
44
|
+
raise EwsError, "Could not retrieve folders. #{resp.code}: #{resp.message}"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
|
25
49
|
# initialize with an item of CalendarFolderType
|
26
50
|
def initialize(folder)
|
27
51
|
super(folder)
|
data/lib/model/calendar_item.rb
CHANGED
@@ -0,0 +1,54 @@
|
|
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
|
+
# This class represents a file attachment item. You can save this object
|
24
|
+
# to a file withthe #save_to_file method.
|
25
|
+
class FileAttachment < Attachment
|
26
|
+
|
27
|
+
# @param [String] attachment_id The unique ID for the attachment.
|
28
|
+
def initialize(attachment_id)
|
29
|
+
@id = attachment_id
|
30
|
+
conn = Viewpoint::EWS::EWS.instance
|
31
|
+
resp = conn.ews.get_attachment([attachment_id])
|
32
|
+
@file_name = resp.items.first[:file_attachment][:name][:text]
|
33
|
+
|
34
|
+
# content in Base64
|
35
|
+
@content = resp.items.first[:file_attachment][:content][:text]
|
36
|
+
end
|
37
|
+
|
38
|
+
# Save this FileAttachment object to a file. By default it saves
|
39
|
+
# it to the original file's name in the current working directory.
|
40
|
+
# @param [String,nil] base_dir the directory to save the file to. Pass nil if you
|
41
|
+
# do not want to specify a directory or you are passing a full path name to file_name
|
42
|
+
# @param [String] file_name The name of the file to save the content to.
|
43
|
+
# Leave this blank to use the default attachment name.
|
44
|
+
def save_to_file(base_dir = nil, file_name = @file_name)
|
45
|
+
base_dir << '/' unless(base_dir.nil? or base_dir.end_with?('/'))
|
46
|
+
File.open("#{base_dir}#{file_name}", 'w+') do |f|
|
47
|
+
f.write(Base64.decode64(@content))
|
48
|
+
end
|
49
|
+
true
|
50
|
+
end
|
51
|
+
|
52
|
+
end # FileAttachment
|
53
|
+
end # EWS
|
54
|
+
end # Viewpoint
|
data/lib/model/folder.rb
CHANGED
@@ -24,6 +24,30 @@ module Viewpoint
|
|
24
24
|
# This is the type of folder that mail messages will be found in.
|
25
25
|
class Folder < GenericFolder
|
26
26
|
|
27
|
+
# Find Message subfolders of the passed root folder. If no parameters are passed
|
28
|
+
# this method will search from the Root folder.
|
29
|
+
# @param [Str] root An folder id, either a DistinguishedFolderId (must me a Symbol)
|
30
|
+
# or a FolderId (String)
|
31
|
+
# @param [String] traversal Shallow/Deep/SoftDeleted
|
32
|
+
# @return [Array] Returns an Array of Folder or subclasses of Folder
|
33
|
+
def self.find_folders(root = :msgfolderroot, traversal = 'Deep', shape = 'Default')
|
34
|
+
restr = {:restriction =>
|
35
|
+
{:is_equal_to => {:field_uRI => {:field_uRI=>'folder:FolderClass'},:field_uRI_or_constant=>{:constant => {:value => 'IPF.Note'}}}}
|
36
|
+
}
|
37
|
+
resp = (Viewpoint::EWS::EWS.instance).ews.find_folder( [normalize_id(root)], traversal, {:base_shape => shape}, restr)
|
38
|
+
if(resp.status == 'Success')
|
39
|
+
folders = []
|
40
|
+
resp.items.each do |f|
|
41
|
+
f_type = f.keys.first.to_s.camel_case
|
42
|
+
folders << (eval "#{f_type}.new(f[f.keys.first])")
|
43
|
+
end
|
44
|
+
return folders
|
45
|
+
else
|
46
|
+
raise EwsError, "Could not retrieve folders. #{resp.code}: #{resp.message}"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
|
27
51
|
# Initialize with an item of FolderType. This is typically the folder
|
28
52
|
# used to house mail messages.
|
29
53
|
def initialize(folder)
|
data/lib/model/generic_folder.rb
CHANGED
@@ -53,12 +53,12 @@ module Viewpoint
|
|
53
53
|
|
54
54
|
# Find subfolders of the passed root folder. If no parameters are passed
|
55
55
|
# this method will search from the Root folder.
|
56
|
-
# @param [
|
56
|
+
# @param [String,Symbol] root An folder id, either a DistinguishedFolderId (must me a Symbol)
|
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 = :msgfolderroot, traversal = 'Shallow')
|
61
|
-
resp = (Viewpoint::EWS::EWS.instance).ews.find_folder( [normalize_id(root)], traversal )
|
60
|
+
def self.find_folders(root = :msgfolderroot, traversal = 'Shallow', shape = 'Default')
|
61
|
+
resp = (Viewpoint::EWS::EWS.instance).ews.find_folder( [normalize_id(root)], traversal, {:base_shape => shape} )
|
62
62
|
if(resp.status == 'Success')
|
63
63
|
folders = []
|
64
64
|
resp.items.each do |f|
|
@@ -88,13 +88,13 @@ module Viewpoint
|
|
88
88
|
|
89
89
|
# Gets a folder by name. This name must match the folder name exactly.
|
90
90
|
# @param [String] name The name of the folder to fetch.
|
91
|
-
def self.get_folder_by_name(name)
|
91
|
+
def self.get_folder_by_name(name, shape = 'Default')
|
92
92
|
# For now the :field_uRI and :field_uRI_or_constant must be in an Array for Ruby 1.8.7 because Hashes
|
93
93
|
# are not positional at insertion until 1.9
|
94
94
|
restr = {:restriction =>
|
95
95
|
{:is_equal_to =>
|
96
96
|
[{:field_uRI => {:field_uRI=>'folder:DisplayName'}}, {:field_uRI_or_constant =>{:constant => {:value=>name}}}]}}
|
97
|
-
resp = (Viewpoint::EWS::EWS.instance).ews.find_folder([:msgfolderroot], '
|
97
|
+
resp = (Viewpoint::EWS::EWS.instance).ews.find_folder([:msgfolderroot], 'Deep', {:base_shape => shape}, restr)
|
98
98
|
if(resp.status == 'Success')
|
99
99
|
f = resp.items.first
|
100
100
|
f_type = f.keys.first.to_s.camel_case
|
data/lib/model/item.rb
CHANGED
@@ -72,6 +72,7 @@ module Viewpoint
|
|
72
72
|
end
|
73
73
|
|
74
74
|
def deepen!
|
75
|
+
return true unless @shallow
|
75
76
|
conn = Viewpoint::EWS::EWS.instance
|
76
77
|
resp = conn.ews.get_item([@item_id], {:base_shape => 'AllProperties'})
|
77
78
|
resp = resp.items.shift
|
@@ -80,6 +81,7 @@ module Viewpoint
|
|
80
81
|
@ews_methods = []
|
81
82
|
@ews_methods_undef = []
|
82
83
|
init_methods
|
84
|
+
true
|
83
85
|
end
|
84
86
|
|
85
87
|
# Move this item to a new folder
|
@@ -113,6 +115,25 @@ module Viewpoint
|
|
113
115
|
end
|
114
116
|
end
|
115
117
|
|
118
|
+
# Return the attachments for this Item
|
119
|
+
# @return [Array,Attachment] An array of Attachments for this Item
|
120
|
+
def attachments
|
121
|
+
return [] unless has_attachments?
|
122
|
+
deepen!
|
123
|
+
attmts = []
|
124
|
+
@ews_item[:attachments].each_pair do |k,v|
|
125
|
+
# k should be file_attachment or item_attachment
|
126
|
+
if(v.is_a?(Hash))
|
127
|
+
attmts << (eval "#{k.to_s.camel_case}.new(v[:attachment_id][:id])")
|
128
|
+
else
|
129
|
+
v.each do |att|
|
130
|
+
attmts << (eval "#{k.to_s.camel_case}.new(att[:attachment_id][:id])")
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
attmts
|
135
|
+
end
|
136
|
+
|
116
137
|
# Delete this item
|
117
138
|
# @param [Boolean] soft Whether or not to do a soft delete. By default EWS will do a
|
118
139
|
# hard delete of this item. See the MSDN docs for more info:
|
@@ -166,7 +187,12 @@ module Viewpoint
|
|
166
187
|
end
|
167
188
|
|
168
189
|
def method_missing(m, *args, &block)
|
169
|
-
|
190
|
+
if(@shallow)
|
191
|
+
deepen!
|
192
|
+
send(m, *args, &block)
|
193
|
+
else
|
194
|
+
warn "!!! No such method: #{m}"
|
195
|
+
end
|
170
196
|
end
|
171
197
|
|
172
198
|
end # Item
|
@@ -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
|
+
|
21
|
+
module Viewpoint
|
22
|
+
module EWS
|
23
|
+
# An attachment that represents an attachment to another Exchange Item.
|
24
|
+
# This is not yet implemented.
|
25
|
+
class ItemAttachment < Attachment
|
26
|
+
|
27
|
+
# @param [String] attachment_id The unique ID for the attachment.
|
28
|
+
def initialize(attachment_id)
|
29
|
+
raise EwsNotImplemented, "ItemAttachments are not yet implemented in Viewpoint"
|
30
|
+
end
|
31
|
+
|
32
|
+
end # ItemAttachment
|
33
|
+
end # EWS
|
34
|
+
end # Viewpoint
|
data/lib/model/mailbox_user.rb
CHANGED
@@ -52,6 +52,19 @@ module Viewpoint
|
|
52
52
|
@ews_item = mbox_user
|
53
53
|
define_str_var :name, :email_address, :routing_type, :mailbox_type, :item_id
|
54
54
|
end
|
55
|
+
|
56
|
+
def get_oof
|
57
|
+
mailbox = {:mailbox => {:address => {:text => email_address}}}
|
58
|
+
resp = (Viewpoint::EWS::EWS.instance).ews.get_user_oof_settings(mailbox)
|
59
|
+
s = resp[:oof_settings]
|
60
|
+
@oof_state = s[:oof_state][:text]
|
61
|
+
@oof_ext_audience = s[:external_audience][:text]
|
62
|
+
@oof_start = DateTime.parse(s[:duration][:start_time][:text])
|
63
|
+
@oof_end = DateTime.parse(s[:duration][:end_time][:text])
|
64
|
+
@oof_internal_reply = s[:internal_reply][:message][:text]
|
65
|
+
@oof_external_reply = s[:internal_reply][:message][:text]
|
66
|
+
true
|
67
|
+
end
|
55
68
|
|
56
69
|
# Adds one or more delegates to a principal's mailbox and sets specific access permissions
|
57
70
|
# @see http://msdn.microsoft.com/en-us/library/bb856527.aspx
|
data/lib/model/task.rb
CHANGED
@@ -51,6 +51,37 @@ module Viewpoint
|
|
51
51
|
super(ews_item)
|
52
52
|
end
|
53
53
|
|
54
|
+
# Delete this item
|
55
|
+
# @param [Boolean] soft Whether or not to do a soft delete. By default EWS will do a
|
56
|
+
# hard delete of this item. See the MSDN docs for more info:
|
57
|
+
# http://msdn.microsoft.com/en-us/library/aa562961.aspx
|
58
|
+
# @param [String, nil] affected_task_occurrences "AllOccurrences/SpecifiedOccurrenceOnly"
|
59
|
+
# Default is AllOccurrences
|
60
|
+
# If you use 'SpecifiedOccurrenceOnly' on a non-reocurring task you will receive and error.
|
61
|
+
# @return [Boolean] Whether or not the item was deleted
|
62
|
+
# @todo Add exception handling for failed deletes
|
63
|
+
#
|
64
|
+
def delete!(soft=false, affected_task_occurrences='AllOccurrences')
|
65
|
+
deltype = soft ? 'SoftDelete' : 'HardDelete'
|
66
|
+
resp = (Viewpoint::EWS::EWS.instance).ews.delete_item([@item_id], deltype, nil, affected_task_occurrences)
|
67
|
+
self.clear_object!
|
68
|
+
resp.status == 'Success'
|
69
|
+
end
|
70
|
+
|
71
|
+
# Delete this item by moving it to the Deleted Items folder
|
72
|
+
# @see http://msdn.microsoft.com/en-us/library/aa562961.aspx
|
73
|
+
# @param [String, nil] affected_task_occurrences "AllOccurrences/SpecifiedOccurrenceOnly"
|
74
|
+
# Default is AllOccurrences
|
75
|
+
# If you use 'SpecifiedOccurrenceOnly' on a non-reocurring task you will receive and error.
|
76
|
+
# @return [Boolean] Whether or not the item was deleted
|
77
|
+
# @todo Add exception handling for failed deletes
|
78
|
+
def recycle!(affected_task_occurrences='AllOccurrences')
|
79
|
+
resp = (Viewpoint::EWS::EWS.instance).ews.delete_item([@item_id], 'MoveToDeletedItems', nil, affected_task_occurrences)
|
80
|
+
self.clear_object!
|
81
|
+
resp.status == 'Success'
|
82
|
+
end
|
83
|
+
|
84
|
+
|
54
85
|
private
|
55
86
|
|
56
87
|
def init_methods
|
data/lib/model/tasks_folder.rb
CHANGED
@@ -22,6 +22,31 @@ module Viewpoint
|
|
22
22
|
module EWS
|
23
23
|
# This class represents a TaskFolderType object in the Exchange Data store.
|
24
24
|
class TasksFolder < GenericFolder
|
25
|
+
|
26
|
+
# Find Task subfolders of the passed root folder. If no parameters are passed
|
27
|
+
# this method will search from the Root folder.
|
28
|
+
# @param [Str] root An folder id, either a DistinguishedFolderId (must me a Symbol)
|
29
|
+
# or a FolderId (String)
|
30
|
+
# @param [String] traversal Shallow/Deep/SoftDeleted
|
31
|
+
# @return [Array] Returns an Array of Folder or subclasses of Folder
|
32
|
+
def self.find_folders(root = :msgfolderroot, traversal = 'Deep', shape = 'Default')
|
33
|
+
restr = {:restriction =>
|
34
|
+
{:is_equal_to => {:field_uRI => {:field_uRI=>'folder:FolderClass'},:field_uRI_or_constant=>{:constant => {:value => 'IPF.Task'}}}}
|
35
|
+
}
|
36
|
+
resp = (Viewpoint::EWS::EWS.instance).ews.find_folder( [normalize_id(root)], traversal, {:base_shape => shape}, restr)
|
37
|
+
if(resp.status == 'Success')
|
38
|
+
folders = []
|
39
|
+
resp.items.each do |f|
|
40
|
+
f_type = f.keys.first.to_s.camel_case
|
41
|
+
folders << (eval "#{f_type}.new(f[f.keys.first])")
|
42
|
+
end
|
43
|
+
return folders
|
44
|
+
else
|
45
|
+
raise EwsError, "Could not retrieve folders. #{resp.code}: #{resp.message}"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
|
25
50
|
|
26
51
|
def initialize(folder)
|
27
52
|
super(folder)
|
@@ -308,6 +308,18 @@ module Viewpoint
|
|
308
308
|
end
|
309
309
|
end
|
310
310
|
end
|
311
|
+
|
312
|
+
def attachment_ids!(node, attachment_ids)
|
313
|
+
node.add("#{NS_EWS_MESSAGES}:AttachmentIds") do |att|
|
314
|
+
attachment_ids.each do |id|
|
315
|
+
add_hierarchy!(att, {:attachment_id => {:id => id}})
|
316
|
+
end
|
317
|
+
end
|
318
|
+
end
|
319
|
+
|
320
|
+
def attachment_shape!(node)
|
321
|
+
node.add("#{NS_EWS_MESSAGES}:AttachmentShape")
|
322
|
+
end
|
311
323
|
|
312
324
|
# Add a hierarchy of elements from hash data
|
313
325
|
# @example Hash to XML
|
@@ -43,6 +43,17 @@ module Viewpoint
|
|
43
43
|
end
|
44
44
|
end
|
45
45
|
|
46
|
+
# @see ExchangeWebService#subscribe
|
47
|
+
def push_subscription_request!(folder_ids, event_types, url, watermark=nil, status_frequency=5)
|
48
|
+
@node.add("#{NS_EWS_MESSAGES}:PushSubscriptionRequest") do |ps|
|
49
|
+
folder_ids!(ps, folder_ids, nil, "#{NS_EWS_TYPES}:FolderIds")
|
50
|
+
event_types!(ps, event_types)
|
51
|
+
ps.add("#{NS_EWS_TYPES}:Watermark", watermark) unless watermark.nil?
|
52
|
+
ps.add("#{NS_EWS_TYPES}:StatusFrequency", status_frequency)
|
53
|
+
ps.add("#{NS_EWS_TYPES}:URL", url)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
46
57
|
# @param [String] type The type of items in the items array message/calendar
|
47
58
|
# @todo Fix max_changes_returned to be more flexible
|
48
59
|
def create_item!(folder_id, items, message_disposition, send_invites, type)
|
@@ -51,6 +51,8 @@ module Viewpoint
|
|
51
51
|
end
|
52
52
|
|
53
53
|
# ********* Begin Hooks *********
|
54
|
+
|
55
|
+
|
54
56
|
def on_create_document(doc)
|
55
57
|
doc.alias NS_EWS_TYPES, 'http://schemas.microsoft.com/exchange/services/2006/types'
|
56
58
|
doc.alias NS_EWS_MESSAGES, 'http://schemas.microsoft.com/exchange/services/2006/messages'
|
@@ -73,6 +75,8 @@ module Viewpoint
|
|
73
75
|
def on_after_create_http_request(req)
|
74
76
|
req.set_auth @@user, @@pass
|
75
77
|
end
|
78
|
+
|
79
|
+
|
76
80
|
# ********** End Hooks **********
|
77
81
|
|
78
82
|
|
@@ -303,6 +307,19 @@ module Viewpoint
|
|
303
307
|
parse!(resp)
|
304
308
|
end
|
305
309
|
|
310
|
+
# Used to subscribe client applications to either push or pull notifications.
|
311
|
+
# @see http://msdn.microsoft.com/en-us/library/aa566188.aspx Subscribe on MSDN
|
312
|
+
def push_subscribe(folder_ids, event_types, url, watermark=nil, status_frequency=5)
|
313
|
+
action = "#{SOAP_ACTION_PREFIX}/Subscribe"
|
314
|
+
resp = invoke("#{NS_EWS_MESSAGES}:Subscribe", :soap_action => action) do |root|
|
315
|
+
build!(root) do
|
316
|
+
push_subscription_request!(folder_ids, event_types, url, watermark, status_frequency)
|
317
|
+
end
|
318
|
+
end
|
319
|
+
parse!(resp)
|
320
|
+
|
321
|
+
end
|
322
|
+
|
306
323
|
# End a pull notification subscription.
|
307
324
|
# @see http://msdn.microsoft.com/en-us/library/aa564263.aspx
|
308
325
|
#
|
@@ -449,7 +466,27 @@ module Viewpoint
|
|
449
466
|
action = "#{SOAP_ACTION_PREFIX}/CreateItem"
|
450
467
|
resp = invoke("#{NS_EWS_MESSAGES}:CreateItem", :soap_action => action) do |node|
|
451
468
|
build!(node) do
|
452
|
-
create_item!(folder_id, items, message_disposition,
|
469
|
+
create_item!(folder_id, items, message_disposition, false, 'task')
|
470
|
+
end
|
471
|
+
end
|
472
|
+
parse!(resp)
|
473
|
+
end
|
474
|
+
|
475
|
+
# Operation is used to create contact items
|
476
|
+
# This is actually a CreateItem operation but they differ for different types
|
477
|
+
# of Exchange objects so it is named appropriately here.
|
478
|
+
# @see # http://msdn.microsoft.com/en-us/library/aa580529.aspx
|
479
|
+
#
|
480
|
+
# @param [String, Symbol] folder_id The folder to save this task in. Either a
|
481
|
+
# DistinguishedFolderId (must me a Symbol) or a FolderId (String)
|
482
|
+
# @param [Hash, Array] items An array of item Hashes or a single item Hash. Hash
|
483
|
+
# values should be based on values found here: http://msdn.microsoft.com/en-us/library/aa581315.aspx
|
484
|
+
# This Hash will eventually be passed to add_hierarchy! in the builder so it is in that format.
|
485
|
+
def create_contact_item(folder_id, items)
|
486
|
+
action = "#{SOAP_ACTION_PREFIX}/CreateItem"
|
487
|
+
resp = invoke("#{NS_EWS_MESSAGES}:CreateItem", :soap_action => action) do |node|
|
488
|
+
build!(node) do
|
489
|
+
create_item!(folder_id, items, nil, false, 'contact')
|
453
490
|
end
|
454
491
|
end
|
455
492
|
parse!(resp)
|
@@ -565,12 +602,18 @@ module Viewpoint
|
|
565
602
|
parse_delete_attachment(resp)
|
566
603
|
end
|
567
604
|
|
568
|
-
|
605
|
+
# Used to retrieve existing attachments on items in the Exchange store
|
606
|
+
# @see http://msdn.microsoft.com/en-us/library/aa494316.aspx
|
607
|
+
# @param [Array] attachment_ids Attachment Ids to fetch
|
608
|
+
def get_attachment(attachment_ids)
|
569
609
|
action = "#{SOAP_ACTION_PREFIX}/GetAttachment"
|
570
|
-
resp = invoke("#{NS_EWS_MESSAGES}:GetAttachment", :soap_action => action) do |
|
571
|
-
|
610
|
+
resp = invoke("#{NS_EWS_MESSAGES}:GetAttachment", :soap_action => action) do |root|
|
611
|
+
build!(root) do
|
612
|
+
attachment_shape!(root)
|
613
|
+
attachment_ids!(root, attachment_ids)
|
614
|
+
end
|
572
615
|
end
|
573
|
-
|
616
|
+
parse!(resp)
|
574
617
|
end
|
575
618
|
|
576
619
|
def create_managed_folder
|
@@ -656,24 +699,29 @@ module Viewpoint
|
|
656
699
|
parse_get_user_availability(resp)
|
657
700
|
end
|
658
701
|
|
659
|
-
|
702
|
+
# Gets a mailbox user's Out of Office (OOF) settings and messages.
|
703
|
+
# @see http://msdn.microsoft.com/en-us/library/aa563465.aspx
|
704
|
+
def get_user_oof_settings(mailbox)
|
660
705
|
action = "#{SOAP_ACTION_PREFIX}/GetUserOofSettings"
|
661
|
-
resp = invoke("#{NS_EWS_MESSAGES}:
|
662
|
-
|
706
|
+
resp = invoke("#{NS_EWS_MESSAGES}:GetUserOofSettingsRequest", :soap_action => action) do |root|
|
707
|
+
build!(root) do
|
708
|
+
mailbox!(root,mailbox[:mailbox],NS_EWS_TYPES)
|
709
|
+
end
|
663
710
|
end
|
664
|
-
|
711
|
+
parse!(resp)
|
665
712
|
end
|
666
713
|
|
667
|
-
|
714
|
+
# Sets a mailbox user's Out of Office (OOF) settings and message.
|
715
|
+
# @see http://msdn.microsoft.com/en-us/library/aa580294.aspx
|
716
|
+
def set_user_oof_settings(mailbox, oof_state, ext_audience, dt_start, dt_end, int_msg, ext_mg)
|
668
717
|
action = "#{SOAP_ACTION_PREFIX}/SetUserOofSettings"
|
669
|
-
resp = invoke("#{NS_EWS_MESSAGES}:SetUserOofSettings", :soap_action => action) do |
|
670
|
-
|
718
|
+
resp = invoke("#{NS_EWS_MESSAGES}:SetUserOofSettings", :soap_action => action) do |root|
|
719
|
+
build!(root)
|
671
720
|
end
|
672
|
-
|
721
|
+
parse!(resp)
|
673
722
|
end
|
674
723
|
|
675
724
|
|
676
|
-
|
677
725
|
# Private Methods (Builders and Parsers)
|
678
726
|
private
|
679
727
|
|
data/lib/soap/handsoap/parser.rb
CHANGED
@@ -27,13 +27,12 @@ module Viewpoint
|
|
27
27
|
@response = response
|
28
28
|
@response_type = (response/"//#{NS_SOAP}:Body/*").first.node_name
|
29
29
|
|
30
|
-
rmsg = (response/'
|
30
|
+
rmsg = (response/'//*[@ResponseClass]').first
|
31
31
|
@response_message = EwsSoapResponse.new(rmsg['ResponseClass'],
|
32
32
|
(rmsg/'m:ResponseCode/text()').first.to_s,
|
33
33
|
(rmsg/'m:MessageText/text()').first.to_s)
|
34
34
|
|
35
35
|
@response_message.set_soap_resp(response)
|
36
|
-
|
37
36
|
end
|
38
37
|
|
39
38
|
# This is the main parser method. It takes the response type and tries to
|
@@ -139,6 +139,20 @@ module Viewpoint
|
|
139
139
|
raise EwsError, "#{@response_message.code}: #{@response_message.message}"
|
140
140
|
end
|
141
141
|
end
|
142
|
+
|
143
|
+
def get_attachment_response(opts)
|
144
|
+
atts = []
|
145
|
+
if(@response_message.status == 'Success')
|
146
|
+
att_id = (@response/"//#{NS_EWS_MESSAGES}:Attachments/*").each do |a|
|
147
|
+
atts << xml_to_hash!(a.native_element)
|
148
|
+
end
|
149
|
+
@response_message.items = atts
|
150
|
+
#@response_message.items = @response
|
151
|
+
else
|
152
|
+
raise EwsError, "#{@response_message.code}: #{@response_message.message}"
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
142
156
|
|
143
157
|
def create_attachment_response(opts)
|
144
158
|
if(@response_message.status == 'Success')
|
@@ -163,7 +177,10 @@ module Viewpoint
|
|
163
177
|
else
|
164
178
|
raise EwsError, "#{@response_message.code}: #{@response_message.message}"
|
165
179
|
end
|
180
|
+
end
|
166
181
|
|
182
|
+
def get_user_oof_settings_response(opts)
|
183
|
+
@response_message.items = xml_to_hash!((@response/"//#{NS_EWS_TYPES}:OofSettings").first.native_element)
|
167
184
|
end
|
168
185
|
|
169
186
|
# Parse out a Mailbox element
|
data/lib/soap/soap_provider.rb
CHANGED
data/lib/viewpoint.rb
CHANGED
@@ -52,6 +52,9 @@ require 'model/meeting_request'
|
|
52
52
|
require 'model/meeting_response'
|
53
53
|
require 'model/meeting_cancellation'
|
54
54
|
require 'model/task'
|
55
|
+
require 'model/attachment'
|
56
|
+
require 'model/file_attachment'
|
57
|
+
require 'model/item_attachment'
|
55
58
|
|
56
59
|
# Load the Exception classes
|
57
60
|
require 'exceptions/exceptions'
|
File without changes
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 1
|
8
|
-
-
|
9
|
-
version: 0.1.
|
8
|
+
- 3
|
9
|
+
version: 0.1.3
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Dan Wanek
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-
|
17
|
+
date: 2010-10-29 00:00:00 -05:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
@@ -99,15 +99,18 @@ files:
|
|
99
99
|
- VERSION
|
100
100
|
- lib/exceptions/exceptions.rb
|
101
101
|
- lib/extensions/string.rb
|
102
|
+
- lib/model/attachment.rb
|
102
103
|
- lib/model/calendar_folder.rb
|
103
104
|
- lib/model/calendar_item.rb
|
104
105
|
- lib/model/contact.rb
|
105
106
|
- lib/model/contacts_folder.rb
|
106
107
|
- lib/model/distribution_list.rb
|
107
108
|
- lib/model/event.rb
|
109
|
+
- lib/model/file_attachment.rb
|
108
110
|
- lib/model/folder.rb
|
109
111
|
- lib/model/generic_folder.rb
|
110
112
|
- lib/model/item.rb
|
113
|
+
- lib/model/item_attachment.rb
|
111
114
|
- lib/model/mailbox_user.rb
|
112
115
|
- lib/model/meeting_cancellation.rb
|
113
116
|
- lib/model/meeting_message.rb
|
@@ -127,11 +130,11 @@ files:
|
|
127
130
|
- lib/soap/soap_provider.rb
|
128
131
|
- lib/viewpoint.rb
|
129
132
|
- preamble
|
133
|
+
- test/.rspec
|
130
134
|
- test/spec/basic_functions.spec
|
131
135
|
- test/spec/folder_subscriptions.spec
|
132
136
|
- test/spec/folder_synchronization.spec
|
133
137
|
- test/spec/item_tests.spec
|
134
|
-
- test/spec/spec.opts
|
135
138
|
- utils/ewsWSDL2rb.rb
|
136
139
|
has_rdoc: true
|
137
140
|
homepage: http://github.com/zenchild/Viewpoint
|