postini 0.0.6 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +4 -0
- data/Manifest.txt +12 -26
- data/README.txt +11 -4
- data/Rakefile +27 -4
- data/features/development.feature +13 -0
- data/features/step_definitions/common_steps.rb +172 -0
- data/features/support/common.rb +29 -0
- data/features/support/env.rb +6 -0
- data/features/support/matchers.rb +11 -0
- data/lib/postini/automated_batch_service.rb +464 -0
- data/lib/postini/configuration_check.rb +25 -0
- data/lib/postini/endpoint_resolver_service.rb +41 -0
- data/lib/postini/endpoints.rb +26 -0
- data/lib/postini/exceptions.rb +85 -0
- data/lib/postini.rb +74 -102
- data/script/console +1 -1
- data/script/txt2html +5 -16
- data/spec/exceptions_spec.rb +19 -0
- data/spec/postini_spec.rb +5 -38
- data/spec/rcov.opts +1 -0
- data/spec/spec_helper.rb +1 -1
- data/tasks/rspec.rake +1 -19
- data/vendor/automatedbatch.wsdl +1 -1
- metadata +21 -54
- data/config/hoe.rb +0 -76
- data/config/requirements.rb +0 -15
- data/lib/postini/api/automatedbatch/AutomatedBatch.rb +0 -1244
- data/lib/postini/api/automatedbatch/AutomatedBatchDriver.rb +0 -216
- data/lib/postini/api/automatedbatch/AutomatedBatchMappingRegistry.rb +0 -1883
- data/lib/postini/api/automatedbatch/AutomatedBatchServiceClient.rb +0 -523
- data/lib/postini/api/endpointresolver/EndpointResolver.rb +0 -121
- data/lib/postini/api/endpointresolver/EndpointResolverDriver.rb +0 -51
- data/lib/postini/api/endpointresolver/EndpointResolverMappingRegistry.rb +0 -268
- data/lib/postini/api/endpointresolver/EndpointResolverServiceClient.rb +0 -38
- data/lib/postini/api.rb +0 -8
- data/lib/postini/domain.rb +0 -72
- data/lib/postini/helpers/attributes.rb +0 -94
- data/lib/postini/helpers.rb +0 -13
- data/lib/postini/user.rb +0 -91
- data/lib/postini/users/aliases.rb +0 -55
- data/lib/postini/version.rb +0 -9
- data/spec/attribute_helper_spec.rb +0 -47
- data/spec/domain_spec.rb +0 -36
- data/spec/user_spec.rb +0 -142
- data/website/index.html +0 -89
- data/website/index.txt +0 -60
- data/website/javascripts/rounded_corners_lite.inc.js +0 -285
- data/website/spam_box.png +0 -0
- data/website/stylesheets/screen.css +0 -143
- data/website/template.html.erb +0 -56
@@ -0,0 +1,464 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
module Postini
|
3
|
+
class AutomatedBatchService < Handsoap::Service
|
4
|
+
|
5
|
+
include ConfigurationCheck
|
6
|
+
|
7
|
+
endpoint Postini::Endpoints.automated_batch
|
8
|
+
|
9
|
+
on_create_document do |doc|
|
10
|
+
doc.alias 'aut', 'http://postini.com/PSTN/SOAPAPI/v2/automatedbatch'
|
11
|
+
end
|
12
|
+
|
13
|
+
def on_fault( fault )
|
14
|
+
exception = RemoteException.delegate( fault.reason )
|
15
|
+
|
16
|
+
# Handle specifics, translate to higher level exception
|
17
|
+
|
18
|
+
# or raise
|
19
|
+
raise exception
|
20
|
+
end
|
21
|
+
|
22
|
+
# public methods
|
23
|
+
|
24
|
+
# Associates an additional address with a user's primary email
|
25
|
+
# address. The alias receives the same filtering and shares the
|
26
|
+
# same User Ouarantine as the user’s primary email address.
|
27
|
+
#
|
28
|
+
# * confirm - If an existing user address is being overwritten to
|
29
|
+
# become an alias address, use confirm
|
30
|
+
#
|
31
|
+
# Raises a Postini::BatchError if something goes wrong
|
32
|
+
def add_alias( user_address, alias_address, confirm = true )
|
33
|
+
response = invoke("aut:addalias") do |message|
|
34
|
+
build_auth!( message )
|
35
|
+
message.add('userAddressOrId', user_address)
|
36
|
+
message.add('aliasAddress', alias_address)
|
37
|
+
message.add('confirm', 'confirm') if confirm
|
38
|
+
end
|
39
|
+
|
40
|
+
true
|
41
|
+
end
|
42
|
+
requires_configured :add_alias
|
43
|
+
|
44
|
+
# Adds the domain record +name+ to the organization
|
45
|
+
# +orgid+. Enclose +orgid+ in double quotes or preceded with a
|
46
|
+
# '\' symbol if it contains a quote ('), double quote ("),
|
47
|
+
# backslash (\), apostrophe, commas, #, = symbols.
|
48
|
+
#
|
49
|
+
# Raises a Postini::BatchException if something goes wrong
|
50
|
+
def add_domain( orgid, name )
|
51
|
+
response = invoke( "aut:adddomain" ) do |message|
|
52
|
+
build_auth!( message )
|
53
|
+
message.add('orgNameOrId', orgid )
|
54
|
+
message.add('args') do |args|
|
55
|
+
args.add('domain', name)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
true
|
60
|
+
end
|
61
|
+
requires_configured :add_domain
|
62
|
+
|
63
|
+
# Adds a user (+address+) to an organization (+org+). Enclose
|
64
|
+
# +orgid+ in double quotes or preceded with a
|
65
|
+
# '\' symbol if it contains a quote ('), double quote ("),
|
66
|
+
# backslash (\), apostrophe, commas, #, = symbols.
|
67
|
+
#
|
68
|
+
# Raises a Postini::BatchException if something foes wrong
|
69
|
+
def add_user( orgid, address, welcome = false )
|
70
|
+
response = invoke("aut:adduser") do |message|
|
71
|
+
build_auth!( message )
|
72
|
+
message.add('userAddress', address)
|
73
|
+
message.add('args') do |args|
|
74
|
+
args.add('org', orgid)
|
75
|
+
args.add('welcome', welcome)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
true
|
80
|
+
end
|
81
|
+
requires_configured :add_user
|
82
|
+
|
83
|
+
# This operation is an Service Management API’s AutomatedBatch
|
84
|
+
# utility. It checks the user’s email, API license key, and
|
85
|
+
# password authentication tokens used for connection and
|
86
|
+
# authorization validation between the web service and the client.
|
87
|
+
#
|
88
|
+
# * email - The email address entered by the user.
|
89
|
+
# * apiKey - A unique customer and product ID.
|
90
|
+
# * password -- The PMP password entered by the user.
|
91
|
+
#
|
92
|
+
# If the organization is configured for POP authorization, always
|
93
|
+
# use the administrator's email login and password which will be
|
94
|
+
# in the PMP format. An end user's POP password will fail.
|
95
|
+
def check_auth( email = nil, password = nil, api_key = nil )
|
96
|
+
response = invoke("aut:checkauth") do |message|
|
97
|
+
build_auth!( message, email, password, api_key )
|
98
|
+
end
|
99
|
+
|
100
|
+
return true
|
101
|
+
end
|
102
|
+
requires_configured :check_auth
|
103
|
+
|
104
|
+
# Removes the specified alias completely from the email security
|
105
|
+
# service.
|
106
|
+
def delete_alias( alias_address )
|
107
|
+
response = invoke("aut:deletealias") do |message|
|
108
|
+
build_auth!( message )
|
109
|
+
message.add('aliasAddress', alias_address)
|
110
|
+
end
|
111
|
+
|
112
|
+
return true
|
113
|
+
end
|
114
|
+
requires_configured :delete_alias
|
115
|
+
|
116
|
+
# Removes the domain from the organizational hierarchy. All the
|
117
|
+
# users for the domain needs to be removed first by #delete_user.
|
118
|
+
#
|
119
|
+
# Raises a Postini::BatchException if something goes wrong
|
120
|
+
def delete_domain( name )
|
121
|
+
response = invoke("aut:deletedomain") do |message|
|
122
|
+
build_auth!( message )
|
123
|
+
message.add('domainNameOrId', name)
|
124
|
+
end
|
125
|
+
|
126
|
+
true
|
127
|
+
end
|
128
|
+
requires_configured :delete_domain
|
129
|
+
|
130
|
+
# Delete a user record from the email security service.
|
131
|
+
#
|
132
|
+
# Raises a Postini::BatchExceptio if something goes wrong
|
133
|
+
def delete_user( address )
|
134
|
+
response = invoke("aut:deleteuser") do |message|
|
135
|
+
build_auth!( message )
|
136
|
+
message.add('userAddressOrId', address)
|
137
|
+
end
|
138
|
+
|
139
|
+
true
|
140
|
+
end
|
141
|
+
requires_configured :delete_user
|
142
|
+
|
143
|
+
# Retrieve the details of the domain from the email security
|
144
|
+
# service as a hash with the following keys:
|
145
|
+
#
|
146
|
+
# :org => string - Name of the parent org
|
147
|
+
# :substrip => true/false - Whether sub domain stripping in enabled
|
148
|
+
# :aliased_to => nil/string - Alias of another domain
|
149
|
+
# :aliased_as => array - List of domain aliases
|
150
|
+
# :id => integer - Domain id
|
151
|
+
# :name => string - Domain name
|
152
|
+
def display_domain( name )
|
153
|
+
response = invoke("aut:displaydomain") do |message|
|
154
|
+
build_auth!( message )
|
155
|
+
message.add('domainNameOrId', name )
|
156
|
+
end
|
157
|
+
|
158
|
+
parse_display_domain_results( response.document.xpath('//tns:displaydomainResponse', tns).first )
|
159
|
+
end
|
160
|
+
requires_configured :display_domain
|
161
|
+
|
162
|
+
# Retrieve the details of the user from the email securty service
|
163
|
+
# as a hash with following keys:
|
164
|
+
#
|
165
|
+
# :active => bool
|
166
|
+
# :address => string
|
167
|
+
# :approved_recipients => array
|
168
|
+
# :approved_senders => array
|
169
|
+
# :blocked_senders => array
|
170
|
+
# :create_method => integer
|
171
|
+
# :created_date => Time
|
172
|
+
# :filter_adult => string
|
173
|
+
# :filter_bulk => string
|
174
|
+
# :filter_getrich => string
|
175
|
+
# :filter_offers => string
|
176
|
+
# :filter_racial => string
|
177
|
+
# :initial_password => string
|
178
|
+
# :junkmail_filter => bool
|
179
|
+
# :lang_locale => string
|
180
|
+
# :lastmod_date => Time
|
181
|
+
# :message_encryption => string
|
182
|
+
# :message_limit => string
|
183
|
+
# :message_limited => bool
|
184
|
+
# :message_count => integer
|
185
|
+
# :notice_address => string
|
186
|
+
# :org => string
|
187
|
+
# :password => string
|
188
|
+
# :timezone => string
|
189
|
+
# :id => integer
|
190
|
+
# :virus_notify => string
|
191
|
+
# :virus_state => bool
|
192
|
+
# :weblocked => bool
|
193
|
+
# :welcome_count => integer
|
194
|
+
# :wireless_state => string
|
195
|
+
def display_user( address )
|
196
|
+
response = invoke("aut:displayuser") do |message|
|
197
|
+
build_auth!( message )
|
198
|
+
message.add('userAddressOrId', address)
|
199
|
+
end
|
200
|
+
|
201
|
+
parse_display_user_results( response.document.xpath('//tns:displayuserResponse', tns).first )
|
202
|
+
end
|
203
|
+
requires_configured :display_user
|
204
|
+
|
205
|
+
# Modify a domain by moving it to a new organization, setting or
|
206
|
+
# removing aliases, or enabling/disabling subdomain
|
207
|
+
# stripping. Changes are passed as a hash with the following keys:
|
208
|
+
#
|
209
|
+
# :org => string - New organization to move domain to
|
210
|
+
# :substrip => bool - New new value for substrip
|
211
|
+
# :aliases => array - Add new domain aliases to the array, to
|
212
|
+
# remove an existing domain alias prepend the name
|
213
|
+
# with a hyphen (-)
|
214
|
+
def modify_domain( name, changes = {} )
|
215
|
+
valid_changes = {}
|
216
|
+
valid_changes['neworg'] = changes[:org] if changes.has_key?(:org)
|
217
|
+
if changes.has_key?(:substrip)
|
218
|
+
valid_changes['substrip'] = ( changes[:substrip] == true ? 'yes' : 'no' )
|
219
|
+
end
|
220
|
+
valid_changes['alias'] = changes[:aliases].to_a.join(', ') if changes.has_key?(:aliases)
|
221
|
+
|
222
|
+
response = invoke("aut:modifydomain") do |message|
|
223
|
+
build_auth!( message )
|
224
|
+
message.add('domainNameOrId', name)
|
225
|
+
message.add('domainModifications') do |mods|
|
226
|
+
valid_changes.each do |k,v|
|
227
|
+
mods.add( k, v )
|
228
|
+
end
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
display_domain( name )
|
233
|
+
end
|
234
|
+
requires_configured :modify_domain
|
235
|
+
|
236
|
+
# Modify a user extensively by providing any of the following keys
|
237
|
+
# in the changes hash
|
238
|
+
#
|
239
|
+
# :active => bool
|
240
|
+
# :address => string (change the email address)
|
241
|
+
# :approved_recipients => array (full or changes)
|
242
|
+
# :approved_senders => array (full or changes)
|
243
|
+
# :blocked_senders => array (full or changes)
|
244
|
+
# :filter_adult => string
|
245
|
+
# :filter_bulk => string
|
246
|
+
# :filter_getrich => string
|
247
|
+
# :filter_offers => string
|
248
|
+
# :filter_racial => string
|
249
|
+
# :initial_password => string
|
250
|
+
# :junkemail_filter => bool
|
251
|
+
# :lang_locale => string
|
252
|
+
# :message_limit => integer
|
253
|
+
# :message_limited => bool
|
254
|
+
# :notice_address => string
|
255
|
+
# :org => string
|
256
|
+
# :password => string
|
257
|
+
# :virus_notify => bool
|
258
|
+
# :virus_state => bool
|
259
|
+
# :weblocked => bool
|
260
|
+
# :wireless_state => string
|
261
|
+
#
|
262
|
+
# Notes on array parameters: Provide the full set of values, or an
|
263
|
+
# array of diffs (new entries prepended with a plus (+) and
|
264
|
+
# entries to be removed prepended with a hyphen (-).
|
265
|
+
#
|
266
|
+
# Notes on *all* parameters: I don't use all of these, nor will I
|
267
|
+
# ever, so please test them well and report any bugs to me.
|
268
|
+
def modify_user( address, changes = {} )
|
269
|
+
valid_changes = {}
|
270
|
+
valid_changes[:orgid] = changes[:org] if changes.has_key?(:org)
|
271
|
+
|
272
|
+
# Vanilla string copies
|
273
|
+
[ :active, :address, :filter_adult, :filter_bulk, :filter_getrich,
|
274
|
+
:filter_offers, :filter_racial, :initial_password, :lang_locale,
|
275
|
+
:notice_address, :password, :wireless_state, :message_limit
|
276
|
+
].each do |k|
|
277
|
+
|
278
|
+
valid_changes[k] = changes[k] if changes.has_key?(k)
|
279
|
+
end
|
280
|
+
|
281
|
+
# Booleans need some special handling
|
282
|
+
[ :active, :junkemail_filter, :message_limited, :virus_notify,
|
283
|
+
:virus_state, :weblocked
|
284
|
+
].each do |k|
|
285
|
+
|
286
|
+
if changes.has_key?(k)
|
287
|
+
valid_changes[k] = ( changes[k] == true ? 'yes' : 'no' )
|
288
|
+
end
|
289
|
+
end
|
290
|
+
|
291
|
+
# Join the arrays
|
292
|
+
[ :approved_senders, :approved_recipients, :blocked_senders ].each do |k|
|
293
|
+
|
294
|
+
if changes.has_key?( k )
|
295
|
+
valid_changes[k] = changes[k].join(', ')
|
296
|
+
end
|
297
|
+
end
|
298
|
+
|
299
|
+
# pray
|
300
|
+
response = invoke("aut:modifyuser") do |message|
|
301
|
+
build_auth!( message )
|
302
|
+
message.add('userAddressOrId', address)
|
303
|
+
message.add('userModifications') do |mods|
|
304
|
+
valid_changes.each do |k,v|
|
305
|
+
mods.add( k.to_s, v )
|
306
|
+
end
|
307
|
+
end
|
308
|
+
end
|
309
|
+
|
310
|
+
address = valid_changes[:address] || address
|
311
|
+
|
312
|
+
display_user( address )
|
313
|
+
end
|
314
|
+
requires_configured :modify_user
|
315
|
+
|
316
|
+
# Determines if connections to the web service and the web service
|
317
|
+
# client are not blocked. It is a simple round trip test.
|
318
|
+
#
|
319
|
+
# * true - The connection is successful. If it fails, the
|
320
|
+
# development tool will throw either an error, or warning
|
321
|
+
# depending upon the type of failure.
|
322
|
+
# * false - To test the exception handling between the web service
|
323
|
+
# and the application, use test<false> which will
|
324
|
+
# complete the roundtrip between the servers and return
|
325
|
+
# a StatusException.
|
326
|
+
#
|
327
|
+
# The Endpoint Resolver web service is not used with the test command.
|
328
|
+
def test( pass = true )
|
329
|
+
response = invoke("aut:test") do |message|
|
330
|
+
message.add('should_work', pass)
|
331
|
+
end
|
332
|
+
|
333
|
+
parse_test_results( response.document.xpath('//tns:testResponse', tns).first )
|
334
|
+
end
|
335
|
+
requires_configured :test
|
336
|
+
|
337
|
+
private
|
338
|
+
|
339
|
+
def tns
|
340
|
+
{ 'tns' => 'http://postini.com/PSTN/SOAPAPI/v2/automatedbatch' }
|
341
|
+
end
|
342
|
+
|
343
|
+
def build_auth!( message, email = nil, password = nil, api_key = nil )
|
344
|
+
message.add('authElem') do |auth|
|
345
|
+
auth.add('apiKey', api_key || Postini.api_key)
|
346
|
+
auth.add('email', email || Postini.username )
|
347
|
+
auth.add('pword', password || Postini.password )
|
348
|
+
end
|
349
|
+
end
|
350
|
+
|
351
|
+
def to_array( string )
|
352
|
+
array = string.split(/[,\s+]/)
|
353
|
+
array.delete_if { |e| e == 'empty' }
|
354
|
+
array
|
355
|
+
end
|
356
|
+
|
357
|
+
# helpers
|
358
|
+
|
359
|
+
def parse_test_results( node )
|
360
|
+
node.xpath('./confirmation_message/text()').to_s
|
361
|
+
end
|
362
|
+
|
363
|
+
def parse_display_domain_results( node )
|
364
|
+
# <tns:displaydomainResponse>
|
365
|
+
# <domainRecord>
|
366
|
+
# <aliasedto>postini4r1.co.za</aliasedto>
|
367
|
+
# <aliasedfrom>postini4rone.co.za</aliasedfrom>
|
368
|
+
# <domainid>10000</domainid>
|
369
|
+
# <domainname>postini4r1.co.za</domainname>
|
370
|
+
# <org>postini-0.stage.example.org</org>
|
371
|
+
# <substrip>0</substrip>
|
372
|
+
# </domainRecord>
|
373
|
+
# </tns:displaydomainResponse>
|
374
|
+
|
375
|
+
data = {
|
376
|
+
:id => node.xpath('./domainRecord/domainid/text()').to_s.to_i,
|
377
|
+
:name => node.xpath('./domainRecord/domainname/text()').to_s,
|
378
|
+
:org => node.xpath('./domainRecord/org/text()').to_s,
|
379
|
+
:substrip => node.xpath('./domainRecord/substrip/text()').to_s == '1'
|
380
|
+
}
|
381
|
+
|
382
|
+
unless node.xpath('./domainRecord/aliasedto/text()').empty?
|
383
|
+
data[:aliased_to] = node.xpath('./domainRecord/aliasedto/text()').to_s
|
384
|
+
end
|
385
|
+
|
386
|
+
unless node.xpath('./domainRecord/aliasedfrom/text()').empty?
|
387
|
+
data[:aliased_from] = to_array( node.xpath('./domainRecord/aliasedfrom/text()').to_s )
|
388
|
+
end
|
389
|
+
|
390
|
+
data
|
391
|
+
end
|
392
|
+
|
393
|
+
def parse_display_user_results( node )
|
394
|
+
# <tns:displayuserResponse>
|
395
|
+
# <userRecord>
|
396
|
+
# <active>yes</active>
|
397
|
+
# <address>info@example.com</address>
|
398
|
+
# <approved_recipients>empty</approved_recipients>
|
399
|
+
# <approved_senders>empty</approved_senders>
|
400
|
+
# <blocked_senders>empty</blocked_senders>
|
401
|
+
# <create_method>3</create_method>
|
402
|
+
# <created_date>123456789</created_date>
|
403
|
+
# <filter_adult>moderately aggressive</filter_adult>
|
404
|
+
# <filter_bulk>leniently aggressive</filter_bulk>
|
405
|
+
# <filter_getrich>moderately aggressive</filter_getrich>
|
406
|
+
# <filter_offers>moderately aggressive</filter_offers>
|
407
|
+
# <filter_racial>moderately aggressive</filter_racial>
|
408
|
+
# <initial_password/>
|
409
|
+
# <junkmail_filter>on</junkmail_filter>
|
410
|
+
# <lang_locale/>
|
411
|
+
# <lastmod_date>123456789</lastmod_date>
|
412
|
+
# <message_count>0</message_count>
|
413
|
+
# <message_limit/>
|
414
|
+
# <message_limited>no</message_limited>
|
415
|
+
# <notice_address/>
|
416
|
+
# <orgid>Example Org Users</orgid>
|
417
|
+
# <password>randomhashrepresentation</password>
|
418
|
+
# <timezone>Europe/Lisbon</timezone>
|
419
|
+
# <user_id>1</user_id>
|
420
|
+
# <virus_notify>Organization default</virus_notify>
|
421
|
+
# <virus_state>on</virus_state>
|
422
|
+
# <weblocked>no</weblocked>
|
423
|
+
# <welcome_count>1</welcome_count>
|
424
|
+
# <wireless_state>unavailable</wireless_state>
|
425
|
+
# </userRecord>
|
426
|
+
# </tns:displayuserResponse>
|
427
|
+
|
428
|
+
data = {
|
429
|
+
:active => node.xpath('./userRecord/active/text()').to_s == 'yes',
|
430
|
+
:address => node.xpath('./userRecord/address/text()').to_s,
|
431
|
+
:approved_recipients => to_array( node.xpath('./userRecord/approved_recipients/text()').to_s ),
|
432
|
+
:approved_senders => to_array( node.xpath('./userRecord/approved_senders/text()').to_s ),
|
433
|
+
:blocked_senders => to_array( node.xpath('./userRecord/blocked_senders/text()').to_s ),
|
434
|
+
:create_method => node.xpath('./userRecord/create_method/text()').to_s.to_i,
|
435
|
+
:created_date => Time.at( node.xpath('./userRecord/created_date/text()').to_s.to_i ),
|
436
|
+
:filter_adult => node.xpath('./userRecord/filter_adult/text()').to_s,
|
437
|
+
:filter_bulk => node.xpath('./userRecord/filter_bulk/text()').to_s,
|
438
|
+
:filter_getrich => node.xpath('./userRecord/filter_getrich/text()').to_s,
|
439
|
+
:filter_offers => node.xpath('./userRecord/filter_offers/text()').to_s,
|
440
|
+
:filter_racial => node.xpath('./userRecord/filter_racial/text()').to_s,
|
441
|
+
:initial_password => node.xpath('./userRecord/initial_password/text()').to_s,
|
442
|
+
:junkmail_filter => node.xpath('./userRecord/junkmail_filter/text()').to_s == 'on',
|
443
|
+
:lang_locale => node.xpath('./userRecord/lang_local/text()').to_s,
|
444
|
+
:lastmod_date => Time.at( node.xpath('./userRecord/lastmod_date/text()').to_s.to_i ),
|
445
|
+
:message_encryption => node.xpath('./userRecord/message_encryption/text()').to_s,
|
446
|
+
:message_limit => node.xpath('./userRecord/message_limit/text()').to_s,
|
447
|
+
:message_limited => node.xpath('./userRecord/message_limited/text()').to_s == 'yes',
|
448
|
+
:message_count => node.xpath('./userRecord/message_count/text()').to_s.to_i,
|
449
|
+
:notice_address => node.xpath('./userRecord/notice_address/text()').to_s,
|
450
|
+
:org => node.xpath('./userRecord/orgid/text()').to_s,
|
451
|
+
:password => node.xpath('./userRecord/password/text()').to_s,
|
452
|
+
:timezone => node.xpath('./userRecord/timezone/text()').to_s,
|
453
|
+
:id => node.xpath('./userRecord/user_id/text()').to_s,
|
454
|
+
:virus_notify => node.xpath('./userRecord/virus_notify/text()').to_s,
|
455
|
+
:virus_state => node.xpath('./userRecord/virus_state/text()').to_s,
|
456
|
+
:weblocked => node.xpath('./userRecord/weblocked/text()').to_s == 'yes',
|
457
|
+
:welcome_count => node.xpath('./userRecord/welcome_count/text()').to_s.to_i,
|
458
|
+
:wireless_state => node.xpath('./userRecord/wireless_state/text()').to_s
|
459
|
+
}
|
460
|
+
|
461
|
+
data
|
462
|
+
end
|
463
|
+
end
|
464
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Postini
|
2
|
+
|
3
|
+
# Mixin with a method decorator that prevents calls from being made
|
4
|
+
# if the library is not properly configured.
|
5
|
+
module ConfigurationCheck
|
6
|
+
|
7
|
+
def self.included( base )
|
8
|
+
base.extend( ClassMethods )
|
9
|
+
end
|
10
|
+
|
11
|
+
module ClassMethods
|
12
|
+
|
13
|
+
def requires_configured( method_name )
|
14
|
+
class_eval <<-EOF, __FILE__, __LINE__
|
15
|
+
alias #{method_name}_original #{method_name}
|
16
|
+
def #{method_name}( *args )
|
17
|
+
raise Postini::NotConfigured, "Cannot call #{method_name} if not configured" unless Postini.configured?
|
18
|
+
|
19
|
+
#{method_name}_original( *args )
|
20
|
+
end
|
21
|
+
EOF
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Postini
|
2
|
+
class EndpointResolverService < Handsoap::Service
|
3
|
+
|
4
|
+
include ConfigurationCheck
|
5
|
+
|
6
|
+
endpoint Postini::Endpoints.resolver
|
7
|
+
|
8
|
+
on_create_document do |doc|
|
9
|
+
doc.alias 'end', 'https://api-meta.postini.com/api2/endpointresolver'
|
10
|
+
end
|
11
|
+
|
12
|
+
# public methods
|
13
|
+
|
14
|
+
def get_service_endpoint( email, service = "v2AutomatedBatch" )
|
15
|
+
response = invoke("end:GetServiceEndpoint") do |message|
|
16
|
+
message.add( "apiKey", Postini.api_key )
|
17
|
+
message.add( "email", email )
|
18
|
+
message.add( "service", service )
|
19
|
+
end
|
20
|
+
|
21
|
+
parse_get_service_endpoint_result( response.document.xpath('//tns:GetServiceEndpointResponse', tns).first )
|
22
|
+
end
|
23
|
+
requires_configured :get_service_endpoint
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def tns
|
28
|
+
{ 'tns' => 'http://postini.com/PSTN/SOAPAPI/v2/endpointresolver' }
|
29
|
+
end
|
30
|
+
|
31
|
+
# helpers
|
32
|
+
|
33
|
+
def parse_get_service_endpoint_result( node )
|
34
|
+
#<tns:GetServiceEndpointResponse>
|
35
|
+
# <EndpointURI>https://api-s200.postini.com/api2/automatedbatch</EndpointURI>
|
36
|
+
#</tns:GetServiceEndpointResponse>
|
37
|
+
|
38
|
+
node.xpath('./EndpointURI/text()').to_s
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Postini
|
2
|
+
|
3
|
+
# Our endpoints for use by handsoap
|
4
|
+
class Endpoints
|
5
|
+
|
6
|
+
class << self
|
7
|
+
|
8
|
+
def resolver
|
9
|
+
{
|
10
|
+
:uri => "https://api-meta.postini.com/api2/endpointresolver",
|
11
|
+
:version => 1
|
12
|
+
}
|
13
|
+
end
|
14
|
+
|
15
|
+
def automated_batch
|
16
|
+
raise NotConfigured, "automatedbatch service endpoint requires system number" if Postini.system_number.nil?
|
17
|
+
|
18
|
+
{
|
19
|
+
:uri => "https://api-s#{Postini.system_number}.postini.com/api2/automatedbatch",
|
20
|
+
:version => 1
|
21
|
+
}
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
module Postini
|
2
|
+
|
3
|
+
# Parent class of our exception hierarchy
|
4
|
+
class Error < ::StandardError; end
|
5
|
+
|
6
|
+
class DuplicateAddress < Error; end
|
7
|
+
|
8
|
+
class UnknownDomain < Error; end
|
9
|
+
|
10
|
+
# Raised if the #Postini library is not sufficiently configured.
|
11
|
+
class NotConfigured < Error; end
|
12
|
+
|
13
|
+
# Handle exceptions thrown by Postini
|
14
|
+
class RemoteException < Error
|
15
|
+
|
16
|
+
attr_reader :type, :message, :request_id
|
17
|
+
|
18
|
+
class << self
|
19
|
+
|
20
|
+
# Find the correct sub-class and pass the exception on
|
21
|
+
def delegate( reason )
|
22
|
+
if reason =~ /^(\w+):/
|
23
|
+
type = $1
|
24
|
+
type << 'Exception' unless type =~ /Exception$/
|
25
|
+
|
26
|
+
if Postini.const_defined?( type )
|
27
|
+
return Postini.const_get( type ).new( reason )
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
return new( reason )
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def initialize( reason )
|
36
|
+
|
37
|
+
if reason =~ /^(\w+):(.*)\(Request ID ([0-9A-F\-]{36})\)$/
|
38
|
+
@type = $1
|
39
|
+
@message = $2.strip
|
40
|
+
@request_id = $3
|
41
|
+
else
|
42
|
+
@message = reason
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def inspect
|
47
|
+
"#{self.class} Type: #{@type}, Message: #{@message}, Request ID: #{@request_id}"
|
48
|
+
end
|
49
|
+
|
50
|
+
def to_s
|
51
|
+
inspect
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
# Intentionally thrown exception, used to test connection level
|
56
|
+
# operation and the ability to send exceptions.
|
57
|
+
class StatusException < RemoteException; end
|
58
|
+
|
59
|
+
# Specified API license key blocked for administrative reasons
|
60
|
+
class AdminBlockException < RemoteException; end
|
61
|
+
|
62
|
+
# Invalid authentication tokens and other auth errors
|
63
|
+
class AuthenticationException < RemoteException; end
|
64
|
+
|
65
|
+
# Exceptions based on those given by the batch commandline interface
|
66
|
+
class BatchException < RemoteException; end
|
67
|
+
|
68
|
+
# Internal exceptions caused by server-wide problems
|
69
|
+
class InternalException < RemoteException; end
|
70
|
+
|
71
|
+
# One or more element values does not validate
|
72
|
+
class InvalidValueException < RemoteException; end
|
73
|
+
|
74
|
+
# Malformed API license key
|
75
|
+
class MalformedKeyException < RemoteException; end
|
76
|
+
|
77
|
+
# One or more required elements is missing from the input
|
78
|
+
class MissingElementException < RemoteException; end
|
79
|
+
|
80
|
+
# Specified API license key does not exist
|
81
|
+
class NoSuchKeyException < RemoteException; end
|
82
|
+
|
83
|
+
# Exceptions caused by unhandled server-side problems
|
84
|
+
class UnknownInternalException < RemoteException; end
|
85
|
+
end
|