Here is another PHP Preauth example (requires PHP >= 5.1.2 compiled with hash support).
Configuration for single or multiple domain support:
PHP Code:
// Configuration array allowing different settings per domain
$_zimbra_preauth = array(
    
"domain.com" => array(
        
// Configurable qstring, {account} replaced by $account etc...
        
"qstring" => "account={account}&by={by}&timestamp={timestamp}&expires={expires}&preauth={preauth}",
        
// preauthkey for the given domain
        
"preauthkey" => "6b7ead4bd425836e8cf0079cd6c1a05acc127acd07c8ee4b61023e19250e929c",
    ),
    
"otherdomain.com"=>array(
        
// This domain has a redirectURL
        
"qstring" => "account={account}&by={by}&timestamp={timestamp}&expires={expires}&preauth={preauth}&redirectURL=/zimbra/h/",
        
"preauthkey" => "6b7ead4bd425836e8cf0079cd6c1a05acc127acd07c8ee4b61023e19250e929c",
    ),
); 
Function to generate the preauth and qstring:
PHP Code:
// Generate the preauth qstring for the user and optional domain
function Zimbra_gen_preauth_qstring($user,$domain="domain.com") {
    global 
$_zimbra_preauth;
    if (!isset(
$domain) || ($domain == "")) { $domain "domain.com"; }
    
// Copy the qstring template localy to operate on it
    
$out $_zimbra_preauth[$domain]['qstring'];
    
// Setup the default pieces except for the preauth
    
$parts = array(
        
"account"=>"{$user}@{$domain}",
        
"by"=>"name",
        
"expires"=>"0",
        
"timestamp"=>microtime(TRUE)*1000,
    );
    
// Create the preauth hash and add it to the parts
    
$parts['preauth'] = hash_hmac('sha1',join("|",$parts),$_zimbra_preauth[$domain]['preauthkey']);
    
// Go through the parts and replace each qstring template parameter with the appropriate one
    
foreach ($parts as $part=>$val) {
        
$out str_replace("{{$part}}",urlencode($val),$out);
    }
    
// Return the filled qstring to be added to https://domain.com/service/preauth?
    
return $out;

Example Usage:
PHP Code:
// Example usage for myuser@domain.com:
$qstring Zimbra_gen_preauth_qstring("myuser");
// Or if the domain is not the default domain
// $qstring = Zimbra_gen_preauth_qstring("myuser","otherdomain.com");
header("Location: https://domain.com/service/preauth?{$qstring}"); 
Notes:
  • You will want to add error checking so that gen requests for undefined domains error out elegantly
  • You will likely want to gently rework the code for your application as the comments and variables are named more for illustration than convention.
  • You can move the config array into the function and simplify the whole thing if you do not want a globally sourced variable or do need the ability to configure multiple domains.
  • If you already have a Zimbra related class you can simply add it into your class and call it accordingly.


Cheers,

RioGD