Zimbra offers Open Source email server software and shared calendar for Linux and the Mac
Go Back   Zimbra :: Forums > Zimbra Collaboration Suite > Developers

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.

Reply
 
LinkBack Thread Tools Search this Thread Display Modes
  #1 (permalink)  
Old 07-02-2007, 10:12 PM
Member
 
Posts: 11
Default [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-&gt;__doRequest('&lt;?xml version=&quot;...', 'https://mail.myzim....', 'urn:zimbra#Auth...', 1, 0)
#1 /mnt/Web/htdocs/SOAP/soap.php(22): SoapClient-&gt;__call('AuthRequest', Array, Array)
#2 {main}
  thrown in <b>/mnt/Web/htdocs/SOAP/soap.php</b> on line <b>22</b><br />
Reply With Quote
  #2 (permalink)  
Old 07-02-2007, 10:37 PM
Member
 
Posts: 11
Default

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!
Reply With Quote
  #3 (permalink)  
Old 07-03-2007, 01:16 PM
Intermediate Member
 
Posts: 22
Default

Read this thread: PHP SOAP vs Zimbra
Reply With Quote
  #4 (permalink)  
Old 07-05-2007, 07:27 AM
Member
 
Posts: 11
Default

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);
}
Reply With Quote
  #5 (permalink)  
Old 07-05-2007, 08:26 PM
Intermediate Member
 
Posts: 22
Default

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!
Reply With Quote
  #6 (permalink)  
Old 07-08-2007, 11:21 AM
Member
 
Posts: 11
Default 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);
}
?>
Reply With Quote
  #7 (permalink)  
Old 07-08-2007, 11:46 AM
Member
 
Posts: 11
Default 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);
}
Reply With Quote
  #8 (permalink)  
Old 10-23-2007, 12:26 PM
Junior Member
 
Posts: 7
Default

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
Reply With Quote
  #9 (permalink)  
Old 10-23-2007, 07:14 PM
Junior Member
 
Posts: 5
Default

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.
Reply With Quote
  #10 (permalink)  
Old 01-25-2011, 04:11 AM
New Member
 
Posts: 3
Default

grat work
but, does exists function to send mail instead of managing account ?
thanks
Gabriele
Reply With Quote
Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes


Similar Threads

Why Join?

Registering let's you ask questions, makes it easier to search, displays any files attached to posts, and notifies you about replies.

blog.zimbra.com




 

SEO by vBSEO ©2011, Crawlability, Inc.