exchanger 0.1.0
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.
- data/LICENSE +20 -0
- data/README.md +53 -0
- data/lib/exchanger.rb +79 -0
- data/lib/exchanger/attributes.rb +61 -0
- data/lib/exchanger/boolean.rb +4 -0
- data/lib/exchanger/client.rb +19 -0
- data/lib/exchanger/config.rb +32 -0
- data/lib/exchanger/dirty.rb +239 -0
- data/lib/exchanger/element.rb +161 -0
- data/lib/exchanger/elements/attendee.rb +10 -0
- data/lib/exchanger/elements/base_folder.rb +61 -0
- data/lib/exchanger/elements/calendar_folder.rb +11 -0
- data/lib/exchanger/elements/calendar_item.rb +59 -0
- data/lib/exchanger/elements/complete_name.rb +16 -0
- data/lib/exchanger/elements/contact.rb +49 -0
- data/lib/exchanger/elements/contacts_folder.rb +17 -0
- data/lib/exchanger/elements/distribution_list.rb +8 -0
- data/lib/exchanger/elements/email_address.rb +16 -0
- data/lib/exchanger/elements/entry.rb +11 -0
- data/lib/exchanger/elements/folder.rb +9 -0
- data/lib/exchanger/elements/identifier.rb +7 -0
- data/lib/exchanger/elements/im_address.rb +20 -0
- data/lib/exchanger/elements/item.rb +86 -0
- data/lib/exchanger/elements/mailbox.rb +34 -0
- data/lib/exchanger/elements/meeting_cancellation.rb +4 -0
- data/lib/exchanger/elements/meeting_message.rb +16 -0
- data/lib/exchanger/elements/meeting_request.rb +6 -0
- data/lib/exchanger/elements/meeting_response.rb +4 -0
- data/lib/exchanger/elements/message.rb +24 -0
- data/lib/exchanger/elements/phone_number.rb +13 -0
- data/lib/exchanger/elements/physical_address.rb +15 -0
- data/lib/exchanger/elements/search_folder.rb +5 -0
- data/lib/exchanger/elements/single_recipient.rb +6 -0
- data/lib/exchanger/elements/task.rb +5 -0
- data/lib/exchanger/elements/tasks_folder.rb +4 -0
- data/lib/exchanger/field.rb +139 -0
- data/lib/exchanger/operation.rb +110 -0
- data/lib/exchanger/operations/create_item.rb +64 -0
- data/lib/exchanger/operations/expand_dl.rb +42 -0
- data/lib/exchanger/operations/find_folder.rb +55 -0
- data/lib/exchanger/operations/find_item.rb +54 -0
- data/lib/exchanger/operations/get_folder.rb +55 -0
- data/lib/exchanger/operations/get_item.rb +44 -0
- data/lib/exchanger/operations/resolve_names.rb +43 -0
- data/lib/exchanger/operations/update_item.rb +43 -0
- data/lib/exchanger/persistence.rb +27 -0
- data/spec/calendar_item_spec.rb +26 -0
- data/spec/client_spec.rb +11 -0
- data/spec/contact_spec.rb +68 -0
- data/spec/element_spec.rb +4 -0
- data/spec/field_spec.rb +118 -0
- data/spec/folder_spec.rb +13 -0
- data/spec/mailbox_spec.rb +9 -0
- data/spec/spec_helper.rb +6 -0
- metadata +208 -0
@@ -0,0 +1,64 @@
|
|
1
|
+
module Exchanger
|
2
|
+
# The CreateItem operation creates items in the Exchanger store.
|
3
|
+
#
|
4
|
+
# You can use the CreateItem operation to create the following:
|
5
|
+
# * Calendar items
|
6
|
+
# * E-mail messages
|
7
|
+
# * Meeting requests
|
8
|
+
# * Tasks
|
9
|
+
# * Contacts
|
10
|
+
#
|
11
|
+
# http://msdn.microsoft.com/en-us/library/aa563797.aspx
|
12
|
+
class CreateItem < Operation
|
13
|
+
class Request < Operation::Request
|
14
|
+
attr_accessor :folder_id, :email_address, :items
|
15
|
+
|
16
|
+
# Reset request options to defaults.
|
17
|
+
def reset
|
18
|
+
@folder_id = :contacts
|
19
|
+
@email_address = nil
|
20
|
+
@items = []
|
21
|
+
end
|
22
|
+
|
23
|
+
def to_xml
|
24
|
+
Nokogiri::XML::Builder.new do |xml|
|
25
|
+
xml.send("soap:Envelope", "xmlns:soap" => NS["soap"], "xmlns:t" => NS["t"], "xmlns:xsi" => NS["xsi"], "xmlns:xsd" => NS["xsd"]) do
|
26
|
+
xml.send("soap:Body") do
|
27
|
+
xml.CreateItem("xmlns" => NS["m"]) do
|
28
|
+
xml.SavedItemFolderId do
|
29
|
+
if folder_id.is_a?(Symbol)
|
30
|
+
xml.send("t:DistinguishedFolderId", "Id" => folder_id) do
|
31
|
+
if email_address
|
32
|
+
xml.send("t:Mailbox") do
|
33
|
+
xml.send("t:EmailAddress", email_address)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
else
|
38
|
+
xml.send("t:FolderId", "Id" => folder_id)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
xml.Items do
|
42
|
+
items.each do |item|
|
43
|
+
item_xml = item.to_xml
|
44
|
+
item_xml.add_namespace_definition("t", NS["t"])
|
45
|
+
item_xml.namespace = item_xml.namespace_definitions[0]
|
46
|
+
xml << item_xml.to_s
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
class Response < Operation::Response
|
57
|
+
def item_ids
|
58
|
+
to_xml.xpath(".//t:ItemId", NS).map do |node|
|
59
|
+
Identifier.new_from_xml(node)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module Exchanger
|
2
|
+
# The ExpandDL operation exposes the full membership of distribution lists.
|
3
|
+
#
|
4
|
+
# http://msdn.microsoft.com/en-us/library/aa494152.aspx
|
5
|
+
class ExpandDL < Operation
|
6
|
+
class Request < Operation::Request
|
7
|
+
attr_accessor :mailbox
|
8
|
+
|
9
|
+
# Reset request options to defaults.
|
10
|
+
def reset
|
11
|
+
@mailbox = nil
|
12
|
+
end
|
13
|
+
|
14
|
+
def to_xml
|
15
|
+
Nokogiri::XML::Builder.new do |xml|
|
16
|
+
xml.send("soap:Envelope", "xmlns:soap" => NS["soap"]) do
|
17
|
+
xml.send("soap:Body") do
|
18
|
+
xml.ExpandDL("xmlns" => NS["m"], "xmlns:t" => NS["t"]) do
|
19
|
+
xml.Mailbox do
|
20
|
+
if mailbox.item_id
|
21
|
+
xml.send("t:ItemId", "Id" => mailbox.item_id.id, "ChangeKey" => mailbox.item_id.change_key)
|
22
|
+
else
|
23
|
+
xml.send("t:EmailAddress", mailbox.email_address)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
class Response < Operation::Response
|
34
|
+
def mailboxes
|
35
|
+
to_xml.xpath(".//t:Mailbox", NS).map do |node|
|
36
|
+
item_klass = Exchanger.const_get(node.name)
|
37
|
+
item_klass.new_from_xml(node)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module Exchanger
|
2
|
+
# The FindFolder operation uses Exchanger Web Services to find subfolders of
|
3
|
+
# an identified folder and returns a set of properties that describe the set of subfolders.
|
4
|
+
#
|
5
|
+
# http://msdn.microsoft.com/en-us/library/aa563918.aspx
|
6
|
+
class FindFolder < Operation
|
7
|
+
class Request < Operation::Request
|
8
|
+
attr_accessor :parent_folder_id, :base_shape, :email_address, :traversal
|
9
|
+
|
10
|
+
# Reset request options to defaults.
|
11
|
+
def reset
|
12
|
+
@parent_folder_id = nil
|
13
|
+
@traversal = :shallow
|
14
|
+
@base_shape = :all_properties
|
15
|
+
@email_address = nil
|
16
|
+
end
|
17
|
+
|
18
|
+
def to_xml
|
19
|
+
Nokogiri::XML::Builder.new do |xml|
|
20
|
+
xml.send("soap:Envelope", "xmlns:soap" => NS["soap"]) do
|
21
|
+
xml.send("soap:Body") do
|
22
|
+
xml.FindFolder("xmlns" => NS["m"], "xmlns:t" => NS["t"], "Traversal" => traversal.to_s.camelize) do
|
23
|
+
xml.FolderShape do
|
24
|
+
xml.send "t:BaseShape", base_shape.to_s.camelize
|
25
|
+
end
|
26
|
+
xml.ParentFolderIds do
|
27
|
+
if parent_folder_id.is_a?(Symbol)
|
28
|
+
xml.send("t:DistinguishedFolderId", "Id" => parent_folder_id) do
|
29
|
+
if email_address
|
30
|
+
xml.send("t:Mailbox") do
|
31
|
+
xml.send("t:EmailAddress", email_address)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
else
|
36
|
+
xml.send("t:FolderId", "Id" => parent_folder_id)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
class Response < Operation::Response
|
47
|
+
def folders
|
48
|
+
to_xml.xpath(".//t:Folders", NS).children.map do |node|
|
49
|
+
folder_klass = Exchanger.const_get(node.name)
|
50
|
+
folder_klass.new_from_xml(node)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module Exchanger
|
2
|
+
# The FindItem operation identifies items that are located in a specified folder.
|
3
|
+
#
|
4
|
+
# http://msdn.microsoft.com/en-us/library/aa566107.aspx
|
5
|
+
class FindItem < Operation
|
6
|
+
class Request < Operation::Request
|
7
|
+
attr_accessor :folder_id, :traversal, :base_shape, :email_address
|
8
|
+
|
9
|
+
# Reset request options to defaults.
|
10
|
+
def reset
|
11
|
+
@folder_id = :contacts
|
12
|
+
@traversal = :shallow
|
13
|
+
@base_shape = :all_properties
|
14
|
+
@email_address = nil
|
15
|
+
end
|
16
|
+
|
17
|
+
def to_xml
|
18
|
+
Nokogiri::XML::Builder.new do |xml|
|
19
|
+
xml.send("soap:Envelope", "xmlns:soap" => NS["soap"]) do
|
20
|
+
xml.send("soap:Body") do
|
21
|
+
xml.FindItem("xmlns" => NS["m"], "xmlns:t" => NS["t"], "Traversal" => traversal.to_s.camelize) do
|
22
|
+
xml.ItemShape do
|
23
|
+
xml.send "t:BaseShape", base_shape.to_s.camelize
|
24
|
+
end
|
25
|
+
xml.ParentFolderIds do
|
26
|
+
if folder_id.is_a?(Symbol)
|
27
|
+
xml.send("t:DistinguishedFolderId", "Id" => folder_id) do
|
28
|
+
if email_address
|
29
|
+
xml.send("t:Mailbox") do
|
30
|
+
xml.send("t:EmailAddress", email_address)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
else
|
35
|
+
xml.send("t:FolderId", "Id" => folder_id)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
class Response < Operation::Response
|
46
|
+
def items
|
47
|
+
to_xml.xpath(".//t:Items", NS).children.map do |node|
|
48
|
+
item_klass = Exchanger.const_get(node.name)
|
49
|
+
item_klass.new_from_xml(node)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module Exchanger
|
2
|
+
# The GetFolder operation gets folders from the Exchanger store.
|
3
|
+
#
|
4
|
+
# http://msdn.microsoft.com/en-us/library/aa580274.aspx
|
5
|
+
class GetFolder < Operation
|
6
|
+
class Request < Operation::Request
|
7
|
+
attr_accessor :folder_ids, :base_shape, :email_address
|
8
|
+
|
9
|
+
# Reset request options to defaults.
|
10
|
+
def reset
|
11
|
+
@folder_ids = []
|
12
|
+
@base_shape = :default
|
13
|
+
@email_address = nil
|
14
|
+
end
|
15
|
+
|
16
|
+
def to_xml
|
17
|
+
Nokogiri::XML::Builder.new do |xml|
|
18
|
+
xml.send("soap:Envelope", "xmlns:soap" => NS["soap"]) do
|
19
|
+
xml.send("soap:Body") do
|
20
|
+
xml.GetFolder("xmlns" => NS["m"], "xmlns:t" => NS["t"]) do
|
21
|
+
xml.FolderShape do
|
22
|
+
xml.send "t:BaseShape", base_shape.to_s.camelize
|
23
|
+
end
|
24
|
+
xml.FolderIds do
|
25
|
+
folder_ids.each do |folder_id|
|
26
|
+
if folder_id.is_a?(Symbol)
|
27
|
+
xml.send("t:DistinguishedFolderId", "Id" => folder_id) do
|
28
|
+
if email_address
|
29
|
+
xml.send("t:Mailbox") do
|
30
|
+
xml.send("t:EmailAddress", email_address)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
else
|
35
|
+
xml.send("t:FolderId", "Id" => folder_id)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
class Response < Operation::Response
|
47
|
+
def folders
|
48
|
+
to_xml.xpath(".//m:Folders", NS).children.map do |node|
|
49
|
+
folder_klass = Exchanger.const_get(node.name)
|
50
|
+
folder_klass.new_from_xml(node)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Exchanger
|
2
|
+
# The GetItem operation gets items from the Exchanger store.
|
3
|
+
#
|
4
|
+
# http://msdn.microsoft.com/en-us/library/aa565934.aspx
|
5
|
+
class GetItem < Operation
|
6
|
+
class Request < Operation::Request
|
7
|
+
attr_accessor :item_ids, :base_shape
|
8
|
+
|
9
|
+
# Reset request options to defaults.
|
10
|
+
def reset
|
11
|
+
@item_ids = []
|
12
|
+
@base_shape = :all_properties
|
13
|
+
end
|
14
|
+
|
15
|
+
def to_xml
|
16
|
+
Nokogiri::XML::Builder.new do |xml|
|
17
|
+
xml.send("soap:Envelope", "xmlns:soap" => NS["soap"]) do
|
18
|
+
xml.send("soap:Body") do
|
19
|
+
xml.GetItem("xmlns" => NS["m"], "xmlns:t" => NS["t"]) do
|
20
|
+
xml.ItemShape do
|
21
|
+
xml.send "t:BaseShape", base_shape.to_s.camelize
|
22
|
+
end
|
23
|
+
xml.ItemIds do
|
24
|
+
item_ids.each do |item_id|
|
25
|
+
xml.send("t:ItemId", "Id" => item_id)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
class Response < Operation::Response
|
36
|
+
def items
|
37
|
+
to_xml.xpath(".//m:Items", NS).children.map do |node|
|
38
|
+
item_klass = Exchanger.const_get(node.name)
|
39
|
+
item_klass.new_from_xml(node)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module Exchanger
|
2
|
+
# The ResolveNames operation resolves ambiguous e-mail addresses and display names.
|
3
|
+
#
|
4
|
+
# http://msdn.microsoft.com/en-us/library/aa563518.aspx
|
5
|
+
class ResolveNames < Operation
|
6
|
+
class Request < Operation::Request
|
7
|
+
attr_accessor :name
|
8
|
+
|
9
|
+
# Reset request options to defaults.
|
10
|
+
def reset
|
11
|
+
@name = nil
|
12
|
+
end
|
13
|
+
|
14
|
+
def to_xml
|
15
|
+
Nokogiri::XML::Builder.new do |xml|
|
16
|
+
xml.send("soap:Envelope", "xmlns:soap" => NS["soap"]) do
|
17
|
+
xml.send("soap:Body") do
|
18
|
+
xml.ResolveNames("xmlns" => NS["m"], "xmlns:t" => NS["t"], "ReturnFullContactData" => "true") do
|
19
|
+
xml.UnresolvedEntry name
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
class Response < Operation::Response
|
28
|
+
def mailboxes
|
29
|
+
to_xml.xpath(".//t:Mailbox", NS).map do |node|
|
30
|
+
item_klass = Exchanger.const_get(node.name)
|
31
|
+
item_klass.new_from_xml(node)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def contacts
|
36
|
+
to_xml.xpath(".//t:Contact", NS).map do |node|
|
37
|
+
item_klass = Exchanger.const_get(node.name)
|
38
|
+
item_klass.new_from_xml(node)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module Exchanger
|
2
|
+
# The UpdateItem operation is used to modify the properties of an existing item in the Exchanger store.
|
3
|
+
#
|
4
|
+
# http://msdn.microsoft.com/en-us/library/aa581084.aspx
|
5
|
+
# http://msdn.microsoft.com/en-us/library/aa579673.aspx
|
6
|
+
class UpdateItem < Operation
|
7
|
+
class Request < Operation::Request
|
8
|
+
attr_accessor :items
|
9
|
+
|
10
|
+
# Reset request options to defaults.
|
11
|
+
def reset
|
12
|
+
@items = []
|
13
|
+
end
|
14
|
+
|
15
|
+
def to_xml
|
16
|
+
Nokogiri::XML::Builder.new do |xml|
|
17
|
+
xml.send("soap:Envelope", "xmlns:soap" => NS["soap"], "xmlns:t" => NS["t"], "xmlns:xsi" => NS["xsi"], "xmlns:xsd" => NS["xsd"]) do
|
18
|
+
xml.send("soap:Body") do
|
19
|
+
xml.UpdateItem("xmlns" => NS["m"], "ConflictResolution" => "AlwaysOverwrite") do
|
20
|
+
xml.ItemChanges do
|
21
|
+
items.each do |item|
|
22
|
+
item_change = item.to_xml_change
|
23
|
+
item_change.add_namespace_definition("t", NS["t"])
|
24
|
+
item_change.namespace = item_change.namespace_definitions[0]
|
25
|
+
xml << item_change.to_s
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
class Response < Operation::Response
|
36
|
+
def item_ids
|
37
|
+
to_xml.xpath(".//t:ItemId", NS).map do |node|
|
38
|
+
Identifier.new_from_xml(node)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Exchanger
|
2
|
+
module Persistence
|
3
|
+
def new_record?
|
4
|
+
not id
|
5
|
+
end
|
6
|
+
|
7
|
+
def save
|
8
|
+
if new_record?
|
9
|
+
create
|
10
|
+
else
|
11
|
+
update
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
# Reloads the +Element+ attributes from Exchanger.
|
16
|
+
def reload
|
17
|
+
if new_record?
|
18
|
+
false
|
19
|
+
else
|
20
|
+
reloaded_element = self.class.find(self.id)
|
21
|
+
@attributes = reloaded_element.attributes
|
22
|
+
reset_modifications
|
23
|
+
true
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require "spec/spec_helper"
|
2
|
+
|
3
|
+
describe Exchanger::CalendarFolder do
|
4
|
+
before do
|
5
|
+
@folder = Exchanger::Folder.find(:calendar, "edgars.beigarts@tieto.com")
|
6
|
+
end
|
7
|
+
|
8
|
+
it "should return calendar folder" do
|
9
|
+
@folder.class.should == Exchanger::CalendarFolder
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should have calendar items" do
|
13
|
+
@folder.items.size.should > 0
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe Exchanger::CalendarItem do
|
18
|
+
before do
|
19
|
+
@folder = Exchanger::Folder.find(:calendar, "edgars.beigarts@tieto.com")
|
20
|
+
@item = @folder.items.first
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should have start time" do
|
24
|
+
@item.start.class.should == Time
|
25
|
+
end
|
26
|
+
end
|