| Welcome to the Zimbra :: Forums! | |
Welcome, if you would like to post a comment please register.
We also encourage you to explore all things Zimbra with our team and members of the community.
|  | | 
07-02-2007, 10:12 PM
| | | [SOLVED] Simple SOAP Admin Example In PHP I have been reading through the posts like mad and looked all over Google but I can't find a super simple stripped down PHP example of how to add an account to Zimbra via SOAP *with* actual PHP source code. This would be a really great addition to the Wiki that once I get something actually working I would be happy to add to it so other people don't have all the wasted time I have looking for something that just doesn't exist.... Anyway, enough ranting  Anyway, I don't know jack about SOAP in PHP and I'm doing my best to guess my way through this with little luck. I'm sure all I am missing is something really silly but I just can't seem to get this working. Can someone please enlighten me as to what I am doing wrong? Thanks in advance!
Here is my PHP script: PHP Code: <?PHP
$client = new SoapClient(NULL,
array
(
"location" => "https://mail.myzimbrasever.com/service/soap/",
"uri" => "urn:zimbra"
)
);
print(
$client->__call("AuthRequest",
array
(
new SoapParam("admin", "name"),
new SoapParam("mypass", "password")
),
array
(
"uri" => "urn:zimbra",
"soapaction" => "urn:zimbra#AuthRequest"
)
)
. "\n");
?> And here is my completely useless output: Code: <br />
<b>Fatal error</b>: Uncaught SoapFault exception: [HTTP] Could not connect to host in /mnt/Web/htdocs/SOAP/soap.php:22
Stack trace:
#0 [internal function]: SoapClient->__doRequest('<?xml version="...', 'https://mail.myzim....', 'urn:zimbra#Auth...', 1, 0)
#1 /mnt/Web/htdocs/SOAP/soap.php(22): SoapClient->__call('AuthRequest', Array, Array)
#2 {main}
thrown in <b>/mnt/Web/htdocs/SOAP/soap.php</b> on line <b>22</b><br /> | 
07-02-2007, 10:37 PM
| | | OK, I have made a little bit of progress...well I think anyway: PHP Code: <?PHP
$client = new SoapClient(NULL,
array
(
"location" => "https://mail.myzimbraserver.com:7071/service/soap/",
"uri" => "urn:zimbra"
)
);
print(
$client->__call("AuthRequest",
array
(
new SoapParam("admin", "name"),
new SoapParam("mypass", "password")
),
array
(
"uri" => "urn:zimbraAdmin",
"soapaction" => "urn:zimbraAdmin#AuthRequest"
)
)
. "\n");
?>
Which now gives me the same messy output but start off with: Code: Fatal error: Uncaught SoapFault exception: [soap:Receiver] system failure: Request not allowed on port 7071 Anyone know what I'm still doing wrong here?
Thanks! | 
07-05-2007, 07:27 AM
| | | Thanks! That got me to the point to where I could get an account to be added using the code below but I am having a hard time passing attributes i.e. COS. I know what the SOAP packet should look like but I can't get the PHP SOAP functions to put the attribute in correctly. Using CURL would be 100x easier because I could just get the traces from zmprov and then just toss in the values I needed to substitue where appropriate.
I want to send (I got my object ID from "zmproc gc basicemail"):
<a n="zimbraCOSid">f070eede-c0c5-4867-a158-1f35f1c39e15</a>
But what my code is sending is:
<a n="zimbraCOSid">f070eede-c0c5-4867-a158-1f35f1c39e15</a n="zimbraCOSid">
I get back a:
<soap:Reason><soap:Text>parse error: Error on line 2 of document : The end-tag for element type "a" must end with a '>' delimiter. Nested exception: The end-tag for element type "a" must end with a '>' delimiter.</soap:Text></soap:Reason>
I can't seem to get the closing </a> to not include the n="zimbraCOSid". I am also wondering if the SOAP PHP functions are doing anything special (other than frustrating me) or if I can just make a string of the XML/SOAP that I want to send and just use CURL to send it over. Frankly, all of my problems have come from trying to guess how the PHP SOAP lib works, not how Zimbra's SOAP interface works... Any insight on how to fix my closing tag problem and/or if CURL can do it on its own would be greatly appreciated. Thanks! Code: function ZimbraAdminCreateAccount($Trace, $ServerAddress, $AdminUserName, $AdminPassword, $NewUserName, $NewPassword)
{
$client = new SoapClient(NULL,
array
(
"location" => "https://$ServerAddress:7071/service/admin/soap",
"uri" => "urn:zimbra",
"trace" => $Trace,
"exceptions" => "1",
"soap_version" => SOAP_1_1,
"style" => SOAP_RPC,
"use" => SOAP_LITERAL
)
);
try
{
$ZimbraSession = $client->__soapCall("AuthRequest",
array
(
new SoapParam("$AdminUserName", "name"),
new SoapParam("$AdminPassword", "password")
),
array
(
"uri" => "urn:zimbraAdmin",
"soapaction" => "urn:zimbraAdmin#AuthRequest"
),
new SoapHeader("urn:zimbra", "context")
);
}
catch (SoapFault $exception)
{
echo "Login exception caught<br><br>";
echo htmlentities($client->__getLastRequest()) . "<br><br>";
echo htmlentities($client->__getLastResponse()) . "<br><br>";
echo $exception . "<br><br>";
}
// echo "----- Logged in<BR><BR>";
try
{
$ZimbraReturn = $client->__soapCall("CreateAccountRequest",
array
(
new SoapParam("$NewUserName", "name"),
new SoapParam("$NewPassword", "password"),
new SoapParam("f070eede-c0c5-4867-a158-1f35f1c39e15", "a n=\"zimbraCOSid\"")
),
array
(
"uri" => "urn:zimbraAdmin",
"soapaction" => "urn:zimbraAdmin#CreateAccountRequest"
),
array
(
new SoapHeader("urn:zimbra", "context", new SoapVar("<ns2:context><authToken>" . $ZimbraSession[authToken] . "</authToken></ns2:context>", XSD_ANYXML))
)
);
}
catch (SoapFault $exception)
{
echo "CreateAccountRequest exception caught<br><br>";
echo "Sent: " . htmlentities($client->__getLastRequest()) . "<br><br>";
echo "Received: " . htmlentities($client->__getLastResponse()) . "<br><br>";
}
// echo "Sent: " . htmlentities($client->__getLastRequest()) . "<br><br>";
// echo "Received: " . htmlentities($client->__getLastResponse()) . "<br><br>";
return($ZimbraReturn);
} | 
07-05-2007, 08:26 PM
| | Intermediate Member | |
Posts: 22
| | I haven't tried this to set attribute values in PHP's SOAP, but you might be able to use it: PHP: SOAP Functions - Manual
Please let us know how that works! | 
07-08-2007, 11:21 AM
| | | Got it working! Well for those wondering the PHP SOAP functions really are not doing anything but making is really hard to do a simple curl HTTP POST to Zimbra's SOAP URL. Doing it the following way makes it so you can do "zmprov --debug whatever" and be able to use that trace to get done exactly the same thing in PHP. In the example below you could technically break it up into 2 functions and have the login happen in an isolated function so that it doesn't create a ton of admin sessions sitting out there every time you add an account since one authToken & sessionId can be used for an infinite amount of SOAP requests. But for my purposes my PHP script is very short lived and literally just adds the account and exits so it is not needed. Code: <?PHP
$ServerAddress = "192.168.1.1";
$AdminUserName = "admin";
$AdminPassword = "adminpassword";
$NewUserName = "mynewaccount@mydomain.com";
$NewUserPassword = "mynewpassoword";
$COSId = "f070eede-c0c5-4867-a158-1f35f1c39e15";
// To get your COSId for COS defualt or any other COS (I left mine in there as an example):
// zmprov getCos default | grep "zimbraId:" from the command line
if(($ZimbraSOAPResponse = ZimbraAdminCreateAccount(1, $ServerAddress, $AdminUserName, $AdminPassword, $NewUserName, $NewUserPassword, $COSId)) == FALSE)
{
printf("ZimbraAdminCreateAccount Failed!<BR>\n");
return(FALSE);
}
print("Zimbra create account response:<BR>" . htmlentities($ZimbraSOAPResponse) . "<BR><BR>\n");
?>
<?PHP
// -------------------------------------------------------------------
function ZimbraAdminCreateAccount($Trace, $ServerAddress, $AdminUserName, $AdminPassword, $NewUserName, $NewPassword, $COSId)
{
$CurlHandle = curl_init();
curl_setopt($CurlHandle, CURLOPT_URL, "https://$ServerAddress:7071/service/admin/soap");
curl_setopt($CurlHandle, CURLOPT_POST, TRUE);
curl_setopt($CurlHandle, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($CurlHandle, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($CurlHandle, CURLOPT_SSL_VERIFYHOST, FALSE);
// ------ Send the zimbraAdmin AuthRequest -----
$SOAPMessage = '<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
<soap:Header>
<context xmlns="urn:zimbra"/>
</soap:Header>
<soap:Body>
<AuthRequest xmlns="urn:zimbraAdmin">
<name>' . $AdminUserName . '</name>
<password>' . $AdminPassword . '</password>
</AuthRequest>
</soap:Body>
</soap:Envelope>';
curl_setopt($CurlHandle, CURLOPT_POSTFIELDS, $SOAPMessage);
if(!($ZimbraSOAPResponse = curl_exec($CurlHandle)))
{
print("ERROR: curl_exec - (" . curl_errno($CurlHandle) . ") " . curl_error($CurlHandle));
return(FALSE);
}
// print("Raw Zimbra SOAP Response:<BR>" . htmlentities($ZimbraSOAPResponse) . "<BR><BR>\n");
// Parse for the sessionId
// <sessionId type="admin" id="123">123</sessionId>
$sessionId = strstr($ZimbraSOAPResponse, "<sessionId");
$sessionId = strstr($sessionId, ">");
$sessionId = substr($sessionId, 1, strpos($sessionId, "<") - 1);
// print("sessionId = $sessionId<BR>\n");
// Parse for the authToken
// <authToken>123</authToken>
$authToken = strstr($ZimbraSOAPResponse, "<authToken");
$authToken = strstr($authToken, ">");
$authToken = substr($authToken, 1, strpos($authToken, "<") - 1);
// print("authToken = $authToken<BR>\n");
// ------ Send the zimbraCreateAccount request -----
$SOAPMessage = '<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
<soap:Header>
<context xmlns="urn:zimbra">
<authToken>' . $authToken . '</authToken>
<sessionId id="' . $sessionId . '">' . $sessionId . '</sessionId>
</context>
</soap:Header>
<soap:Body>
<CreateAccountRequest xmlns="urn:zimbraAdmin">
<name>' . $NewUserName . '</name>
<password>' . $NewUserPassword . '</password>
<a n="zimbraCOSId">' . $COSId . '</a>
</CreateAccountRequest>
</soap:Body>
</soap:Envelope>';
curl_setopt($CurlHandle, CURLOPT_POSTFIELDS, $SOAPMessage);
if(!($ZimbraSOAPResponse = curl_exec($CurlHandle)))
{
print("ERROR: curl_exec - (" . curl_errno($CurlHandle) . ") " . curl_error($CurlHandle));
return(FALSE);
}
// print("Raw Zimbra SOAP Response:<BR>" . htmlentities($ZimbraSOAPResponse) . "<BR><BR>\n");
return($ZimbraSOAPResponse);
}
?> | 
07-08-2007, 11:46 AM
| | | DeleteAccount Function And because I'm such a nice and cool guy here is the code for deleting an account: Code: function ZimbraAdminDeleteAccount($Trace, $ServerAddress, $AdminUserName, $AdminPassword, $DeleteUserName)
{
$CurlHandle = curl_init();
curl_setopt($CurlHandle, CURLOPT_URL, "https://$ServerAddress:7071/service/admin/soap");
curl_setopt($CurlHandle, CURLOPT_POST, TRUE);
curl_setopt($CurlHandle, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($CurlHandle, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($CurlHandle, CURLOPT_SSL_VERIFYHOST, FALSE);
// ------ Send the zimbraAdmin AuthRequest -----
$SOAPMessage = '<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
<soap:Header>
<context xmlns="urn:zimbra"/>
</soap:Header>
<soap:Body>
<AuthRequest xmlns="urn:zimbraAdmin">
<name>' . $AdminUserName . '</name>
<password>' . $AdminPassword . '</password>
</AuthRequest>
</soap:Body>
</soap:Envelope>';
curl_setopt($CurlHandle, CURLOPT_POSTFIELDS, $SOAPMessage);
if(!($ZimbraSOAPResponse = curl_exec($CurlHandle)))
{
print("ERROR: curl_exec - (" . curl_errno($CurlHandle) . ") " . curl_error($CurlHandle));
return(FALSE);
}
// print("Raw Zimbra SOAP Response:<BR>" . htmlentities($ZimbraSOAPResponse) . "<BR><BR>\n");
// Parse for the sessionId
// <sessionId type="admin" id="123">123</sessionId>
$sessionId = strstr($ZimbraSOAPResponse, "<sessionId");
$sessionId = strstr($sessionId, ">");
$sessionId = substr($sessionId, 1, strpos($sessionId, "<") - 1);
// print("sessionId = $sessionId<BR>\n");
// Parse for the authToken
// <authToken>123</authToken>
$authToken = strstr($ZimbraSOAPResponse, "<authToken");
$authToken = strstr($authToken, ">");
$authToken = substr($authToken, 1, strpos($authToken, "<") - 1);
// print("authToken = $authToken<BR>\n");
// ------ Send the GetAccountRequest request -----
$SOAPMessage = '<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
<soap:Header>
<context xmlns="urn:zimbra">
<authToken>' . $authToken . '</authToken>
<sessionId id="' . $sessionId . '">' . $sessionId . '</sessionId>
</context>
</soap:Header>
<soap:Body>
<GetAccountRequest xmlns="urn:zimbraAdmin">
<account by="name">' . $DeleteUserName . '</account>
</GetAccountRequest>
</soap:Body>
</soap:Envelope>';
curl_setopt($CurlHandle, CURLOPT_POSTFIELDS, $SOAPMessage);
if(!($ZimbraSOAPResponse = curl_exec($CurlHandle)))
{
print("ERROR: curl_exec - (" . curl_errno($CurlHandle) . ") " . curl_error($CurlHandle));
return(FALSE);
}
// print("Raw Zimbra SOAP Response:<BR>" . htmlentities($ZimbraSOAPResponse) . "<BR><BR>\n");
// Parse for zimbraId
// <a n="zimbraId">0ffaa258-048f-47f2-9efd-5901f2fd6913</a>
$zimbraId = strstr($ZimbraSOAPResponse, "<a n=\"zimbraId\"");
$zimbraId = strstr($zimbraId, ">");
$zimbraId = substr($zimbraId, 1, strpos($zimbraId, "<") - 1);
// print("zimbraId = $zimbraId<BR>\n");
// Check if we got a zimbraId
if($zimbraId == "")
{
// No zimbraId found! This usually means that the account is not found. You can parse the message if you really want to know
// print("Raw Zimbra SOAP Response:<BR>" . htmlentities($ZimbraSOAPResponse) . "<BR><BR>\n");
return(FALSE);
}
// ------ Send the zimbraCreateAccount request -----
$SOAPMessage = '<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
<soap:Header>
<context xmlns="urn:zimbra">
<authToken>' . $authToken . '</authToken>
<sessionId id="' . $sessionId . '">' . $sessionId . '</sessionId>
</context>
</soap:Header>
<soap:Body>
<DeleteAccountRequest xmlns="urn:zimbraAdmin">
<id>' . $zimbraId . '</id>
</DeleteAccountRequest>
</soap:Body>
</soap:Envelope>';
curl_setopt($CurlHandle, CURLOPT_POSTFIELDS, $SOAPMessage);
if(!($ZimbraSOAPResponse = curl_exec($CurlHandle)))
{
print("ERROR: curl_exec - (" . curl_errno($CurlHandle) . ") " . curl_error($CurlHandle));
return(FALSE);
}
// print("Raw Zimbra SOAP Response:<BR>" . htmlentities($ZimbraSOAPResponse) . "<BR><BR>\n");
return($ZimbraSOAPResponse);
} | 
10-23-2007, 12:26 PM
| | | There is a typo/mistake in this post
the line that starts with ....function ZimbraAdminCreateAccount ...should have NewUserPassword (not NewPassword) so it matches other parts of php.
Also, helpful pointer....make sure you enable the SOAP and CURL extensions in your PHP.INI | 
10-23-2007, 07:14 PM
| | | note: enabling CURL and SOAP in the ini file only applies to Windows. *nix will require a compilation of PHP with CURL and SOAP enabled. | 
01-25-2011, 04:11 AM
| | | grat work
but, does exists function to send mail instead of managing account ?
thanks
Gabriele | | Thread Tools | Search this Thread | | | | | Display Modes | Linear Mode | | Why Join? Registering let's you ask questions, makes it easier to search, displays any files attached to posts, and notifies you about replies.  |