?
Solved

Create Exchange Mailboxes Automatically with PHP

Posted on 2007-11-16
4
Medium Priority
?
1,867 Views
Last Modified: 2010-04-21
I have developed a PHP script that spiders the entire Active Directory structure on a domain controller I'm hosting. The script recursively maps a tree of the OUs, then populates an array with ALL user accounts in the tree (a backhanded way of circumventing the maxpage = 1000 issue on the DC). I then traverse the array and move all users into a multi-dimensional array with the keys denoting the mail server and storage group they reside on. From here, I create global distribution groups for each mail server/storage group. (i.e., "MAILSERVER1 - SG1MS1", "MAILSERVER1 - SG1MS2", etc), and create another distribution group for each mail server with all of the distribution groups denoting storage groups and mail stores as its children. i.e.

MAILSERVER1 Users
  --> MAILSERVER1 - SG1MS1
  --> MAILSERVER1 - SG1MS2
  --> MAILSERVER1 - SG2MS1
MAILSERVER2 Users
  --> MAILSERVER2 - SG1MS1
  --> MAILSERVER2 - SG1MS2
  --> MAILSERVER2 - SG2MS1

...where each of the above lines is a distribution group, with the indented lines being children of the master distribution groups. As mentioned previously, all of the users are populated into the child groups.

My problem is, I can do all of this, but I have no clue how to create Exchange mailboxes and link them to the distribution groups I create using the ldap_add() function. This does me no good, because I want the script to run nightly as a cron job to build distribution lists I can use to contact users on any given mail server or storage group at any time, but without an Exchange mailbox, I can't send mail to the distribution list.

Code is attached below, and works perfectly at this point (which I'm truly pleased with). I want to include the code to create the Exchange mailbox at the end of the ldap_createGroup() function.
$ldap_conn = nai_ldap_bind();
$ldap_attributes = array("description","homeMDB", "distinguishedName");
$base_dn = "OU=All Users,DC=**MYDOMAIN**,DC=**NET**";
$tree = ldap_getChildTree($ldap_conn, $base_dn);
 
echo "<html><body>";
$users = ldap_enumerateUsers($tree, $base_dn, $ldap_conn, $ldap_attributes);
 
$total_count = count($users);
foreach($users AS $the_user)
{
// The Terminated flag is used to check the "description" field. Accounts that are being processed for terminated are prefixed with "term", and I choose to ignore them when building these groups.
 
  $terminated = false;
  $description = $the_user['description'][0];
  
  if($description)
    if(strpos($description,"term") !== false)
    {
      $terminated = true;
      $term_count++;
    }
  $homeMDB = $the_user['homeMDB'][0];
  if($homeMDB && !$terminated)
  {
    $ms_start = strpos($homeMDB,"CN=")+3;
    $ms_end = strpos($homeMDB,",CN=", $ms_start+2);
    $mail_store = substr($homeMDB,$ms_start,($ms_end - $ms_start));
    
    $server_start = strpos($homeMDB,"CN=InformationStore,CN=") + 23;
    $server_end = strpos($homeMDB,",CN=Servers");
    $mail_server = substr($homeMDB,$server_start, ($server_end - $server_start));
    $mail[$mail_server][$mail_store][] = $the_user['distinguishedName'][0];
  }
}
 
$dn_mailServers = "OU=**PLACE WHERE I CREATE THE GROUPS**,OU=All Users,DC=**MYDOMAIN**,DC=**NET**";
$mail_attributes = array("description","distinguishedName");
$mail_groups = ldap_findUsers($dn_mailServers, $ldap_conn, $mail_attributes, "group");
foreach($mail_groups AS $the_group)
{
  $dn = $the_group['distinguishedName'][0];
  ldap_delete ($ldap_conn, $dn); 
}
echo "Deleted All Groups for Recreation<br />";
 
foreach($mail AS $mail_server=>$ms_array)
{
  $ms_groups = array();
  foreach($ms_array AS $mail_store=>$sg_users)
  {
    $object_name="$mail_server - $mail_store";
    $dn="CN=".$object_name.",OU=**PLACE WHERE I CREATE THE GROUPS**,OU=All Users,DC=**MYDOMAIN**,DC=**NET**";
    ldap_createGroup($object_name,$dn,$sg_users,$ldap_conn);
    
    if(ldap_error($ldap_conn) == "Success")
      echo "Created distribution list for <b>$object_name</b><br />";
    else
    {
      echo(ldap_error($ldap_conn)); 
      echo " - <b><font color=red>$object_name</font></b><br />";
    }
    $ms_groups[] = $dn;
  }
  $object_name="$mail_server Users";
  $dn="CN=".$object_name.",OU=**PLACE WHERE I CREATE THE GROUPS**,OU=All Users,DC=**MYDOMAIN**,DC=**NET**";
  ldap_createGroup($object_name,$dn,$ms_groups,$ldap_conn);
  
  if(ldap_error($ldap_conn) == "Success")
    echo "Created distribution list for <b>$object_name</b><br />";
  else
  {
    echo(ldap_error($ldap_conn)); 
    echo " for <b><font color=red>$object_name</font></b><br />";
  }
}
ldap_close($ldap_conn);     
 
// --------------------------------------------------------------
// --------------------------------------------------------------
// --------------------------------------------------------------
// 
//   FUNCTION FILE INCLUDED BELOW
// 
<?php
function ldap_getChildTree($ldap_conn, $base_dn)
{ 
  $ldap_filter = "ou=*";
  $ldap_attributes = array("ou");
  $base_sr=ldap_list($ldap_conn, $base_dn, $ldap_filter, $ldap_attributes);
  
  $children = ldap_get_entries($ldap_conn, $base_sr);
  $subtree = array();
  
  foreach($children AS $child)
  {
    if(is_array($child))
    {
      $cn = $child['ou'][0];
      $child_dn = "OU=" . $cn . "," . $base_dn;
      $child_array = ldap_getChildTree($ldap_conn, $child_dn);
      if($child_array != NULL)
        $subtree[$cn] = $child_array;
      else
        $subtree[$cn] = NULL;
    }
  }
  
  if(count($subtree) > 0)
    return $subtree;
  else
    return null;
}
 
function printTree($array, $level=0, $user_count=false) 
{
  foreach($array as $key => $value) 
  {
    $div_id = rand(100000);
    echo "<div id=\"$div_id\" onClick=\"\"><div style=\"padding: 2px 0px 2px 0px; font-family: Verdana; font-size: 9px;\"><div style=\"float: left; width: ".($level*20)."px;\">&nbsp;</div>
                 <div style\"float: right;\">$key</div></div>";
    if(is_array($value))
      printTree($value, $level+1);
    echo "</div>";
  }
}
 
function ldap_enumerateUsers($root, $base_dn, $ldap_conn, $ldap_attributes)
{
  foreach($root as $key => $value) 
  {
    $child_OU = "OU=$key,".$base_dn; 
    if(!is_array($value))
    {
      $child_users = ldap_findUsers($child_OU, $ldap_conn, $ldap_attributes);
      if($child_users != null)
        if($users != null)
          $users = array_merge($users, $child_users);
        else
          $users = $child_users;
    }
    else
    {
      $child_users = ldap_enumerateUsers($value, $child_OU, $ldap_conn, $ldap_attributes);
      $own_users = ldap_findUsers($child_OU, $ldap_conn, $ldap_attributes);
      
      if($users != null)
      {
        if($child_users != null && $own_users != null)
          $users = array_merge($users, $child_users, $own_users);
        else if($child_users != null)
          $users = array_merge($users, $child_users);
        else if($own_users != null)
          $users = array_merge($users, $own_users);
      }
      else
      {
        if($child_users != null && $own_users != null)
          $users = array_merge($child_users, $own_users);
        else if($child_users != null)
          $users = $child_users;
        else if($own_users != null)
          $users = $own_users;
      }
    }
  }
  return $users;
}
 
function ldap_findUsers($base_dn, $ldap_conn, $ldap_attributes, $ldap_objectClass="user")
{
  $ldap_filter = "(&(objectclass=$ldap_objectClass)(cn=*))";
  
$ldap_userdata array
  $ldap_sr = ldap_list($ldap_conn,$base_dn,$ldap_filter, $ldap_attributes);
  $ldap_entry = ldap_first_entry($ldap_conn, $ldap_sr);
    
  while($ldap_entry)
  {
    $ldap_userdata[] = ldap_get_attributes($ldap_conn, $ldap_entry);
    $ldap_entry = ldap_next_entry($ldap_conn, $ldap_entry);
  }
  return $ldap_userdata;
}
 
function ldap_createGroup($object_name, $dn, $members, $ldap_conn)
{
    $addgroup_ad['cn']="$object_name";
    $addgroup_ad['objectClass'][0] = "top";
    $addgroup_ad['objectClass'][1] ="group";
    $addgroup_ad['groupType']="2";
    $addgroup_ad['member']=$members;
    $addgroup_ad["sAMAccountName"] =$object_name;
 
    ldap_add($ldap_conn,$dn,$addgroup_ad);
    
    if(ldap_error($ldap_conn) == "Success")
      return true;
    else
      return false;
}
?>

Open in new window

0
Comment
Question by:prussel3
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 2
  • 2
4 Comments
 
LVL 23

Expert Comment

by:Stacy Spear
ID: 20305501
You've done a lot of work! Especially considering that for the 1000/page issue you could do multipage queries or increase the page limit.

Query based distribution groups accomplish the same thing for a lot less on the distro groups.

Not to knock you, just far more productive ways to accomplish your goal. Also, the query based group is ALWAYS up to date. No need to recreate nightly.

When you create a mailbox, you first need specify where is going (homeMDB). This is an example string:
CN=MailStore,CN=First Storage Group,CN=InformationStore,CN=PARIS,CN=Servers,
CN=First Administrative Group,CN=Administrative Groups,CN=ExchangeOrg,CN=Microsoft Exchange, CN=Services,CN=Configuration,DC=example,DC=com

Will post later the other fields needed to be filled out, then the mailenable method needs to be called on the user.
0
 
LVL 1

Author Comment

by:prussel3
ID: 20313620
Any follow-up on the mail-enable method to be called, and how to execute that in the PHP script I've built?

As for your other comment regarding query-based distribution groups... currently running on a Windows 2000 environment   =/    Thanks for the heads-up though, when I upgrade the server in the coming months I'll opt for that solution.
0
 
LVL 23

Accepted Solution

by:
Stacy Spear earned 2000 total points
ID: 20315409
Oops! Forgot, sorry.

You need the following properties: msExchHomeServerName (/0=Organization/ou=First Admin Group/cn=configuration/cn=servers/cn=exchserver), homdMDB (as listed above), and mailNickname (usually the same as the sAMAccountName).

Once you do this (and I haven't tried yet with PHP) is to use the mailenable method as userobject.mailenable() and it should work.
0
 
LVL 1

Author Closing Comment

by:prussel3
ID: 31409689
I mentioned it was partially easy to understand because of my lack of familiarity with the topic in question. I felt a little more direction could have been given with the references to the mailenable() method, though the answer pointed me in the right direction.
0

Featured Post

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Originally, this post was published on Monitis Blog, you can check it here . In business circles, we sometimes hear that today is the “age of the customer.” And so it is. Thanks to the enormous advances over the past few years in consumer techno…
The main intent of this article is to make you aware of ‘Exchange fail to mount’ error, its effects, causes, and solution.
Learn how to set-up custom confirmation messages to users who complete your Wufoo form. Include inputs from fields in your form, webpage redirects, and more with Wufoo’s confirmation options.
This video shows how to quickly and easily add an email signature for all users on Exchange 2016. The resulting signature is applied on a server level by Exchange Online. The email signature template has been downloaded from: www.mail-signatures…
Suggested Courses

649 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question