zm-ruby-client 0.14.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.
Files changed (148) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +58 -0
  3. data/Gemfile +8 -0
  4. data/LICENSE +674 -0
  5. data/README.md +47 -0
  6. data/SECURITY.md +21 -0
  7. data/lib/zm/client/account/account.rb +345 -0
  8. data/lib/zm/client/account/account_dls_membership_collection.rb +22 -0
  9. data/lib/zm/client/account/account_dls_owner_collection.rb +22 -0
  10. data/lib/zm/client/account/accounts_builder.rb +19 -0
  11. data/lib/zm/client/account/accounts_collection.rb +48 -0
  12. data/lib/zm/client/account.rb +7 -0
  13. data/lib/zm/client/ace/ace.rb +32 -0
  14. data/lib/zm/client/ace/aces_builder.rb +25 -0
  15. data/lib/zm/client/ace/aces_collection.rb +36 -0
  16. data/lib/zm/client/ace.rb +5 -0
  17. data/lib/zm/client/appointment/appointment.rb +143 -0
  18. data/lib/zm/client/appointment/appointment_jsns_builder.rb +125 -0
  19. data/lib/zm/client/appointment/appointment_jsns_initializer.rb +129 -0
  20. data/lib/zm/client/appointment/appointments_builder.rb +33 -0
  21. data/lib/zm/client/appointment/appointments_collection.rb +106 -0
  22. data/lib/zm/client/appointment.rb +7 -0
  23. data/lib/zm/client/backup/backup.rb +59 -0
  24. data/lib/zm/client/backup/backups_builder.rb +26 -0
  25. data/lib/zm/client/backup/backups_collection.rb +22 -0
  26. data/lib/zm/client/backup.rb +5 -0
  27. data/lib/zm/client/base/account_object.rb +17 -0
  28. data/lib/zm/client/base/admin_object.rb +45 -0
  29. data/lib/zm/client/base/object.rb +80 -0
  30. data/lib/zm/client/base/objects_builder.rb +31 -0
  31. data/lib/zm/client/base/objects_collection.rb +135 -0
  32. data/lib/zm/client/base.rb +7 -0
  33. data/lib/zm/client/cluster/cluster.rb +121 -0
  34. data/lib/zm/client/cluster/cluster_config.rb +100 -0
  35. data/lib/zm/client/cluster.rb +4 -0
  36. data/lib/zm/client/common/message.rb +10 -0
  37. data/lib/zm/client/common/recipients.rb +67 -0
  38. data/lib/zm/client/common/token_metadata.rb +44 -0
  39. data/lib/zm/client/common.rb +5 -0
  40. data/lib/zm/client/config.rb +12 -0
  41. data/lib/zm/client/connector/rest_account.rb +74 -0
  42. data/lib/zm/client/connector/soap_account.rb +563 -0
  43. data/lib/zm/client/connector/soap_admin.rb +532 -0
  44. data/lib/zm/client/connector/soap_base.rb +65 -0
  45. data/lib/zm/client/connector/soap_error.rb +26 -0
  46. data/lib/zm/client/connector/soap_xml_builder.rb +68 -0
  47. data/lib/zm/client/constant.rb +217 -0
  48. data/lib/zm/client/contact/contact.rb +124 -0
  49. data/lib/zm/client/contact/contact_member.rb +73 -0
  50. data/lib/zm/client/contact/contacts_builder.rb +24 -0
  51. data/lib/zm/client/contact/contacts_collection.rb +26 -0
  52. data/lib/zm/client/contact/mod_group_contact.rb +74 -0
  53. data/lib/zm/client/contact.rb +7 -0
  54. data/lib/zm/client/cos/cos.rb +59 -0
  55. data/lib/zm/client/cos/coses_builder.rb +29 -0
  56. data/lib/zm/client/cos/coses_collection.rb +33 -0
  57. data/lib/zm/client/cos.rb +5 -0
  58. data/lib/zm/client/data_source.rb +5 -0
  59. data/lib/zm/client/distributionlist/distributionlist.rb +125 -0
  60. data/lib/zm/client/distributionlist/distributionlists_builder.rb +29 -0
  61. data/lib/zm/client/distributionlist/distributionlists_collection.rb +41 -0
  62. data/lib/zm/client/distributionlist.rb +5 -0
  63. data/lib/zm/client/document/document.rb +51 -0
  64. data/lib/zm/client/document/documents_builder.rb +31 -0
  65. data/lib/zm/client/document/documents_collection.rb +93 -0
  66. data/lib/zm/client/document.rb +5 -0
  67. data/lib/zm/client/domain/domain.rb +85 -0
  68. data/lib/zm/client/domain/domains_builder.rb +32 -0
  69. data/lib/zm/client/domain/domains_collection.rb +36 -0
  70. data/lib/zm/client/domain.rb +5 -0
  71. data/lib/zm/client/folder/folder.rb +215 -0
  72. data/lib/zm/client/folder/folder_grant.rb +58 -0
  73. data/lib/zm/client/folder/folder_retention_policy.rb +48 -0
  74. data/lib/zm/client/folder/folders_builder.rb +58 -0
  75. data/lib/zm/client/folder/folders_collection.rb +95 -0
  76. data/lib/zm/client/folder/mod_document_folder.rb +17 -0
  77. data/lib/zm/client/folder.rb +8 -0
  78. data/lib/zm/client/identity/identities_builder.rb +25 -0
  79. data/lib/zm/client/identity/identities_collection.rb +26 -0
  80. data/lib/zm/client/identity/identity.rb +75 -0
  81. data/lib/zm/client/identity.rb +5 -0
  82. data/lib/zm/client/license/license.rb +29 -0
  83. data/lib/zm/client/license/licenses_collection.rb +28 -0
  84. data/lib/zm/client/license.rb +4 -0
  85. data/lib/zm/client/message/message.rb +225 -0
  86. data/lib/zm/client/message/messages_builder.rb +31 -0
  87. data/lib/zm/client/message/messages_collection.rb +111 -0
  88. data/lib/zm/client/message.rb +5 -0
  89. data/lib/zm/client/mountpoint/mountpoint.rb +95 -0
  90. data/lib/zm/client/mountpoint/mountpoints_builder.rb +38 -0
  91. data/lib/zm/client/mountpoint/mountpoints_collection.rb +61 -0
  92. data/lib/zm/client/mountpoint.rb +5 -0
  93. data/lib/zm/client/mta_queue/mta_queue.rb +60 -0
  94. data/lib/zm/client/mta_queue/mta_queues_builder.rb +26 -0
  95. data/lib/zm/client/mta_queue/mta_queues_collection.rb +95 -0
  96. data/lib/zm/client/mta_queue.rb +5 -0
  97. data/lib/zm/client/mta_queue_item/mta_queue_item.rb +51 -0
  98. data/lib/zm/client/mta_queue_item/mta_queue_items_builder.rb +27 -0
  99. data/lib/zm/client/mta_queue_item/mta_queue_items_collection.rb +99 -0
  100. data/lib/zm/client/mta_queue_item.rb +5 -0
  101. data/lib/zm/client/resource/resource.rb +149 -0
  102. data/lib/zm/client/resource/resources_builder.rb +29 -0
  103. data/lib/zm/client/resource/resources_collection.rb +41 -0
  104. data/lib/zm/client/resource.rb +5 -0
  105. data/lib/zm/client/search_folder/search_folder.rb +63 -0
  106. data/lib/zm/client/search_folder/search_folders_builder.rb +26 -0
  107. data/lib/zm/client/search_folder/search_folders_collection.rb +28 -0
  108. data/lib/zm/client/search_folder.rb +5 -0
  109. data/lib/zm/client/server/server.rb +516 -0
  110. data/lib/zm/client/server/servers_builder.rb +26 -0
  111. data/lib/zm/client/server/servers_collection.rb +37 -0
  112. data/lib/zm/client/server.rb +5 -0
  113. data/lib/zm/client/share/share.rb +60 -0
  114. data/lib/zm/client/share/shares_builder.rb +23 -0
  115. data/lib/zm/client/share/shares_collection.rb +48 -0
  116. data/lib/zm/client/share.rb +5 -0
  117. data/lib/zm/client/signature/signature.rb +62 -0
  118. data/lib/zm/client/signature/signature_jsns_builder.rb +29 -0
  119. data/lib/zm/client/signature/signatures_builder.rb +26 -0
  120. data/lib/zm/client/signature/signatures_collection.rb +28 -0
  121. data/lib/zm/client/signature.rb +6 -0
  122. data/lib/zm/client/tag/tag.rb +45 -0
  123. data/lib/zm/client/tag/tags_builder.rb +25 -0
  124. data/lib/zm/client/tag/tags_collection.rb +26 -0
  125. data/lib/zm/client/tag.rb +5 -0
  126. data/lib/zm/client/task/task.rb +74 -0
  127. data/lib/zm/client/task/tasks_builder.rb +31 -0
  128. data/lib/zm/client/task/tasks_collection.rb +100 -0
  129. data/lib/zm/client/task.rb +5 -0
  130. data/lib/zm/client/upload/upload.rb +154 -0
  131. data/lib/zm/client/upload.rb +3 -0
  132. data/lib/zm/client/version.rb +18 -0
  133. data/lib/zm/client.rb +5 -0
  134. data/lib/zm/modules/common/account_common.rb +71 -0
  135. data/lib/zm/modules/common/cos_common.rb +463 -0
  136. data/lib/zm/modules/common/dl_common.rb +36 -0
  137. data/lib/zm/modules/common/identity_common.rb +19 -0
  138. data/lib/zm/modules/common/resource_common.rb +59 -0
  139. data/lib/zm/modules/common/signature_common.rb +16 -0
  140. data/lib/zm/modules/common/zimbra-attrs.json +1 -0
  141. data/lib/zm/utils/thread_pool.rb +72 -0
  142. data/lib/zm-ruby-client.rb +1 -0
  143. data/test/accounts.rb +62 -0
  144. data/test/cluster_config.rb +30 -0
  145. data/test/coses.rb +26 -0
  146. data/test/domains.rb +70 -0
  147. data/zm-ruby-client.gemspec +24 -0
  148. metadata +244 -0
@@ -0,0 +1,74 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'openssl'
4
+ require 'curb'
5
+
6
+ module Zm
7
+ module Client
8
+ class RestAccountConnector
9
+ attr_reader :verbose, :follow_location
10
+
11
+ def initialize
12
+ @verbose = false
13
+ @follow_location = true
14
+ @curl = easy_curl
15
+ end
16
+
17
+ def verbose!
18
+ @verbose = true
19
+ @curl.verbose = @verbose
20
+ end
21
+
22
+ def cookie(cookie)
23
+ @curl.headers['Cookie'] = cookie
24
+ end
25
+
26
+ def download(url, dest_file_path)
27
+ @curl.url = URI.escape(url)
28
+ File.open(dest_file_path, 'wb') do |f|
29
+ @curl.on_body do |data|
30
+ f << data
31
+ data.size
32
+ end
33
+ @curl.perform
34
+ end
35
+ end
36
+
37
+ def upload(url, src_file_path)
38
+ @curl.url = URI.escape(url)
39
+ @curl.http_post(Curl::PostField.file('file', src_file_path))
40
+
41
+ if @curl.status.to_i >= 400
42
+ messages = [
43
+ "Upload failure ! #{src_file_path}",
44
+ extract_title(@curl.body_str)
45
+ ].compact
46
+ raise RestError, messages.join("\n")
47
+ end
48
+
49
+ @curl.body_str
50
+ end
51
+
52
+ private
53
+
54
+ def easy_curl
55
+ Curl::Easy.new do |curl|
56
+ curl.timeout = 300
57
+ curl.enable_cookies = false
58
+ curl.encoding = ''
59
+ curl.ssl_verify_peer = false
60
+ curl.ssl_verify_host = 0
61
+ curl.multipart_form_post = true
62
+ curl.verbose = verbose
63
+ curl.follow_location = follow_location
64
+ end
65
+ end
66
+
67
+ def extract_title(str)
68
+ str.scan(%r{<title>(.*)</title>}).first.first
69
+ rescue StandardError
70
+ nil
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,563 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'soap_base'
4
+ require_relative 'soap_error'
5
+ require 'gyoku'
6
+
7
+ # include OpenSSL
8
+ # include Digest
9
+
10
+ module Zm
11
+ module Client
12
+ class SoapAccountConnector < SoapBaseConnector
13
+
14
+ SOAP_PATH = '/service/soap/'
15
+ MAILSPACE = 'urn:zimbraMail'
16
+ ACCOUNTSPACE = 'urn:zimbraAccount'
17
+ A_NODE_PROC = lambda { |n| { n: n.first, _content: n.last } }
18
+ A_NODE_PROC_NAME = lambda { |n| { name: n.first, _content: n.last } }
19
+ A_NODE_PROC_ARROW_NAME = lambda { |n| { :@name => n.first, content!: n.last } }
20
+
21
+ def initialize(scheme, host, port)
22
+ @uri = URI::HTTP.new(scheme, nil, host, port, nil, SOAP_PATH, nil, nil, nil)
23
+ init_curl_client
24
+ end
25
+
26
+ def auth_template(mail)
27
+ {
28
+ Body: {
29
+ AuthRequest: {
30
+ _jsns: ACCOUNTSPACE,
31
+ account: {
32
+ _content: mail,
33
+ by: :name
34
+ }
35
+ }
36
+ }
37
+ }
38
+ end
39
+
40
+ def auth_preauth(mail, domainkey)
41
+ ts = (Time.now.to_i * 1000)
42
+ preauth = compute_preauth(mail, ts, domainkey)
43
+ body = auth_template(mail)
44
+ preauth_h = {
45
+ preauth: {
46
+ _content: preauth,
47
+ timestamp: ts
48
+ }
49
+ }
50
+ body[:Body][:AuthRequest].merge!(preauth_h)
51
+ do_auth(body)
52
+ end
53
+
54
+ def auth_password(mail, password)
55
+ body = auth_template(mail)
56
+ body[:Body][:AuthRequest].merge!({ password: password })
57
+ do_auth(body)
58
+ end
59
+
60
+ def do_auth(body)
61
+ res = curl_request(body, AuthError)
62
+ res[BODY][:AuthResponse][:authToken].first[:_content]
63
+ end
64
+
65
+ # -------------------------------
66
+ # APPOINTMENT
67
+
68
+ def get_appointment(token, id)
69
+ req = { id: id }
70
+ body = init_hash_request(token, :GetAppointmentRequest)
71
+ body[:Body][:GetAppointmentRequest].merge!(req)
72
+ curl_request(body)
73
+ end
74
+
75
+ def create_appointment(token, jsns)
76
+ soap_name = :CreateAppointmentRequest
77
+ body = init_hash_request(token, soap_name)
78
+ body[:Body][soap_name].merge!(jsns)
79
+ curl_request(body)
80
+ end
81
+
82
+ def modify_appointment(token, jsns)
83
+ soap_name = :ModifyAppointmentRequest
84
+ body = init_hash_request(token, soap_name)
85
+ body[:Body][soap_name].merge!(jsns)
86
+ curl_request(body)
87
+ end
88
+
89
+ def cancel_appointment(token, jsns)
90
+ soap_name = :CancelAppointmentRequest
91
+ body = init_hash_request(token, soap_name)
92
+ body[:Body][soap_name].merge!(jsns)
93
+ curl_request(body)
94
+ end
95
+
96
+ # -------------------------------
97
+ # CONTACT
98
+
99
+ def get_all_contacts(token, folder_id = nil)
100
+ body = init_hash_request(token, :GetContactsRequest)
101
+ unless folder_id.nil?
102
+ req = { l: folder_id }
103
+ body[:Body][:GetContactsRequest].merge!(req)
104
+ end
105
+ curl_request(body)
106
+ end
107
+
108
+ def create_contact(token, folder_id, attrs)
109
+ a = attrs.to_a.map(&A_NODE_PROC)
110
+ soap_name = :CreateContactRequest
111
+ req = { cn: { a: a, l: folder_id } }
112
+ body = init_hash_request(token, soap_name)
113
+ body[:Body][soap_name].merge!(req)
114
+ curl_request(body)
115
+ end
116
+
117
+ def modify_contact(token, id, attrs)
118
+ a = attrs.to_a.map(&A_NODE_PROC)
119
+ soap_name = :ModifyContactRequest
120
+ req = { cn: { a: a, id: id } }
121
+ body = init_hash_request(token, soap_name)
122
+ body[:Body][soap_name].merge!(req)
123
+ curl_request(body)
124
+ end
125
+
126
+ def create_group_contact(token, folder_id, attrs, members = [])
127
+ soap_name = :CreateContactRequest
128
+ a = attrs.to_a.map(&A_NODE_PROC)
129
+ req = { cn: { a: a, l: folder_id, m: members } }
130
+ body = init_hash_request(token, soap_name)
131
+ body[:Body][soap_name].merge!(req)
132
+ curl_request(body)
133
+ end
134
+
135
+ def modify_group_contact(token, id, attrs, members = [])
136
+ soap_name = :ModifyContactRequest
137
+ a = attrs.to_a.map(&A_NODE_PROC)
138
+ req = { cn: { a: a, id: id, m: members } }
139
+ body = init_hash_request(token, soap_name)
140
+ body[:Body][soap_name].merge!(req)
141
+ curl_request(body)
142
+ end
143
+
144
+ def contact_action(token, op, id, options = {})
145
+ soap_name = :ContactActionRequest
146
+ action = { op: op, id: id }.merge(options)
147
+ req = { action: action }
148
+ body = init_hash_request(token, soap_name)
149
+ body[:Body][soap_name].merge!(req)
150
+ curl_request(body)
151
+ end
152
+
153
+ # -------------------------------
154
+ # DOCUMENT
155
+
156
+ def save_document(token, l, options = {})
157
+ soap_name = :SaveDocumentRequest
158
+ body = init_hash_request(token, soap_name)
159
+ req = { doc: { l: l } }
160
+ req[:doc].merge!(options)
161
+ body[:Body][soap_name].merge!(req)
162
+ curl_request(body)
163
+ end
164
+
165
+ def item_action(token, op, id, options = {})
166
+ soap_name = :ItemActionRequest
167
+ action = { op: op, id: id }.merge(options)
168
+ req = { action: action }
169
+ body = init_hash_request(token, soap_name)
170
+ body[:Body][soap_name].merge!(req)
171
+ curl_request(body)
172
+ end
173
+
174
+ # -------------------------------
175
+ # FOLDER
176
+
177
+ def get_folder(token, id)
178
+ soap_name = :GetFolderRequest
179
+ body = init_hash_request(token, soap_name)
180
+ req = { folder: { l: id } }
181
+ body[:Body][soap_name].merge!(req)
182
+ curl_request(body)
183
+ end
184
+
185
+ def get_all_folders(token, view = nil, tr = nil)
186
+ soap_name = :GetFolderRequest
187
+ body = init_hash_request(token, soap_name)
188
+ req = { view: view, tr: tr }.reject { |_, v| v.nil? }
189
+ body[:Body][soap_name].merge!(req)
190
+ curl_request(body)
191
+ end
192
+
193
+ def create_folder(token, folder_options)
194
+ soap_name = :CreateFolderRequest
195
+ # folder = { l: parent_id, name: name, view: view, color: color }.merge(options)
196
+ req = { folder: folder_options }
197
+ body = init_hash_request(token, soap_name)
198
+ body[:Body][soap_name].merge!(req)
199
+ curl_request(body)
200
+ end
201
+
202
+ def folder_action(token, op, id, options = {})
203
+ soap_name = :FolderActionRequest
204
+ action = { op: op, id: id }.merge(options)
205
+ req = { action: action }
206
+ body = init_hash_request(token, soap_name)
207
+ body[:Body][soap_name].merge!(req)
208
+ curl_request(body)
209
+ end
210
+
211
+ def get_all_search_folders(token)
212
+ body = init_hash_request(token, :GetSearchFolderRequest)
213
+ curl_request(body)
214
+ end
215
+
216
+ # -------------------------------
217
+ # SEARCH FOLDER
218
+
219
+ def create_search_folder(token, name, query, types = 'messages', l = 1, color = nil, sort_by = nil)
220
+ search = {
221
+ name: name,
222
+ query: query,
223
+ types: types,
224
+ sortBy: sort_by,
225
+ color: color,
226
+ l: l
227
+ }.reject { |_, v| v.nil? }
228
+
229
+ req = { search: search }
230
+ body = init_hash_request(token, :CreateSearchFolderRequest)
231
+ body[:Body][:CreateSearchFolderRequest].merge!(req)
232
+ curl_request(body)
233
+ end
234
+
235
+ def modify_search_folder(token, id, query, types = 'messages')
236
+ search = {
237
+ id: id,
238
+ query: query,
239
+ types: types
240
+ }.reject { |_, v| v.nil? }
241
+
242
+ req = { search: search }
243
+ body = init_hash_request(token, :ModifySearchFolderRequest)
244
+ body[:Body][:ModifySearchFolderRequest].merge!(req)
245
+ curl_request(body)
246
+ end
247
+
248
+ # -------------------------------
249
+ # TASK
250
+
251
+ def create_task(token, folder_id, name, description = nil, options = {})
252
+ comp = { name: name }
253
+ comp.merge!(options) if !options.nil? && !options.empty?
254
+
255
+ task = { su: name, l: folder_id, inv: { comp: [comp] } }
256
+
257
+ task[:mp] = { ct: 'text/plain', content: description } unless description.nil?
258
+
259
+ req = { m: task }
260
+
261
+ body = init_hash_request(token, :CreateTaskRequest)
262
+ body[:Body][:CreateTaskRequest].merge!(req)
263
+ curl_request(body)
264
+ end
265
+
266
+ # -------------------------------
267
+ # SHARE
268
+
269
+ def create_mountpoint(token, link_option)
270
+ soap_name = :CreateMountpointRequest
271
+ req = { link: link_option }
272
+ body = init_hash_request(token, soap_name)
273
+ body[:Body][soap_name].merge!(req)
274
+ curl_request(body)
275
+ end
276
+
277
+ def get_share_info(token, options = {})
278
+ soap_name = :GetShareInfoRequest
279
+ req = { includeSelf: 0 }.merge!(options)
280
+ body = init_hash_request(token, soap_name, ACCOUNTSPACE)
281
+ body[:Body][soap_name].merge!(req)
282
+ curl_request(body)
283
+ end
284
+
285
+ def get_rights(token, rights)
286
+ soap_name = :GetRightsRequest
287
+ ace = rights.map { |r| { right: r } }
288
+ req = { ace: ace }
289
+ body = init_hash_request(token, soap_name, ACCOUNTSPACE)
290
+ body[:Body][soap_name].merge!(req)
291
+ curl_request(body)
292
+ end
293
+
294
+ def grant_rights(token, zid = nil, gt = nil, right = nil, d = nil, key = nil, pw = nil, deny = nil, chkgt = nil)
295
+ ace = {
296
+ zid: zid,
297
+ gt: gt,
298
+ right: right,
299
+ d: d,
300
+ key: key,
301
+ pw: pw,
302
+ deny: deny,
303
+ chkgt: chkgt
304
+ }.reject { |_, v| v.nil? }
305
+
306
+ req = { ace: ace }
307
+ body = init_hash_request(token, :GrantRightsRequest, ACCOUNTSPACE)
308
+ body[:Body][:GrantRightsRequest].merge!(req)
309
+ curl_request(body)
310
+ end
311
+
312
+ def revoke_rights(token, zid = nil, gt = nil, right = nil, d = nil, key = nil, pw = nil, deny = nil, chkgt = nil)
313
+ ace = {
314
+ zid: zid,
315
+ gt: gt,
316
+ right: right,
317
+ d: d,
318
+ key: key,
319
+ pw: pw,
320
+ deny: deny,
321
+ chkgt: chkgt
322
+ }.reject { |_, v| v.nil? }
323
+
324
+ req = { ace: ace }
325
+ body = init_hash_request(token, :RevokeRightsRequest, ACCOUNTSPACE)
326
+ body[:Body][:RevokeRightsRequest].merge!(req)
327
+ curl_request(body)
328
+ end
329
+
330
+ # -------------------------------
331
+ # MESSAGE
332
+
333
+ def get_msg(token, id, options = {})
334
+ req = { m: { id: id } }
335
+ req[:m].merge(options) unless options.empty?
336
+ body = init_hash_request(token, :GetMsgRequest)
337
+ body[:Body][:GetMsgRequest].merge!(req)
338
+ curl_request(body)
339
+ end
340
+
341
+ def msg_action(token, op, id, options = {})
342
+ action = { op: op, id: id }.merge(options)
343
+ req = { action: action }
344
+ body = init_hash_request(token, :MsgActionRequest)
345
+ body[:Body][:MsgActionRequest].merge!(req)
346
+ curl_request(body)
347
+ end
348
+
349
+ def send_msg(token, m)
350
+ req = { m: m }
351
+ body = init_hash_request(token, :SendMsgRequest)
352
+ body[:Body][:SendMsgRequest].merge!(req)
353
+ curl_request(body)
354
+ end
355
+
356
+ def add_msg(token, l, eml, d = nil, f = nil, tn = nil)
357
+ key = :AddMsgRequest
358
+ m = {
359
+ l: l,
360
+ d: d,
361
+ f: f,
362
+ tn: tn,
363
+ content: { _content: eml }
364
+ }.reject { |_, v| v.nil? }
365
+
366
+ req = { m: m }
367
+ body = init_hash_request(token, key)
368
+ body[:Body][key].merge!(req)
369
+
370
+ curl_request(body)
371
+ end
372
+
373
+ # -------------------------------
374
+ # TAG
375
+
376
+ def get_tag(token)
377
+ body = init_hash_request(token, :GetTagRequest)
378
+ curl_request(body)
379
+ end
380
+
381
+ def create_tag(token, name, color, rgb)
382
+ body = init_hash_request(token, :CreateTagRequest)
383
+ req = { tag: { name: name, color: color, rgb: rgb }.reject { |_, v| v.nil? } }
384
+ body[:Body][:CreateTagRequest].merge!(req)
385
+ curl_request(body)
386
+ end
387
+
388
+ def tag_action(token, op, id, options = {})
389
+ action = { op: op, id: id }.merge(options)
390
+ req = { action: action }
391
+ body = init_hash_request(token, :TagActionRequest)
392
+ body[:Body][:TagActionRequest].merge!(req)
393
+ curl_request(body)
394
+ end
395
+
396
+ # -------------------------------
397
+ # IDENTITY
398
+
399
+ def get_all_identities(token)
400
+ body = init_hash_request(token, :GetIdentitiesRequest, ACCOUNTSPACE)
401
+ curl_request(body)
402
+ end
403
+
404
+ def create_identity(token, name, attrs = [])
405
+ soap_name = :CreateIdentityRequest
406
+ req = { identity: { :@name => name, a: attrs.to_a.map(&A_NODE_PROC_ARROW_NAME) } }
407
+ body = init_hash_arrow_request(token, soap_name, ACCOUNTSPACE)
408
+ body[:Envelope][:Body][soap_name].merge!(req)
409
+ body_xml = Gyoku.xml(body, { :key_converter => :none })
410
+ # puts body_xml
411
+ # todo ne fonctionne pas en JS !
412
+ curl_xml(body_xml)
413
+ end
414
+
415
+ def modify_identity(token, id, attrs = [])
416
+ soap_name = :ModifyIdentityRequest
417
+ req = { identity: { :@id => id, a: attrs.to_a.map(&A_NODE_PROC_ARROW_NAME) } }
418
+ body = init_hash_arrow_request(token, soap_name, ACCOUNTSPACE)
419
+ body[:Envelope][:Body][soap_name].merge!(req)
420
+ body_xml = Gyoku.xml(body, { :key_converter => :none })
421
+ # puts body_xml
422
+ # todo ne fonctionne pas en JS !
423
+ curl_xml(body_xml)
424
+ end
425
+
426
+ def delete_identity(token, id)
427
+ soap_name = :DeleteIdentityRequest
428
+ req = { identity: { id: id } }
429
+ body = init_hash_request(token, soap_name, ACCOUNTSPACE)
430
+ body[:Body][soap_name].merge!(req)
431
+ curl_request(body)
432
+ end
433
+
434
+ # -------------------------------
435
+ # PREFERENCES
436
+
437
+ def get_prefs(token, *names)
438
+ req = { prefs: names.map { |name| { name: name } } }
439
+ body = init_hash_request(token, :GetPrefsRequest, ACCOUNTSPACE)
440
+ body[:Body][:GetPrefsRequest].merge!(req) if req.any?
441
+ curl_request(body)
442
+ end
443
+
444
+ def modify_prefs(token, prefs)
445
+ soap_name = :ModifyPrefsRequest
446
+ req = { pref: prefs.map { |pref, value| { name: pref, _content: value } } }
447
+ body = init_hash_request(token, soap_name, ACCOUNTSPACE)
448
+ body[:Body][soap_name].merge!(req) if req.any?
449
+ #puts body
450
+ #curl_request(body)
451
+ #puts SoapXmlBuilder.new(body).to_xml
452
+ # todo ne fonctionne pas en JS !
453
+ curl_xml(SoapXmlBuilder.new(body).to_xml)
454
+ end
455
+
456
+ def get_filter_rules(token)
457
+ soap_name = :GetFilterRulesRequest
458
+ body = init_hash_request(token, soap_name)
459
+ curl_request(body)
460
+ end
461
+
462
+ def modify_filter_rules(token, rules)
463
+ soap_name = :ModifyFilterRulesRequest
464
+ req = { filterRules: [{ filterRule: rules }] }
465
+ body = init_hash_request(token, soap_name)
466
+ body[:Body][soap_name].merge!(req)
467
+ curl_request(body)
468
+ end
469
+
470
+ def get_signatures(token)
471
+ soap_name = :GetSignaturesRequest
472
+ body = init_hash_request(token, soap_name, ACCOUNTSPACE)
473
+ curl_request(body)
474
+ end
475
+
476
+ def create_signature(token, jsns)
477
+ soap_name = :CreateSignatureRequest
478
+ body = init_hash_request(token, soap_name, ACCOUNTSPACE)
479
+ body[:Body][soap_name].merge!(jsns)
480
+ curl_request(body)
481
+ end
482
+
483
+ def modify_signature(token, jsns)
484
+ soap_name = :ModifySignatureRequest
485
+ body = init_hash_request(token, soap_name, ACCOUNTSPACE)
486
+ body[:Body][soap_name].merge!(jsns)
487
+ curl_request(body)
488
+ end
489
+
490
+ def delete_signature(token, id)
491
+ soap_name = :DeleteSignatureRequest
492
+ req = { signature: { id: id } }
493
+ body = init_hash_request(token, soap_name, ACCOUNTSPACE)
494
+ body[:Body][soap_name].merge!(req)
495
+ curl_request(body)
496
+ end
497
+
498
+ # -------------------------------
499
+ # GENERIC
500
+
501
+ def get_info(token, sections = 'mbox', rights = nil)
502
+ req = { rights: rights, sections: sections }.reject { |_, v| v.nil? }
503
+ body = init_hash_request(token, :GetInfoRequest, ACCOUNTSPACE)
504
+ body[:Body][:GetInfoRequest].merge!(req) if req.any?
505
+ curl_request(body)
506
+ end
507
+
508
+ def search(token, types = nil, offset = nil, limit = nil, sortBy = nil, query = nil, options = {})
509
+ soap_name = :SearchRequest
510
+ # types: conversation|message|contact|appointment|task|wiki|document
511
+ req = {
512
+ types: types,
513
+ offset: offset,
514
+ limit: limit,
515
+ sortBy: sortBy,
516
+ query: query
517
+ }.merge!(options)
518
+ req.reject! { |_, v| v.nil? }
519
+
520
+ body = init_hash_request(token, soap_name)
521
+ body[:Body][soap_name].merge!(req) if req.any?
522
+ curl_request(body)
523
+ end
524
+
525
+ private
526
+
527
+ def compute_preauth(mail, ts, domainkey)
528
+ data = "#{mail}|name|0|#{ts}"
529
+ digest = OpenSSL::Digest.new('sha1')
530
+ hmac = OpenSSL::HMAC.hexdigest(digest, domainkey, data)
531
+ hmac.to_s
532
+ end
533
+
534
+ def init_hash_request(token, soap_name, jsns = MAILSPACE)
535
+ {
536
+ Body: {
537
+ soap_name => { _jsns: jsns }
538
+ }
539
+ }.merge(hash_header(token))
540
+ end
541
+
542
+ def init_hash_arrow_request(token, soap_name, jsns = MAILSPACE)
543
+ { Envelope: {
544
+ :@xmlns => 'http://schemas.xmlsoap.org/soap/envelope/',
545
+ '@xmlns:urn' => 'urn:zimbra',
546
+ Header: {
547
+ context: {
548
+ authToken: token,
549
+ :@xmlns => BASESPACE,
550
+ format: {
551
+ :@type => 'js'
552
+ }
553
+ }
554
+ },
555
+ Body: {
556
+ soap_name => { :@xmlns => jsns }
557
+ }
558
+ }
559
+ }
560
+ end
561
+ end
562
+ end
563
+ end