This is the code that I'm having trouble with... Adding domains works, checking for availablility works. Inventory queries work.
Adding and/or deleting mailboxes does not work. 'major_text' => 'Unsupported action: query for object: manualprovision', deleting domains does not work. 'response_text' => 'Authorization failed for user [baremetal]. There are no actions to perform.', Copyright... AFAIK, the starting point was public domain and sent to me by Jason Slaughter at Tucows, assuming it was, I release my enhancements to the public domain. Note that you will need to change the RSP specific constants: use constant USER_ID => 70571; use constant CONTACT_ID => 350349; -Tom #! /usr/bin/perl # # This is a trivially simple example of some functions that might # be used to provision Tucows Email Defense services. This should # only be used as a reference until official Tucows client code # is made available. # # It is suggested that unless you want to link these services to # existing non-domain Tucows products (Certs, Tucows Email, DNS), # then all Email Defense services should be created under the same # user account in the Tucows system. Create one user account in # the Tucows RWI (http://resellers2.opensrs.net/resellers) # and hard-code the values of $user_id and $contact_id in the # create/order API command, or, hard-code $user_id and add a new # contact for each domain added. # # End-users will have their own separate usernames that are the same # as their email username (defined here in the @users array). use strict; use Getopt::Std; use vars qw($opt_a $opt_t $opt_i $opt_u $opt_d $opt_q $opt_D $opt_P $opt_A $opt_R); die "no arguments!?" unless (@ARGV); getopts('dqatiuDPAR') or die "no commands?"; # -i = details for this inventory item number # -u = contacts for the userid # -a = service available for this domain? # -t = test something... # -d = debug mode... extra diagnostic displays # -q = query inventory... just gets a list of item numbers.. # -D = DELETE inventory items # -P domain mx_host user [user user ...] PROVISION service # -A (add) inventory user [user user ...] - add mailboxes # -R (remove) inventory user [user user ...] - remove mailboxes BEGIN { do "/home/opensrs-client-2.77/OpenSRS.conf"; } use constant USER_ID => 70571; use constant CONTACT_ID => 350349; use Data::Dumper; use strict; use lib $PATH_LIB; use OpenSRS::TPP_Client; use OpenSRS::ResponseConverter; use OpenSRS::Util::Common qw(send_email build_select_menu build_select_menu3 build_country_list CODE_2_Country); my $TPP_Client = new OpenSRS::TPP_Client( %OPENSRS, response_converter => new OpenSRS::ResponseConverter(), ); $TPP_Client->login; sub purchase_email_defense { my ($domain, $mx_server, @users) = @_; # why pass these as parameters if they are supposed to be hard coded? my $user_id = USER_ID; # antispam my $contact_id = CONTACT_ID; my $mx_preference = 1; # another, duh, why pass this. (if it was a list...) my $mx_port = 25; my $xcp_request = { version => 1.4.0, action => "create", object => "order", requestor => { username => $OPENSRS{'username'} }, attributes => { service => 'emaildefense', user_id => $user_id, client_reference => 'bulk_procurement-baremetal', handling => 'process', contacts => [ { contact_id => $contact_id } ], create_items => [ { service => 'emaildefense', object_type => 'manualprovision', order_item_type => 'new', product_data => { domain => $domain, feature_set => [ "AntiSpam" ], mtas => [ { preference => $mx_preference , port => $mx_port, host => $mx_server , }, ], accounts => [ # { # name => $username, # role => 'end_user' # } ], }, contact_set => { owner => 0, } } ], } }; # tweaks. The first user gets a password of antispam and the domain_admin # role. No one else gets passwords, which means they can't login directly. for (my $i = 0; $i < scalar(@users); $i++) { $xcp_request->{'attributes'}{'create_items'}[0]{'product_data'}{'accounts'}[$i]{'name'} = $users[$i]; $xcp_request->{'attributes'}{'create_items'}[0]{'product_data'}{'accounts'}[$i]{'role'} = $i ? 'end_user' : 'domain_admin'; $xcp_request->{'attributes'}{'create_items'}[0]{'product_data'}{'accounts'}[$i]{'password'} = '6yBLKe' if ($i == 0); # first user } my $response = $TPP_Client->send_cmd($xcp_request); print Dumper($response); if (1 == $response->{'is_success'}) { return 1; } else { error_log($response->{'response_text'}); return 0; } } sub check_email_defense_availability { my $domain = shift; my $xcp_request = { version => 1.3, action => 'check', object => 'emaildefense.domain', requestor => { username => $OPENSRS{'username'} }, attributes => { service => 'emaildefense', product_data => { domain => $domain } } }; my $response = $TPP_Client->send_cmd($xcp_request); print Dumper(\$response),"\n"; if (1 == $response->{'is_success'}) { if (1 == $response->{'attributes'}->{'product_data'}->{'is_available'}) { return 1; } } else { error_log($response->{'response_text'}); } return 0; } sub cancel_email_defense { my $domain = shift; my $xcp_request = { 'protocol' => 'TPP', 'object' => 'inventory_item.emaildefense', 'version' => '1.4.0', 'action' => 'delete', 'requestor' => { 'username' => $OPENSRS{'username'} }, 'attributes' => { 'inventory_items' => [ { 'inventory_item_id' => '13565' } ] } }; } # # Do something useful here that calls the functions above # if ( 0 ) { } elsif($opt_P) { my ($domain, $mx, @users) = @ARGV; die "$domain doesn't look like a domain name!" unless ($domain =~ m/\.[a-z0-9\-]{2,4}$/i ); die "$mx doesn't look like a mailhost name!" unless ($mx =~ m/\.[a-z0-9\-]{2,4}$/i ); die "you must specify at least one mailbox" unless @users; purchase_email_defense( $domain, $mx, @users); } elsif($opt_A) { my ($inv, @users) = @ARGV; die "first parameter doesn't look like an inventory number" unless ($inv =~ m/^\d+$/); die "can't add zero mailboxes!?" unless @users; add_mailboxes($inv,@users); } elsif($opt_R) { my ($inv, @users) = @ARGV; die "first parameter doesn't look like an inventory number" unless ($inv =~ m/^\d+$/); die "can't remove zero mailboxes!?" unless @users; remove_mailboxes($inv,@users); } elsif($opt_q) { inventory( ) if ($opt_q); } else { foreach my $arg (@ARGV) { if ($opt_a) { my $avail = check_email_defense_availability($arg); print "availability for $arg = $avail\n"; } if ($opt_t) { mytest(); exit; } inventory( item_id => $arg ) if ($opt_i); inventory( contact_id => $arg ) if $opt_u; delete_domain( $arg ) if ($opt_D); print "done arg: $arg\n"; } } print "Done.\n"; exit; sub inventory { my %params = @_; my $att = { query_name => 'inventory_items.created.by_user_id', conditions => [ { type => 'simple', field => 'user_id', operand => { eq => USER_ID }, } ], }; $att = { query_name => 'inventory_item.by_id', conditions => [ { type => 'simple', field => 'inventory_item_id', operand => { eq => $params{item_id} }, }], } if ($params{item_id}); $att = { query_name => 'contacts.by_user_id', conditions => [ { type => 'simple', field => 'user_id', operand => { eq => $params{contact_id} }, } ] } if ($params{contact_id}); my $xcp_request = { 'protocol' => 'TPP', 'object' => 'query', 'version' => '1.4.0', 'action' => 'execute', 'requestor' => { 'username' => $OPENSRS{'username'} }, attributes => $att, }; my $response = $TPP_Client->send_cmd($xcp_request); use Data::Dumper; if ($opt_d or !$response->{is_success} ) { print "inventory response= ", Dumper(\$response),"\n"; print "inventory request= ", Dumper(\$xcp_request),"\n" } my $ref = $response->{attributes}->{result}; if (!$ref) { print "No inventory, have you provisioned anything?\n"; } else { if (! %params) { # just get the item numbers.. foreach my $hr (@$ref) { printf "%d %s (%s)\n", $hr->{inventory_item_id}, $hr->{description}, $hr->{service}; } } elsif ($params{item_id}) { foreach my $hr (@$ref) { printf "inventory: %d\n", $hr->{inventory_item_id}; printf "description: %s\n", $hr->{description}; foreach my $mta (@{$hr->{product_data}->{mtas}}) { printf "mx: %s:%d\n", $mta->{host}, $mta->{port}; } foreach my $account (@{$hr->{product_data}->{accounts}}) { my $feat = join(' ', @{$account->{feature_set}}); printf " %s/%s (%s) %s\n", $account->{name}, $account->{password}, $account->{role}, $feat; } } } elsif ($params{contact_id}) { # print "inventory response= ", Dumper(\$response),"\n"; foreach my $contact (@$ref) { printf "----\n"; printf "user_id: %d\n", $contact->{user_id}; printf "contact_id: %d\n", $contact->{contact_id}; printf "parent_id: %d\n", $contact->{parent_id}; printf "name: %s %s\n", $contact->{first_name}, $contact->{last_name}; printf "email: %s\n", $contact->{email}; } } else { print "ugh, what parameter got specified!?\n"; } } } sub delete_domain { my ($inv_no) = @_; my $xcp_request = { 'protocol' => 'TPP', 'object' => 'inventory_item.emaildefense', 'version' => '1.4.0', 'action' => 'delete', 'requestor' => { 'username' => $OPENSRS{'username'} }, 'attributes' => { 'inventory_items' => [ { 'inventory_item_id' => $inv_no } ] } }; my $response = $TPP_Client->send_cmd($xcp_request); print "delete request= ", Dumper(\$xcp_request),"\n" unless ($response->{is_success}); print "delete response= ", Dumper(\$response),"\n"; } sub add_mailboxes { my ($inventory, @boxes) = @_; my $xcp_request = { 'protocol' => 'TPP', 'object' => 'order', 'version' => '1.4.0', 'action' => 'create', 'requestor' => { 'username' => $OPENSRS{'username'} }, 'attributes' => { 'contacts' => [ { 'contact_id' => CONTACT_ID } ], 'create_items' => [ { 'product_data' => { 'update_feature_set' => {}, 'add_accounts' => { # 'feature_set' => [ 'AntiSpam' ], 'accounts' => [ ] } }, 'object_type' => 'manualprovision', 'contact_set' => { 'owner' => '0' }, # ref to contacts above 'orderitem_type' => 'upgrade', # new/upgrade/downgrade 'service' => 'emaildefense', 'inventory_item_id' => $inventory } ], 'user_id' => USER_ID, 'service' => 'emaildefense', 'handling' => 'process' } }; foreach my $mbox (@boxes) { my $ref = $xcp_request->{attributes}->{create_items}->[0]->{product_data}->{add_accounts}->{accounts}; die "reference extraction failed" unless $ref; push (@$ref, { name => $mbox, role => 'end_user' } ); } my $response = $TPP_Client->send_cmd($xcp_request); print "delete request= ", Dumper(\$xcp_request),"\n" unless ($response->{is_success}); print "delete response= ", Dumper(\$response),"\n"; } sub remove_mailboxes { my ($inv, @boxes) = @_; my $xcp_request = { 'protocol' => 'TPP', 'object' => 'order', 'version' => '1.4.0', 'action' => 'create', 'requestor' => { 'username' => $OPENSRS{'username'} }, 'attributes' => { 'user_id' => USER_ID, 'service' => 'emaildefense', 'handling' => 'process', 'contacts' => [ { 'contact_id' => CONTACT_ID } ], 'data' => 'full', 'create_items' => [ { 'object_type' => 'manualprovision', 'orderitem_type' => 'downgrade', 'service' => 'emaildefense', 'inventory_item_id' => $inv, 'contact_set' => { 'owner' => '0' }, 'product_data' => { 'delete_accounts' => { 'accounts' => [] }, # fill in later 'update_feature_set' => {} }, } ], } }; foreach my $mbox (@boxes) { my $ref = $xcp_request->{attributes}->{create_items}->[0]->{product_data}->{delete_accounts}->{accounts}; die "reference extraction failed" unless $ref; push (@$ref, { name => $mbox } ); } my $response = $TPP_Client->send_cmd($xcp_request); print "delete request= ", Dumper(\$xcp_request),"\n" unless ($response->{is_success}); print "delete response= ", Dumper(\$response),"\n"; }