postini 0.0.6 → 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/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
|