Sympa SOAP Interface

The Simple Object Access Protocol (SOAP) API provides a interface for remote programmatic interaction.   It uses the same authentication scheme as the email and web interfaces so users will only be allowed to invoke commands based on their account permissions and role.   e.g.  list owners can send commands to their lists and listmasters can send commands for all lists. 


SOAP Interfaces

The Endpoints:

  1. Web Service Definition Language (WSDL)  – https://lists.illinois.edu/lists/wsdl 
    1. Robot example:   https://robotName.illinois.edu/lists.wsdl
  2. SOAP Interface – https://lists.illinois.edu/sympasoap
    1. Robot example:  https://robotName.illinois.edu/sympasoap

SOAP Scripts

A General Perl Example

truetrue#!–PERL–
# $Id: sympa_soap_client.pl.in 10083 2014-01-01 00:12:12Z sikeda $

# Sympa – SYsteme de Multi-Postage Automatique
#
# Copyright (c) 1997, 1998, 1999 Institut Pasteur & Christophe Wolfhugel
# Copyright (c) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
# 2006, 2007, 2008, 2009, 2010, 2011 Comite Reseau des Universites
# Copyright (c) 2011, 2012, 2013, 2014 GIP RENATER
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.

use strict;
#use SOAP::Lite +trace;
use SOAP::Lite;
use HTTP::Cookies;
use URI;
use Getopt::Long;

use lib ‘–modulesdir–‘;
# use Conf;
use Commands;
use Conf;
use Auth;
use SympaSession;
use Language;
use Log;
use mail;
use MIME::QuotedPrint;
use List;
use Message;
use admin;
use Config_XML;
use Family;
use report;
use File::Copy;
use tools;
use tt2;
use Sympa::Constants;

my ($reponse, @ret, $val, %fault);

my $usage = “$0 is a perl soap client for Sympa for TEST ONLY. Use it to illustrate how to
code access to features of Sympa soap server. Authentication can be done via
user/password or user cookie or as a trusted remote application

Usage: $0 <with the following options:>
–soap_url=<soap sympa server url>
–service=<a sympa service>
–trusted_application=<app name>
–trusted_application_password=<password>
–proxy_vars=<id=value,id2=value2>
–service_parameters=<value1,value2,value3>

OR usage: $0 <with the following options:>
–soap_url=<soap sympa server url>
–user_email=<email>
–user_password=<password>
–session_id=<sessionid>
–service=<a sympa service>
–service_parameters=<value1,value2,value3>

OR usage: $0 <with the following options:>
–soap_url=<soap sympa server url>
–cookie=<sympauser cookie string>

Example:
$0 –soap_url=<soap sympa server url> –cookie=sympauser=someone\@cru.fr
“;

my %options;
unless (&GetOptions(\%main::options, ‘soap_url=s’, ‘service=s’, ‘trusted_application=s’, ‘trusted_application_password=s’,’user_email=s’, ‘user_password=s’,’cookie=s’,’proxy_vars=s’,’service_parameters=s’,’session_id=s’)) {
printf “”;
}

my $soap_url = $main::options{‘soap_url’};
unless (defined $soap_url){
printf “error : missing soap_url parameter\n”;
printf $usage;
exit;
}

my $user_email = $main::options{‘user_email’};
my $user_password =$main::options{‘user_password’};
my $session_id = $main::options{‘session_id’};
my $trusted_application =$main::options{‘trusted_application’};
my $trusted_application_password =$main::options{‘trusted_application_password’};
my $proxy_vars=$main::options{‘proxy_vars’};
my $service=$main::options{‘service’};
my $service_parameters=$main::options{‘service_parameters’};
my $cookie=$main::options{‘cookie’};

if (defined $trusted_application) {
unless (defined $trusted_application_password) {
printf “error : missing trusted_application_password parameter\n”;
printf $usage;
exit;
}
unless (defined $service) {
printf “error : missing service parameter\n”;
printf $usage;
exit;
}
unless (defined $proxy_vars) {
printf “error : missing proxy_vars parameter\n”;
printf $usage;
exit;
}

&play_soap_as_trusted($soap_url, $trusted_application, $trusted_application_password, $service, $proxy_vars, $service_parameters);
}elsif($service eq ‘getUserEmailByCookie’){
&play_soap(soap_url => $soap_url,
session_id => $session_id,
service => $service);

}elsif(defined $cookie){
printf “error : get_email_cookie\n”;
&get_email($soap_url, $cookie);
exit;
}else{
unless (defined $session_id || (defined $user_email && defined $user_password)){
printf “error : missing session_id OR user_email+user_passwors parameters\n”;
printf $usage;
exit;
}

&play_soap(soap_url => $soap_url,
user_email => $user_email,
user_password => $user_password,
session_id => $session_id,
service => $service,
service_parameters => $service_parameters);
}

sub play_soap_as_trusted{
my $soap_url=shift;
my $trusted_application=shift;
my $trusted_application_password=shift;
my $service=shift;
my $proxy_vars=shift;
my $service_parameters=shift;

my $soap = new SOAP::Lite();
$soap->uri(‘urn:sympasoap’);
$soap->proxy($soap_url);

my @parameters;
@parameters= split(/,/,$service_parameters) if (defined $service_parameters);
my $p= join(‘,’,@parameters);
printf “calling authenticateRemoteAppAndRun( $trusted_application, $trusted_application_password, $proxy_vars,$service,$p)\n”;

my $reponse = $soap->authenticateRemoteAppAndRun( $trusted_application, $trusted_application_password, $proxy_vars,$service,\@parameters);
&print_result($reponse);
}

sub get_email {
my $soap_url=shift;
my $cookie=shift;

my ($service, $reponse, @ret, $val, %fault);

## Cookies management
# my $uri = new URI($soap_url);

# my $cookies = HTTP::Cookies->new(ignore_discard => 1,
# file => ‘/tmp/my_cookies’ );
# $cookies->load();
printf “cookie : %s\n”, $cookie;

my $soap = new SOAP::Lite();
#$soap->on_debug(sub{print@_});
$soap->uri(‘urn:sympasoap’);
$soap->proxy($soap_url);
#, cookie_jar =>$cookies);

print “\n\ngetEmailUserByCookie….\n”;
$reponse = $soap->getUserEmailByCookie($cookie);
&print_result($reponse);
exit;

}

sub play_soap{
my %param = @_;

my $soap_url = $param{‘soap_url’};
my $user_email = $param{‘user_email’};
my $user_password = $param{‘user_password’};
my $session_id = $param{‘session_id’};
my $service = $param{‘service’};
my $service_parameters = $param{‘service_parameters’};

my ($reponse, @ret, $val, %fault);

## Cookies management
# my $uri = new URI($soap_url);

my $cookies = HTTP::Cookies->new(ignore_discard => 1,
file => ‘/tmp/my_cookies’ );
$cookies->load();
printf “cookie : %s\n”, $cookies->as_string();

my @parameters;
@parameters= split(/,/,$service_parameters) if (defined $service_parameters);
my $p= join(‘,’,@parameters);
foreach my $tmpParam (@parameters) {
printf “param: %s\n”, $tmpParam;
}

# Change to the path of Sympa.wsdl
#$service = SOAP::Lite->service($soap_url);
#$reponse = $service->login($user_email,$user_password);
#my $soap = SOAP::Lite->service($soap_url);

my $soap = new SOAP::Lite() || die;
#$soap->on_debug(sub{print@_});
$soap->uri(‘urn:sympasoap’);
$soap->proxy($soap_url,
cookie_jar =>$cookies);

## Do the login unless a session_id is provided
if ($session_id) {
print “Using Session_id $session_id\n”;

}else {
print “LOGIN….\n”;

#$reponse = $soap->casLogin($soap_url);
$reponse = $soap->login($user_email,$user_password);
$cookies->save;
&print_result($reponse);
$session_id = $reponse->result;
}

## Don’t use authenticateAndRun for lists command

## Split parameters
my @parameters=split /,/,$service_parameters;

if ($service eq ‘lists’) {
printf “\n\nlists….\n”;
$reponse = $soap->lists();

}elsif ($service eq ‘subscribe’) {
printf “\n\n$service….\n”;
$reponse = $soap->subscribe(@parameters);

}elsif ($service eq ‘signoff’) {
printf “\n\n$service….\n”;
$reponse = $soap->signoff(@parameters);

}elsif ($service eq ‘add’) {
printf “\n\n$service….\n”;
$reponse = $soap->add(@parameters);

}elsif ($service eq ‘del’) {
printf “\n\n$service….\n”;
$reponse = $soap->del(@parameters);

}elsif ($service eq ‘getUserEmailByCookie’) {
printf “\n\n$service….\n”;
$reponse = $soap->getUserEmailByCookie($session_id);

}else {
printf “\n\nAuthenticateAndRun service=%s;(session_id=%s)….\n”,$service,$session_id;
$reponse = $soap->authenticateAndRun($user_email,$session_id,$service,\@parameters);
}

&print_result($reponse);

}

sub print_result {
my $r = shift;

# If we get a fault
if (defined $r && $r->fault) {
print “Soap error :\n”;
my %fault = %{$r->fault};
foreach $val (keys %fault) {
print “$val = $fault{$val}\n”;
}
}else {
if (ref( $r->result) =~ /^ARRAY/) {
#printf “R: $r->result\n”;
@ret = @{$r->result};
}elsif (ref $r->result) {
print “Pb “.($r->result).”\n”;
return undef;
}else {
@ret = $r->result;
}
&tools::dump_var(\@ret, 0, \*STDOUT);
}

return 1;
}


A Perl example to create a list (listmasters only)

[code language=”perl” title=”sympa-soap-createlist.pl” collapse=”true”]#!/usr/bin/perl
use strict;
use warnings;

$ENV{‘PERL_LWP_SSL_VERIFY_HOSTNAME’} = 0;

use SOAP::Lite;
use HTTP::Cookies;

my $config_email = “userID\@illinois.edu”;

# obtain password from user
use Term::ReadKey;
ReadMode 2;
print “Enter Password: “;
chomp(my $config_password = <STDIN>);
print “\n”;
ReadMode 0;

my $config_soapurl = “https://lists-dev.aces.illinois.edu/sympasoap”;

# Use a specific cookie jar so logins work – logging in sets a cookie
my $cookie_jar = HTTP::Cookies->new();

# If set to false or not set will send the user a ‘welcome to the list’
# message.
my $quiet = “true”;

# force outgoing connections to come from a specific interface by setting local_address
my $soap = SOAP::Lite->proxy($config_soapurl, cookie_jar => $cookie_jar );
$soap->default_ns(‘urn:sympasoap’);

# log in
my $som = $soap->login($config_email, $config_password);
die $som->faultstring if ($som->fault);

my $param_listname = “listName”;
my $param_subject = q(subject subject string

visibility noconceal

send owner

web_archive
access public

archive
period month
access private

clean_delay_queuemod 15

reply_to_header
value list

subscribe open

unsubscribe open,notify

review owner

invite default

custom_subject pre[% listname %]

digest 3 4:36

default_user_options
reception summary

shared_doc
d_edit default
d_read public
);
my $param_template = “soap-creation-template-folder”;
my $param_description = “created by userID via advanced soap”;
my $param_topic = “Other”;

my $create_object = $soap->createList( $param_listname, $param_subject, $param_template, $param_description, $param_topic );
if( $create_object->fault ){
die “Error creating list $param_listname, $param_subject, $param_template, $param_description, $param_topic\n: ” . $create_object->faultstring;
} else {
print “Created $param_listname, $param_subject, $param_template, $param_description, $param_topic\n”;
}

[/code]

A Shell example

[code language=”bash” title=”sympa-test-soap.sh” collapse=”true”]#!/bin/sh
#
# Test the SOAP API that uses sympa_soap_client.pl from above.

# This app can do anything
APP=application
PASS=password
USER=someone@illinois.edu
DOMAIN=sympa.illinois.edu
LIST=list_name@$DOMAIN
MAIL=someone@illinois.edu
TESTLIST=test-$$

SOAPCLIENT=/usr/share/sympa/bin/sympa_soap_client.pl

echo “Using SOAP API to $DOMAIN as application user [$APP]”
echo “With scenario rights of user [$USER]”
echo “”
echo “Testing list info”

$SOAPCLIENT –soap_url=https://$DOMAIN/sympasoap –trusted_application=$APP –trusted_application_password=”$PASS” –proxy_vars=”USER_EMAIL=$USER” –service=info –service_parameters=$LIST

echo “”
echo “Testing adding a subscriber”

$SOAPCLIENT –soap_url=https://$DOMAIN/sympasoap –trusted_application=$APP –trusted_application_password=”$PASS” –proxy_vars=”USER_EMAIL=$USER” –service=”add” –service_parameters=$LIST,$MAIL,”Test user”,0

echo “”
echo “Test self-subscription”

$SOAPCLIENT –soap_url=https://$DOMAIN/sympasoap –trusted_application=$APP –trusted_application_password=”$PASS” –proxy_vars=”USER_EMAIL=$MAIL” –service=”subscribe” –service_parameters=$LIST

echo “”
echo “Test subscriber details”

$SOAPCLIENT –soap_url=https://$DOMAIN/sympasoap –trusted_application=$APP –trusted_application_password=”$PASS” –proxy_vars=”USER_EMAIL=$MAIL” –service=”getDetails” –service_parameters=$LIST

echo “”
echo “List members”

$SOAPCLIENT –soap_url=https://$DOMAIN/sympasoap –trusted_application=$APP –trusted_application_password=”$PASS” –proxy_vars=”USER_EMAIL=$MAIL” –service=”review” –service_parameters=$LIST

echo “”
echo “Removing a subscriber”

$SOAPCLIENT –soap_url=https://$DOMAIN/sympasoap –trusted_application=$APP –trusted_application_password=”$PASS” –proxy_vars=”USER_EMAIL=$USER” –service=”del” –service_parameters=$LIST,$MAIL

echo “”
echo “Test self-unsubscription”

$SOAPCLIENT –soap_url=https://$DOMAIN/sympasoap –trusted_application=$APP –trusted_application_password=”$PASS” –proxy_vars=”USER_EMAIL=$MAIL” –service=”signoff” –service_parameters=$LIST

echo “”
echo “Creating a list”

$SOAPCLIENT –soap_url=https://$DOMAIN/sympasoap –trusted_application=$APP –trusted_application_password=”$PASS” –proxy_vars=”USER_EMAIL=$USER” –service=”createList” –service_parameters=$TESTLIST,”Test list”,uoa_announce,”Test list”,test

echo “”
echo “Deleting a list”

$SOAPCLIENT –soap_url=https://$DOMAIN/sympasoap –trusted_application=$APP –trusted_application_password=”$PASS” –proxy_vars=”USER_EMAIL=$USER” –service=”closeList” –service_parameters=$TESTLIST

[/code]

The SOAP Commands

The SOAP interface is still bound by the current Authentication and Authorization permission schemes so a user will run remote commands via their account.  Therefore, the actions a user can take will be restricted on their permission as list master, privileged owner, or normal owner.  Available functions include:  

command Function
login  user email and passwords are checked against Sympa user DB, or another backend.
casLogin  verify CAS proxy tickets against the CAS server
authenticateAndRun  useful for SOAP clients that can’t set an HTTP cookie ; they can provide both the Sympa session cookie and the requested command in a single cal
authenticateRemoteAppAndRun  equivalent of the previous command used in a trusted context (see trust_remote_applications)
lists  provides a list of available lists (authorization scenarios are applied)
complexLists  same as the previous feature, but provides a complex structure for each list
info  provides description informations about a given list
which  gets the list of subscription of a given user
complexWhich  same as previous command, but provides a complex structure for each list
amI  tells if a given user is member of a given list
review  lists the members of a given list
subscribe  subscribes the current user to a given list
signoff  current user is removed from a given list
add  used to add a given user to a given list (admin feature)
del  removes a given user from a given list (admin feature)
createList  creates a new mailing list (requires appropriate privileges)
closeList  closes a given mailing list (admin feature)

Source information: