Solved

Create Exchange Mailboxes Automatically with PHP

Posted on 2007-11-16
4
1,672 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
  • 2
  • 2
4 Comments
 
LVL 23

Expert Comment

by:Stacy Spear
Comment Utility
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
Comment Utility
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 500 total points
Comment Utility
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
Comment Utility
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

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

Not sure what the best email signature size is? Are you worried about email signature image size? Follow this best practice guide.
This article explains in simple steps how to renew expiring Exchange Server Internal Transport Certificate.
The viewer will learn how to create a basic form using some HTML5 and PHP for later processing. Set up your basic HTML file. Open your form tag and set the method and action attributes.: (CODE) Set up your first few inputs one for the name and …
To add imagery to an HTML email signature, you have two options available to you. You can either add a logo/image by embedding it directly into the signature or hosting it externally and linking to it. The vast majority of email clients display l…

762 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

Need Help in Real-Time?

Connect with top rated Experts

10 Experts available now in Live!

Get 1:1 Help Now