1<?php 2/** 3 * PHP LDAP CLASS FOR MANIPULATING ACTIVE DIRECTORY 4 * Version 4.0.4 5 * 6 * PHP Version 5 with SSL and LDAP support 7 * 8 * Written by Scott Barnett, Richard Hyland 9 * email: scott@wiggumworld.com, adldap@richardhyland.com 10 * http://adldap.sourceforge.net/ 11 * 12 * Copyright (c) 2006-2012 Scott Barnett, Richard Hyland 13 * 14 * We'd appreciate any improvements or additions to be submitted back 15 * to benefit the entire community :) 16 * 17 * This library is free software; you can redistribute it and/or 18 * modify it under the terms of the GNU Lesser General Public 19 * License as published by the Free Software Foundation; either 20 * version 2.1 of the License. 21 * 22 * This library is distributed in the hope that it will be useful, 23 * but WITHOUT ANY WARRANTY; without even the implied warranty of 24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 25 * Lesser General Public License for more details. 26 * 27 * @category ToolsAndUtilities 28 * @package adLDAP 29 * @subpackage Exchange 30 * @author Scott Barnett, Richard Hyland 31 * @copyright (c) 2006-2012 Scott Barnett, Richard Hyland 32 * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html LGPLv2.1 33 * @revision $Revision: 97 $ 34 * @version 4.0.4 35 * @link http://adldap.sourceforge.net/ 36 */ 37require_once(dirname(__FILE__).'/../adLDAP.php'); 38 39/** 40* MICROSOFT EXCHANGE FUNCTIONS 41*/ 42class adLDAPExchange { 43 /** 44 * The current adLDAP connection via dependency injection 45 * 46 * @var adLDAP 47 */ 48 protected $adldap; 49 50 public function __construct(adLDAP $adldap) { 51 $this->adldap = $adldap; 52 } 53 54 /** 55 * Create an Exchange account 56 * 57 * @param string $username The username of the user to add the Exchange account to 58 * @param array $storageGroup The mailbox, Exchange Storage Group, for the user account, this must be a full CN 59 * If the storage group has a different base_dn to the adLDAP configuration, set it using $base_dn 60 * @param string $emailAddress The primary email address to add to this user 61 * @param string $mailNickname The mail nick name. If mail nickname is blank, the username will be used 62 * @param bool $useDefaults Indicates whether the store should use the default quota, rather than the per-mailbox quota. 63 * @param string $baseDn Specify an alternative base_dn for the Exchange storage group 64 * @param bool $isGUID Is the username passed a GUID or a samAccountName 65 * @return string|boolean 66 */ 67 public function createMailbox($username, $storageGroup, $emailAddress, $mailNickname = NULL, $useDefaults = TRUE, $baseDn = NULL, $isGUID = false) 68 { 69 if ($username === NULL) { return "Missing compulsory field [username]"; } 70 if ($storageGroup === NULL) { return "Missing compulsory array [storagegroup]"; } 71 if (!is_array($storageGroup)) { return "[storagegroup] must be an array"; } 72 if ($emailAddress === NULL) { return "Missing compulsory field [emailAddress]"; } 73 74 if ($baseDn === NULL) { 75 $baseDn = $this->adldap->getBaseDn(); 76 } 77 78 $container = "CN=".implode(",CN=", $storageGroup); 79 80 if ($mailNickname === NULL) { 81 $mailNickname = $username; 82 } 83 $mdbUseDefaults = $this->adldap->utilities()->boolToString($useDefaults); 84 85 $attributes = array( 86 'exchange_homemdb'=>$container.",".$baseDn, 87 'exchange_proxyaddress'=>'SMTP:'.$emailAddress, 88 'exchange_mailnickname'=>$mailNickname, 89 'exchange_usedefaults'=>$mdbUseDefaults 90 ); 91 $result = $this->adldap->user()->modify($username, $attributes, $isGUID); 92 if ($result == false) { 93 return false; 94 } 95 return true; 96 } 97 98 /** 99 * Add an X400 address to Exchange 100 * See http://tools.ietf.org/html/rfc1685 for more information. 101 * An X400 Address looks similar to this X400:c=US;a= ;p=Domain;o=Organization;s=Doe;g=John; 102 * 103 * @param string $username The username of the user to add the X400 to to 104 * @param string $country Country 105 * @param string $admd Administration Management Domain 106 * @param string $pdmd Private Management Domain (often your AD domain) 107 * @param string $org Organization 108 * @param string $surname Surname 109 * @param string $givenName Given name 110 * @param bool $isGUID Is the username passed a GUID or a samAccountName 111 * @return string|boolean 112 */ 113 public function addX400($username, $country, $admd, $pdmd, $org, $surname, $givenName, $isGUID=false) 114 { 115 if ($username === NULL){ return "Missing compulsory field [username]"; } 116 117 $proxyValue = 'X400:'; 118 119 // Find the dn of the user 120 $user = $this->adldap->user()->info($username, array("cn","proxyaddresses"), $isGUID); 121 if ($user[0]["dn"] === NULL) { return false; } 122 $userDn = $user[0]["dn"]; 123 124 // We do not have to demote an email address from the default so we can just add the new proxy address 125 $attributes['exchange_proxyaddress'] = $proxyValue . 'c=' . $country . ';a=' . $admd . ';p=' . $pdmd . ';o=' . $org . ';s=' . $surname . ';g=' . $givenName . ';'; 126 127 // Translate the update to the LDAP schema 128 $add = $this->adldap->adldap_schema($attributes); 129 130 if (!$add) { return false; } 131 132 // Do the update 133 // Take out the @ to see any errors, usually this error might occur because the address already 134 // exists in the list of proxyAddresses 135 $result = @ldap_mod_add($this->adldap->getLdapConnection(), $userDn, $add); 136 if ($result == false) { 137 return false; 138 } 139 140 return true; 141 } 142 143 /** 144 * Add an address to Exchange 145 * 146 * @param string $username The username of the user to add the Exchange account to 147 * @param string $emailAddress The email address to add to this user 148 * @param bool $default Make this email address the default address, this is a bit more intensive as we have to demote any existing default addresses 149 * @param bool $isGUID Is the username passed a GUID or a samAccountName 150 * @return string|boolean 151 */ 152 public function addAddress($username, $emailAddress, $default = FALSE, $isGUID = false) 153 { 154 if ($username === NULL) { return "Missing compulsory field [username]"; } 155 if ($emailAddress === NULL) { return "Missing compulsory fields [emailAddress]"; } 156 157 $proxyValue = 'smtp:'; 158 if ($default === true) { 159 $proxyValue = 'SMTP:'; 160 } 161 162 // Find the dn of the user 163 $user = $this->adldap->user()->info($username, array("cn","proxyaddresses"), $isGUID); 164 if ($user[0]["dn"] === NULL){ return false; } 165 $userDn = $user[0]["dn"]; 166 167 // We need to scan existing proxy addresses and demote the default one 168 if (is_array($user[0]["proxyaddresses"]) && $default === true) { 169 $modAddresses = array(); 170 for ($i=0;$i<sizeof($user[0]['proxyaddresses']);$i++) { 171 if (strstr($user[0]['proxyaddresses'][$i], 'SMTP:') !== false) { 172 $user[0]['proxyaddresses'][$i] = str_replace('SMTP:', 'smtp:', $user[0]['proxyaddresses'][$i]); 173 } 174 if ($user[0]['proxyaddresses'][$i] != '') { 175 $modAddresses['proxyAddresses'][$i] = $user[0]['proxyaddresses'][$i]; 176 } 177 } 178 $modAddresses['proxyAddresses'][(sizeof($user[0]['proxyaddresses']) - 1)] = 'SMTP:'.$emailAddress; 179 180 $result = @ldap_mod_replace($this->adldap->getLdapConnection(), $userDn, $modAddresses); 181 if ($result == false) { 182 return false; 183 } 184 185 return true; 186 } else { 187 // We do not have to demote an email address from the default so we can just add the new proxy address 188 $attributes['exchange_proxyaddress'] = $proxyValue.$emailAddress; 189 190 // Translate the update to the LDAP schema 191 $add = $this->adldap->adldap_schema($attributes); 192 193 if (!$add) { 194 return false; 195 } 196 197 // Do the update 198 // Take out the @ to see any errors, usually this error might occur because the address already 199 // exists in the list of proxyAddresses 200 $result = @ldap_mod_add($this->adldap->getLdapConnection(), $userDn, $add); 201 if ($result == false) { 202 return false; 203 } 204 205 return true; 206 } 207 } 208 209 /** 210 * Remove an address to Exchange 211 * If you remove a default address the account will no longer have a default, 212 * we recommend changing the default address first 213 * 214 * @param string $username The username of the user to add the Exchange account to 215 * @param string $emailAddress The email address to add to this user 216 * @param bool $isGUID Is the username passed a GUID or a samAccountName 217 * @return string|boolean 218 */ 219 public function deleteAddress($username, $emailAddress, $isGUID=false) 220 { 221 if ($username === NULL) { return "Missing compulsory field [username]"; } 222 if ($emailAddress === NULL) { return "Missing compulsory fields [emailAddress]"; } 223 224 // Find the dn of the user 225 $user = $this->adldap->user()->info($username, array("cn","proxyaddresses"), $isGUID); 226 if ($user[0]["dn"] === NULL) { return false; } 227 $userDn = $user[0]["dn"]; 228 229 if (is_array($user[0]["proxyaddresses"])) { 230 $mod = array(); 231 for ($i=0;$i<sizeof($user[0]['proxyaddresses']);$i++) { 232 if (strstr($user[0]['proxyaddresses'][$i], 'SMTP:') !== false && $user[0]['proxyaddresses'][$i] == 'SMTP:' . $emailAddress) { 233 $mod['proxyAddresses'][0] = 'SMTP:' . $emailAddress; 234 } elseif (strstr($user[0]['proxyaddresses'][$i], 'smtp:') !== false && $user[0]['proxyaddresses'][$i] == 'smtp:' . $emailAddress) { 235 $mod['proxyAddresses'][0] = 'smtp:' . $emailAddress; 236 } 237 } 238 239 $result = @ldap_mod_del($this->adldap->getLdapConnection(), $userDn,$mod); 240 if ($result == false) { 241 return false; 242 } 243 244 return true; 245 } else { 246 return false; 247 } 248 } 249 /** 250 * Change the default address 251 * 252 * @param string $username The username of the user to add the Exchange account to 253 * @param string $emailAddress The email address to make default 254 * @param bool $isGUID Is the username passed a GUID or a samAccountName 255 * @return bool 256 */ 257 public function primaryAddress($username, $emailAddress, $isGUID = false) 258 { 259 if ($username === NULL) { return "Missing compulsory field [username]"; } 260 if ($emailAddress === NULL) { return "Missing compulsory fields [emailAddress]"; } 261 262 // Find the dn of the user 263 $user = $this->adldap->user()->info($username, array("cn","proxyaddresses"), $isGUID); 264 if ($user[0]["dn"] === NULL){ return false; } 265 $userDn = $user[0]["dn"]; 266 267 if (is_array($user[0]["proxyaddresses"])) { 268 $modAddresses = array(); 269 for ($i=0;$i<sizeof($user[0]['proxyaddresses']);$i++) { 270 if (strstr($user[0]['proxyaddresses'][$i], 'SMTP:') !== false) { 271 $user[0]['proxyaddresses'][$i] = str_replace('SMTP:', 'smtp:', $user[0]['proxyaddresses'][$i]); 272 } 273 if ($user[0]['proxyaddresses'][$i] == 'smtp:' . $emailAddress) { 274 $user[0]['proxyaddresses'][$i] = str_replace('smtp:', 'SMTP:', $user[0]['proxyaddresses'][$i]); 275 } 276 if ($user[0]['proxyaddresses'][$i] != '') { 277 $modAddresses['proxyAddresses'][$i] = $user[0]['proxyaddresses'][$i]; 278 } 279 } 280 281 $result = @ldap_mod_replace($this->adldap->getLdapConnection(), $userDn, $modAddresses); 282 if ($result == false) { 283 return false; 284 } 285 286 return true; 287 } 288 289 } 290 291 /** 292 * Mail enable a contact 293 * Allows email to be sent to them through Exchange 294 * 295 * @param string $distinguishedName The contact to mail enable 296 * @param string $emailAddress The email address to allow emails to be sent through 297 * @param string $mailNickname The mailnickname for the contact in Exchange. If NULL this will be set to the display name 298 * @return string|boolean 299 */ 300 public function contactMailEnable($distinguishedName, $emailAddress, $mailNickname = NULL) 301 { 302 if ($distinguishedName === NULL) { return "Missing compulsory field [distinguishedName]"; } 303 if ($emailAddress === NULL) { return "Missing compulsory field [emailAddress]"; } 304 305 if ($mailNickname !== NULL) { 306 // Find the dn of the user 307 $user = $this->adldap->contact()->info($distinguishedName, array("cn","displayname")); 308 if ($user[0]["displayname"] === NULL) { return false; } 309 $mailNickname = $user[0]['displayname'][0]; 310 } 311 312 $attributes = array("email"=>$emailAddress,"contact_email"=>"SMTP:" . $emailAddress,"exchange_proxyaddress"=>"SMTP:" . $emailAddress,"exchange_mailnickname" => $mailNickname); 313 314 // Translate the update to the LDAP schema 315 $mod = $this->adldap->adldap_schema($attributes); 316 317 // Check to see if this is an enabled status update 318 if (!$mod) { return false; } 319 320 // Do the update 321 $result = ldap_modify($this->adldap->getLdapConnection(), $distinguishedName, $mod); 322 if ($result == false) { return false; } 323 324 return true; 325 } 326 327 /** 328 * Returns a list of Exchange Servers in the ConfigurationNamingContext of the domain 329 * 330 * @param array $attributes An array of the AD attributes you wish to return 331 * @return array 332 */ 333 public function servers($attributes = array('cn','distinguishedname','serialnumber')) 334 { 335 if (!$this->adldap->getLdapBind()){ return false; } 336 337 $configurationNamingContext = $this->adldap->getRootDse(array('configurationnamingcontext')); 338 $sr = @ldap_search($this->adldap->getLdapConnection(), $configurationNamingContext[0]['configurationnamingcontext'][0],'(&(objectCategory=msExchExchangeServer))', $attributes); 339 $entries = @ldap_get_entries($this->adldap->getLdapConnection(), $sr); 340 return $entries; 341 } 342 343 /** 344 * Returns a list of Storage Groups in Exchange for a given mail server 345 * 346 * @param string $exchangeServer The full DN of an Exchange server. You can use exchange_servers() to find the DN for your server 347 * @param array $attributes An array of the AD attributes you wish to return 348 * @param bool $recursive If enabled this will automatically query the databases within a storage group 349 * @return array 350 */ 351 public function storageGroups($exchangeServer, $attributes = array('cn','distinguishedname'), $recursive = NULL) 352 { 353 if (!$this->adldap->getLdapBind()){ return false; } 354 if ($exchangeServer === NULL) { return "Missing compulsory field [exchangeServer]"; } 355 if ($recursive === NULL) { $recursive = $this->adldap->getRecursiveGroups(); } 356 357 $filter = '(&(objectCategory=msExchStorageGroup))'; 358 $sr = @ldap_search($this->adldap->getLdapConnection(), $exchangeServer, $filter, $attributes); 359 $entries = @ldap_get_entries($this->adldap->getLdapConnection(), $sr); 360 361 if ($recursive === true) { 362 for ($i = 0; $i < $entries['count']; $i++) { 363 $entries[$i]['msexchprivatemdb'] = $this->storageDatabases($entries[$i]['distinguishedname'][0]); 364 } 365 } 366 367 return $entries; 368 } 369 370 /** 371 * Returns a list of Databases within any given storage group in Exchange for a given mail server 372 * 373 * @param string $storageGroup The full DN of an Storage Group. You can use exchange_storage_groups() to find the DN 374 * @param array $attributes An array of the AD attributes you wish to return 375 * @return array 376 */ 377 public function storageDatabases($storageGroup, $attributes = array('cn','distinguishedname','displayname')) { 378 if (!$this->adldap->getLdapBind()){ return false; } 379 if ($storageGroup === NULL) { return "Missing compulsory field [storageGroup]"; } 380 381 $filter = '(&(objectCategory=msExchPrivateMDB))'; 382 $sr = @ldap_search($this->adldap->getLdapConnection(), $storageGroup, $filter, $attributes); 383 $entries = @ldap_get_entries($this->adldap->getLdapConnection(), $sr); 384 return $entries; 385 } 386} 387?>