Sdílet prostřednictvím


Why we need to change our current user creation scripts to powershell scripts in Exchange 2007

In Exchange Server 2003 we have a background service named Recipient Update Service (RUS) which update all users to have necessary exchange attributes; for example e-mail address. In Exchange Server 2007 we don't have a service for doing same updates for newly created objects. As a replacement to this functionality in Exchange Server 2007 (E2K7) we have a new component that behaves like a provider rather than a service, maybe we can call this "Recipient Update Provider" . As you understand it's actually working as a provider not a daemon, process or service. If we need to create an object with exchange attributes, we will need to call this "update provider" help.

By default E2K7 GUI interface (Exchange Management Console --- EMC) and (Exchange Management Shell --- EMS) powershell commands has ( such as New-mailbox) this integration. So when you use GUI or powershell command to create a sample user, this both of methods calls to provider in the background to fill Exchange related attributes to objects.

Actually in E2K7 RUS API working as follows;

1- Admin user attempt to create/update user object mailbox via EMS or EMC operation, it calls RUS API

2- RUS API requests all policies from memory

3- DC' s returns address policy and adress lists to RUS API

4- RUS API returns list of attributes to the EMS or EMC

5- EMS or EMC requests required attribute list to RUS API and RUS API returns back to the EMC or EMS

6- EMC or EMS creates or updates object with required attributes in Active Directory (AD)

Whole of the above steps runs on mailbox server under the System Attendant process control.

I've try to write a sample script for user creation process and I've used New-Mailbox powershell command in this script. I hope this script helps for your business.

Actually following sample script doesn't have any risk for your system but please modify following script according your needs and don't run on your production environment before testing it in your test environment !!!

Note: You can copy following lines to a simple text file via notepad and run from powershell console.

Additional information regarding powershell;

https://www.microsoft.com/windowsserver2003/technologies/management/powershell/default.mspx

https://blogs.msdn.com/powershell/

-kekici-

# **************************************************************************

# This is a sample script for creating new server and mail enable process

#

# Author: Kutbettin Ekici

# **************************************************************************

# **************************************************************************

# This is first function which we have to use for new user data collection

function dataenter

{

Write-Host " "

Write-Host "New user (Required) information ... " -ForeGroundColor DarkGreen

Write-Host " "

# Required basic information for a sample user will collect by that way...

$FirstName = Read-Host "First Name"

$LastName = Read-Host "Last Name"

# Password need to collect as a secure string

$passWord = Read-Host "Password" -AsSecureString

# Global variable declaration in a function like that...

# By default variable scoping was local...

$global:Name = Read-Host "Logon name (it needs a unique value)"

$global:Displayname = $FirstName + " " + $LastName

$HomeMDB = Read-Host "Database path (HomeMDB) [For example; servername\StorageGroupName\DatabaseName] "

$alias = Read-Host "Alias name (it needs a unique value)"

$domain = Read-Host "What is the domain name for new user [For example; contoso.local] "

$UPN = $Name+"@"+$domain

Write-Host " "

Write-Host "Optional information for user... " -ForeGroundColor DarkGreen

Write-Host " "

# Optional data for new user

$OU = Read-Host "Organizational Unit location for new user [For example; /Contoso/Bim/Users/ ]"

if ($OU -eq "")

{

# Following line is not necessary but addressing static path will be fine…

$OU = $domain + "/" + "USERS"

}

# normally variable scope in a function by default is local, we can set it global with the following sample line...

# set-variable OU value -scope global

$SendSize = Read-Host "Mail send limit [For example; 1230KB, 2MB ]"

if ($SendSize -eq "")

{

$SendSize = "0KB"

}

$ReceiveSize = Read-Host "Mail receive limit [For example; 10000KB, 2MB ]"

if ($ReceiveSize -eq "")

{

$ReceiveSize = "0KB"

}

$global:Description = Read-Host "User Description [For example; Customer Account Manager]"

$global:title = Read-Host "Title : [For example; Account Manager]"

# Calling createUserMBX function

createUserMBX

}

function createUserMBX

{

Write-Host " "

Write-Host " User Information will be… : " -ForeGroundColor DarkGreen

Write-Host "Name : " $DisplayName -ForeGround Blue

Write-Host "Alias : " $Alias -ForeGround Blue

Write-Host "OU : " $OU -ForeGround Blue

Write-Host "UPN : " $UPN -ForeGround Blue

Write-Host "Logon Name : " $Name -ForeGround Blue

Write-Host "DB address : "$HomeMDB -ForeGround Blue

Write-Host "Send Limit : " $SendSize -ForeGround Blue

Write-Host "Receive Limit : " $ReceiveSize -ForeGround Blue

Write-Host " "

# ************************************************************************

$SecondQuestion = Read-Host "Do you want to create this user with the above information ? Yes (Y) / No: (N)"

if ($SecondQuestion -eq 'Y' )

{

# exception handling lines....

trap {

Write-Host " An error occured, please check the following detailed information and take an action for resolution. " -ForeGroundColor RED -BackGroundColor WHITE

Write-Host " "

break

}

# we are creating user by calling RUS API with the “new-mailbox” command...

New-Mailbox -Name $Name -Alias $Alias -OrganizationalUnit $OU -UserPrincipalName $UPN -SamAccountName $Name -FirstName $FirstName -LastName $LastName -Database $HomeMDB -ResetPasswordOnNextLogon $false -Password $passWord;

if (($SendSize -eq '0KB') -and ($ReceiveSize -eq '0KB'))

{

}

else

{

if ($SendSize -ne '0KB')

{

Set-Mailbox -identity $Alias -MaxSendSize $SendSize

}

if ($ReceiveSize -ne '0KB')

{

Set-Mailbox -identity $Alias -MaxReceiveSize $ReceiveSize

}

}

# This is a sample line for additional settings

# OWA enabled by default With the following line we can disable OWA for new users

# Set-CASMailbox -identity $Alias -OWAEnabled $false

#We are calling new user Ldap path for optional data entry

}

else

{

Write-Host " An error occurred in user creation phase...! " -ForeGround Blue

break

}

}

# **************************************************************************

function get-dn ($Name)

{

Write-Host " "

write-host "Searching" $DisplayName "named new user in the active directory..."

Write-Host " "

trap {

Write-Host " Problems occurred related AD connection or user creation. " -ForeGroundColor RED -BackGroundColor WHITE

Write-Host " Please check error message and take correct action. " -ForeGroundColor RED -BackGroundColor WHITE

Write-Host " "

break

}

# We are starting a powershell ADSI session...

$root = [ADSI]

# By using .NET directory service we are describe a searcher object for ADSI interface

$searcher = new-object DirectoryServices.DirectorySearcher($root)

#Setting up a name filter for user class

$searcher.filter = "(&(objectClass=user)(name= $Name))"

#Listing all possible results... (It's a unique value...)

$user = $searcher.findall()

if ($user.count -gt 1)

{

$count = 0

foreach($i in $user)

{

write-host $count ": " $i.path

$count = $count + 1

}

$selection = Read-Host "Please select item: "

# returning Ldap path back to the requested function...

return $user[$selection].path

}

else

{

return $user[0].path

}

}

function lastUserSetup

{

$global:LDAPpath = get-dn $Name

# another variable scope declaration way is: set-variable var -scope global

trap {

Write-Host " Probably script didn't complete update user: $DisplayName for it's additional attributes. " -ForeGroundColor RED -BackGroundColor WHITE

Write-Host " Please check the error message and take required action. " -ForeGroundColor RED -BackGroundColor WHITE

Write-Host " "

break

}

$NewUser = New-Object System.DirectoryServices.DirectoryEntry $LDAPpath

if ($Displayname -ne "")

{$NewUser.Put('displayName',$DisplayName)}

if ($Description -ne "")

{$NewUser.Put('description',$Description)}

if ($title -ne "")

{$NewUser.Put('title',$title)}

if (($Displayname -eq "") -and ($Description -eq "") -and ($title -eq ""))

{

Write-Host "There isn't any update ..."

}

else

{

Write-Host " "

#We are writing all attributes with the following line

$NewUser.SetInfo()}

Write-Host "Update operation completed successfully."

Write-Host " "

}

function results

{

$NewUser = New-Object System.DirectoryServices.DirectoryEntry $LDAPpath | Select-Object *

Write-Host "************************************************************************** " -ForeGroundColor DarkGREEN

Write-Host "********* User created or updated with the following information ********* " -ForeGroundColor DarkGREEN

Write-Host "E-mail Address : "

Write-Host $newUser.mail -ForeGroundColor DarkGreen

Write-Host " "

Write-Host "Server Path : "

write-host $newUser.msExchHomeServerName -ForeGroundColor DarkGreen

Write-Host " "

Write-Host "Database Path : "

write-host $newUser.homeMDB -ForeGroundColor DarkGreen

Write-Host " "

Write-Host "Display Name : "

write-Host $newUser.DisplayName -ForeGroundColor DarkGreen

Write-Host " "

Write-Host "Logon Name : "

write-host $newUser.sAMAccountName -ForeGroundColor DarkGreen

Write-Host " "

Write-Host "Title : "

Write-Host $newUser.title -ForeGroundColor DarkGreen

Write-Host " "

Write-Host "Description : "

write-host $newUser.description -ForeGroundColor DarkGreen

Write-Host " "

Write-Host " ************************************************************************** " -ForeGroundColor DarkGREEN

}

# This is the start point of powershell script

# Just giving a sample for Read-Host and if statement....

$FirstQuestion = Read-Host " What do you need ? For a new user plase press:Y / For updating a user please press: U "

# if statement sample...

if ($FirstQuestion -eq 'Y' )

{

# We are calling dataenter function by the following line

dataenter

lastUserSetup

results

break

}

else

{

Write-Host " Update function is not implemented yet. " -ForeGroundColor GREEN

break

}