Skip to content

Instantly share code, notes, and snippets.

@grantholle
Created July 23, 2021 00:35
Show Gist options
  • Save grantholle/300e9ddae9fea66e8f6eeb9fd573e008 to your computer and use it in GitHub Desktop.
Save grantholle/300e9ddae9fea66e8f6eeb9fd573e008 to your computer and use it in GitHub Desktop.
A simple class that creates an Exchange mailbox using the LdapRecord package
<?php
use Illuminate\Support\Str;
use LdapRecord\Models\ActiveDirectory\Entry;
use LdapRecord\Models\ActiveDirectory\User as LdapUser;
use LdapTools\Security\GUID;
use Ramsey\Uuid\Uuid;
class MailboxFactory
{
protected $configurationDn;
public function createMailbox()
{
// Use your organizational unit (OU)
$ldapUser = (new LdapUser)->inside('OU=Staff,DC=local');
$email = 'john.doe@example.com';
$username = 'john.doe';
// Populate these values
$ldapUser->givenName = 'John';
$ldapUser->sn = 'Doe';
$ldapUser->cn = 'John Doe';
$ldapUser->displayName = 'John Doe';
$ldapUser->name = 'John Doe';
$ldapUser->title = 'Employee';
$ldapUser->department = 'Department';
$ldapUser->manager = 'CN=Boss Man,OU=Staff,DC=com';
$ldapUser->unicodePwd = Str::random();
$ldapUser->samaccountname = $username;
$ldapUser->mailNickname = $username;
$ldapUser->mail = $email;
$ldapUser->userPrincipalName = $email;
$ldapUser->company = 'Company Name';
$ldapUser->streetAddress = '123 Main Street';
$ldapUser->l = 'City';
$ldapUser->st = 'ST';
$ldapUser->c = 'Country';
$ldapUser->postalCode = '123456';
$ldapUser->wWWHomePage = 'https://www.example.com';
$ldapUser->telephoneNumber = '123-123-123';
// Exchange attributes
// The logic was ported from LdapTools
$ldapUser->msExchHomeServerName = $this->getExchangeServerDn();
$ldapUser->legacyExchangeDN = $this->getLegacyExchangeDn($username);
$ldapUser->homeMDB = $this->getExchangeDatabaseDn();
$ldapUser->mDBUseDefaults = 'TRUE';
$ldapUser->msExchUserCulture = 'en-US';
$ldapUser->proxyAddresses = "SMTP:{$email}";
$ldapUser->msExchMailboxGUID = (new GUID(Uuid::uuid4()))->toBinary();
$ldapUser->msExchUserAccountControl = 0;
$ldapUser->msExchRecipientDisplayType = 1073741824;
$ldapUser->msExchRBACPolicyLink = $this->getExchangeRbacPolicyDn();
$ldapUser->msExchRecipientTypeDetails = 1;
$ldapUser->msExchVersion = 88218628259840;
$ldapUser->showInAddressBook = $this->getAddressBookDns();
$ldapUser->msExchPoliciesIncluded = $this->getRecipientPolicyDn();
// Save the user initially
$ldapUser->save();
// Enable their account
$ldapUser->userAccountControl = 512;
$ldapUser->save();
// Force password reset when the log in
$ldapUser->pwdlastset = 0;
$ldapUser->save();
return $this;
}
protected function getExchangeServerDn()
{
if (!$this->configurationDn) {
$this->getConfigurationNamingContext();
}
$exchangeServer = Entry::in($this->configurationDn)
->where('objectclass', 'msExchExchangeServer')
->whereHas('serverrole')
->first();
if (!$exchangeServer) {
throw new \Exception("Exchange server not found.");
}
return $exchangeServer->getFirstAttribute('distinguishedname');
}
protected function getExchangeDatabaseDn()
{
if (!$this->configurationDn) {
$this->getConfigurationNamingContext();
}
// This is the name of your Exchange mailbox database
$database = 'Mailbox-Db-Name';
$exchangeDb = Entry::in($this->configurationDn)
->where('objectclass', 'msExchMDB')
->where('cn', $database)
->first();
if (!$exchangeDb) {
throw new \Exception("Exchange database not found.");
}
return $exchangeDb->getFirstAttribute('distinguishedname');
}
protected function getExchangeRbacPolicyDn()
{
if (!$this->configurationDn) {
$this->getConfigurationNamingContext();
}
$rbacPolicy = Entry::in($this->configurationDn)
->where('objectclass', 'msExchRBACPolicy')
->where('cn', 'Default Role Assignment Policy')
->first();
if (!$rbacPolicy) {
throw new \Exception("Exchange RBAC policy not found.");
}
return $rbacPolicy->getFirstAttribute('distinguishedname');
}
protected function getAddressBookDns()
{
if (!$this->configurationDn) {
$this->getConfigurationNamingContext();
}
return Entry::in($this->configurationDn)
->where('objectclass', 'addressBookContainer')
->get()
->filter(function ($addressBook) {
return in_array($addressBook->getFirstAttribute('cn'), [
'All Mailboxes(VLV)',
'All Recipients(VLV)',
'All Users',
'Default Global Address List',
'Mailboxes(VLV)',
]);
})
->pluck('distinguishedname')
->flatten()
->toArray();
}
protected function getRecipientPolicyDn()
{
if (!$this->configurationDn) {
$this->getConfigurationNamingContext();
}
$policy = Entry::in($this->configurationDn)
->where('objectclass', 'msExchRecipientPolicy')
->where('cn', 'Default Policy')
->first();
if (!$policy) {
throw new \Exception('Recipient policy could not be found');
}
return $policy->getFirstAttribute('distinguishedname');
}
protected function getLegacyExchangeDn(string $username)
{
if (!$this->configurationDn) {
$this->getConfigurationNamingContext();
}
$policy = Entry::in($this->configurationDn)
->where('objectclass', 'msExchAdminGroup')
->first();
if (!$policy) {
throw new \Exception('Recipient policy could not be found');
}
$uuid = str_replace('-', '', Uuid::uuid4());
return $policy->getFirstAttribute('legacyexchangedn')
. "/cn=Recipients/cn={$uuid}-{$username}";
}
/**
* Gets the configuration naming context from the root dse
*
* @return $this
*/
protected function getConfigurationNamingContext()
{
$rootdse = Entry::in(null)
->read()
->whereHas('objectclass')
->first();
$this->configurationDn = $rootdse->getFirstAttribute('configurationnamingcontext');
return $this;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment