Creating an AD mail-enable user following the Mailbox Server Role Requirements Calculator

 

.: Cute Tamales .:

As we all know, English has become an international IT language. For this reason, from now on, the majority of my posts will be written in English. I apologize to my Portuguese readers who might find this a bad idea.

Last post I wrote about the recommended method of storing multiple mailbox tiers in the same Exchange database, based on the spreadsheet maintained by the Exchange team. I also added a script that shows the users’ distribution per quota within a database, what would be a starting point for a bigger script responsible for provisioning AD user accounts and mailboxes.

Curiously, after writing the last post a costumer called me asking if I knew any script or tool that would help him replace the actual Exchange 2003 process/tool that he has in place, which will not work in Exchange 2010. It made me think about it, and right away I put some pieces of code together and ended-up with a PSH script which could be used by a Help Desk guy for creating an AD mail-enable user.

I did not have time to improve the script as I would like, but it worked pretty well.

In a nutshell the script can be broken down in four parts.

1. Functions Read-Default and checkRegex. They extend the Read-Host cmdlet. They present to the user a default option and validate the response against a regular expression.

2. Function selectDB. It randomly picks an Exchange database name and checks if there is enough room (#max user’s tier) to add the user mailbox into it, considering the user’s quota information and a (manually) pre-defined mailbox tier configuration. Be aware that this way your Exchange databases will not be balanced among themselves, but the difference (in theory) should not be substantial.

Pay attention to the part that requires manually configuration of the Exchange databases name, quota values of mailbox tier 1, tier 2 and tier 3 and the maximum user’s tier per database (from the E2010 Mailbox Server Role Requirements Calculator). As a side note, I would easily get all the Exchange databases names using PSH; however, It would get database names not used in production, so I decided to hard code it on $databases variable.

3. Function ChangeQuota is pretty straightforward. Nevertheless, there is one caveat. The variable $mbquota refers to ProhibitSendReceiveQuota. The IssueWarningQuota is calculated with 90% of the $mbquota and ProhibitSendQuota 95%.

4. It is the scripts’ main part. It enters a loop that shows the menu and initializes the variables. Once the loop finishes, It asks for password (only once), calls the selectDB function and then run the New-Mailbox cmdlet - Don’t forget to change the parameter of OrganizationalUnit, to one that fits you better.

In sequence it runs the set-ADuser cmdlet and the function changeQuota .

Feel free to send me improvements or bug reports.

<#
.SYNOPSIS
Using a menu option a Help Desk user can create an AD user and its mailbox into Exchange 2010. It requires AD and Exchange modules.
.DESCRIPTION
.NOTES
Version : 1.0 - 12/07/2010 - initial version
          1.1 - 15/07/2010 - Added support for four mailbox tiers

Rights Required : Permissions to create a user and a mailbox
Exchange Version : 2010
Author : Artur Rodrigues
Dedicated Blog : https://blogs.technet.com/arturlr
Disclaimer : Use this script at your own risk. There is no guarantee.
.LINK
https://msexchangeteam.com/archive/2009/11/09/453117.aspx
.EXAMPLE
.\createMBuser.ps1
.INPUTS
None. You cannot pipe objects to this script.
#>
#Requires -Version 2.0
## Extend the Read-Host cmdlet to be able to have a default value and check the expression
## First parameter tells with regex expression will be used based on the checkRegex function
## Second parameter defines the message to be displayed
## Third parameter defines the default value
function Read-Default([int]$itype, [string]$strmessage, [string]$strDefault)
{
while ($true) {
Write-Host $strmessage -NoNewline -ForegroundColor White
if ($strDefault.length -gt 0) { Write-Host " [$strDefault] : " -NoNewline -ForegroundColor Yellow }
else { Write-Host ": " -NoNewline }
$result = Read-Host
if ($result.length -eq 0 ) {$result = $strDefault}
if (checkRegex $itype $result) { break }
}
$result
}

## Checks the expression for the Read-Default function
function checkRegex ([int]$iopt,[string]$strCheckName)
{
switch ($iopt) {
0 {$regex = "^[a-zA-Z0-9\.-_]{2,200}$"; Write-Host "Invalid characters. Only AlphaNumeric with no spaces" -ForegroundColor Red ;break} ## allows alphanumeric characters NO SPACES and . - _
1 {$regex = "^[\w\s -.]{2,200}$"; Write-Host "Invalid characters." -ForegroundColor Red ;break} ## allows alphanumeric characters
2 {$regex = "^[0-9 \s ().-]{3,20}$"; Write-Host "Invalid characters. Use: (XX) XXXX-XXXX" -ForegroundColor Red ;break} #Phone
3 {$regex = "^\d{5}(\-)(\d{3})?$"; Write-Host "Invalid characters. Use: XXXXX-XXX" -ForegroundColor Red ;break} #CEP (Brazilian)
4 {$regex = "^[0-9]{1,4}$"; Write-Host "Invalid characters. Only Numeric" -ForegroundColor Red ;break} #Only Numeric
}
If ($strCheckName -match $regex) { $rst = $true }
else {$rst = $false }
$rst
}

## Randomly select an Exchange Database and checks if the # max user per database was reached.
## This script assume that you have 3 tiers with 3 different quotas.
## tier 1 has the lowest quota, for instance, 300MB. So, tier 1 is by default the database quota.
## tier 2, for instance, get all mailboxes from 300MB to 600MB.
## tier 3, for instance, get all mailboxes from 600MB to 1024MB.
## tier 4 has the highest quota. In that case all mailboxes above 1024MB
function SelectDB([int]$quota)
{
#$DebugPreference = "Continue"
$tier = @()
# !!!!!!!!!!!!!!!!!!!!! Start your specific Exchange configuration data here !!!!!!!!!!!!!!!!!!!!!!!!!
# Adds the databases names
$databases = "DB1","DB2","DB3","DB4","DB5","DB6","DB7","DB8","DB9"
#"tier's Name", #user (DO NOT CHANGE IT!), #max user for this tier per database(from the E2010 Mailbox Server Role Requirements Calculator)
# In this example a database can only have 1667 users, 1444 from tier1, 167 from tier2 and 56 from tier3
$tier += ,@("tier 1", 0,1200)
$tier += ,@("tier 2", 0,500)
$tier += ,@("tier 3", 0,150)
$tier += ,@("tier 4", 0,50)
$quotatier1 = 300
$quotatier2 = 600
$quotatier3 = 1024
# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! End of customization part !!!!!!!!!!!!!!!!!!!!!!!!!

# Adds the current mailbox to the write tier
if ($quota -le $quotatier1) {$usertier = "tier 1"}
elseif (($quota -gt $quotatier1) -and ($quota -le $quotatier2)) { $usertier = "tier 2" }
elseif (($quota -gt $quotatier2) -and ($quota -le $quotatier3)) { $usertier = "tier 3" }
elseif ($quota -gt $quotatier3) { $usertier = "tier 4" }

#Picks randomly a database
$db = Get-Random $databases
$mailboxes = Get-Mailbox -Database $db -resultsize unlimited
$dbProp = Get-MailboxDatabase $db
Write-Debug "$quota - $usertier - $db"
if ($mailboxes.count -ne $null) {
foreach ($mailbox in $mailboxes) {
$flag = $false
if ($mailbox.IsMailboxEnabled -eq $false) {continue}
if ($mailbox.ProhibitSendReceiveQuota -eq "unlimited" -and $mailbox.UseDatabaseQuotaDefaults -eq $false) {$quotatier = "tier 4"}
elseif (($mailbox.UseDatabaseQuotaDefaults -eq $true) -or ($mailbox.ProhibitSendReceiveQuota.value.toMB() -le $quotatier1)){$quotatier = "tier 1" }
elseif (($mailbox.ProhibitSendReceiveQuota.value.toMB() -gt $quotatier1) -and ($mailbox.ProhibitSendReceiveQuota.value.toMB() -le $quotatier2)){ $quotatier = "tier 2" }
elseif (($mailbox.ProhibitSendReceiveQuota.value.toMB() -gt $quotatier2) -and ($mailbox.ProhibitSendReceiveQuota.value.toMB() -le $quotatier3)){ $quotatier = "tier 3" }
elseif ($mailbox.ProhibitSendReceiveQuota.value.toMB() -gt $quotatier3){ $quotatier = "tier 4" }
Write-Debug "$mailbox - $quotatier"

for ($count = 0; $count -le 3; $count++) {
if ($tier[$count][0] -eq $quotatier) { $tier[$count][1] += 1;$flag = $true;break }
}
if ($flag -eq $false) {$tier += ,@($quotatier, 1);$iloop += 1 }
}
for ($count = 0; $count -le 3; $count++) {
if ($usertier -eq $tier[$count][0]) {
if ($tier[$count][1] -gt $tier[$count][2]) { Write-Debug $tier[$count][1]; $db="FAIL";break }
else { Write-Debug $tier[$count][1] }
}
}
}
$db
}
## Set the mailbox quota based on the following rule:
## Warning with 90% mailbox capacity
## ProhibitSend with 95% mailbox capacity
## ProhibitSendReceive with the $mbuser value
function ChangeQuota($quota,$mbuser)
{
$IWQValue = [Math]::Round([int]$quota - ([int]$quota * 0.1)).ToString()
$PSQValue = [Math]::Round([int]$quota - ([int]$quota * 0.05)).ToString()
$PSRQValue = $quota
$IWQ = $IWQValue.ToString() + "MB"
$PSQ = $PSQValue.ToString() + "MB"
$PSRQ = $PSRQValue.ToString() + "MB"
Set-Mailbox -Identity $mbuser.trim() -UseDatabaseQuotaDefaults $False -ProhibitSendQuota $PSQ -ProhibitSendReceiveQuota $PSRQ -IssueWarningQuota $IWQ
}

Import-Module activedirectory

$opt = ""
do {
switch ($opt)
{
1 {$firstname = Read-Default 0 "1. First Name " ; break}
2 {$lastname = Read-Default 0 "2. Last Name " ; break}
3 {$samAccountName = Read-Default 0 "3. User Logon Name" "$firstname.$lastname"; if (([ADSISearcher]"samAccountName=$samAccountName").findone()) {Write-Host "Usuário $samAccountName já existe" -foregroundcolor Red; break } }
4 {$displayname = Read-Default 1 "4. Display Name" $firstname,$lastname; break}
5 {$description = Read-Default 1 "5. Description " $description; break}
6 {$office = Read-Default 1 "6. Office " $office; break}
7 {$phone = Read-Default 2 "7. Phone " $phone; break}
8 {$street = Read-Default 1 "8. Street " $street; break}
9 {$city = Read-Default 1 "9. City " "Brasilia"; break}
10 {$state = Read-Default 1 "10. State " "DF"; break}
11 {$zip = Read-Default 3 "11. ZIP " "70000-000"; break}
12 {$title = Read-Default 1 "13. Title "; break}
13 {$department = Read-Default 1 "14. Department "; break}
14 {$company = Read-Default 1 "15. Company "; break}
15 {$mbquota = Read-Default 4 "16. Quota (MB) [0-Database Default]" "0"; break}
16 {$notes = Read-Default 1 "17. Notes "; break}
}
if ($opt -gt 16) {write-host "Last command: "$opt -foregroundcolor Yellow}
#Show menu
clear-host
Write-Host "------------------> Mailbox User Entry <------------------ " -ForegroundColor Green
Write-Host "1. First Name : " -NoNewline
Write-Host $firstname -ForegroundColor Yellow
Write-Host "2. Last Name : " -NoNewline
Write-Host $lastname -ForegroundColor Yellow
Write-Host "3. User Logon Name : " -NoNewline
Write-Host $samAccountName -ForegroundColor Yellow
Write-Host "4. Display Name : " -NoNewline
Write-Host $displayname -ForegroundColor Yellow
Write-Host "5. Description : "-NoNewline
Write-Host $description -ForegroundColor Yellow
Write-Host "6. Office : " -NoNewline
Write-Host $office -ForegroundColor Yellow
Write-Host "7. Phone : " -NoNewline
Write-Host $phone -ForegroundColor Yellow
Write-Host "8. Street : " -NoNewline
Write-Host $street -ForegroundColor Yellow
Write-Host "9. City : " -NoNewline
Write-Host $city -ForegroundColor Yellow
Write-Host "10. State : " -NoNewline
Write-Host $state -ForegroundColor Yellow
Write-Host "11. ZIP : " -NoNewline
Write-Host $zip -ForegroundColor Yellow
Write-Host "12. Title : " -NoNewline
Write-Host $title -ForegroundColor Yellow
Write-Host "13. Department : " -NoNewline
Write-Host $department -ForegroundColor Yellow
Write-Host "14. Company : " -NoNewline
Write-Host $company -ForegroundColor Yellow
Write-Host "15. Quota (MB) : " -NoNewline
Write-Host $mbquota -ForegroundColor Yellow
Write-Host "16. Notes : " -NoNewline
Write-Host $notes -ForegroundColor Yellow
Write-Host "[C]. Create User" -ForegroundColor White
Write-Host
if ($msgErr -ne $null) {write-host $msgErr -foregroundcolor Red; $msgErr = $null}
$opt = Read-Host "Select an option.. [1-16] [C]? "
if ($opt -eq "C" -or $opt -eq "c") {
if (($samAccountName -eq $null) -or ($displayname -eq $null) -or ($mbquota -eq $null)) {
$msgErr = "Please, fill the fields 3, 4 and 15!"
}
else {break}
}
} while ($true)
$password = Read-Host "Password :" -AsSecureString
$ifail =0

do {
$MDB = SelectDB $mbquota
Write-Debug $mdb
if ($MDB -eq "FAIL") { $ifail += 1}
if ($ifail -eq 5) { Write-Host "Error on selecting Database!"; exit }
} while ($MDB -eq "FAIL")

New-Mailbox -Name $displayname.Trim() `
-Database $MDB `
-Password $password `
-UserPrincipalName $samAccountName@contoso.com `
-ActiveSyncMailboxPolicy "Default" `
-Alias $samAccountName `
-Confirm `
-DisplayName ($displayname.Trim()) `
-FirstName $firstname `
-LastName $lastname `
-OrganizationalUnit "contoso.com/newusers" `
-ResetPasswordOnNextLogon $true `
-SamAccountName $samAccountName

## Wait for DC's to pick up change
Start-Sleep -s 10
$HashTable = New-Object HashTable
if ($description -ne $null) { $HashTable.Add("description", $description) }
if ($department -ne $null) { $HashTable.Add("department",$department) }
if ($phone -ne $null) { $HashTable.Add("homephone",$phone) }
if ($office -ne $null) { $HashTable.Add("physicalDeliveryOfficeName",$office) }
if ($street -ne $null) { $HashTable.Add("streetAddress",$street) }
if ($city -ne $null) { $HashTable.Add("l",$city) }
if ($state -ne $null) { $HashTable.Add("st",$state) }
if ($zip -ne $null) { $HashTable.Add("postalCode",$zip) }
if ($title -ne $null) { $HashTable.Add("title",$title) }
if ($company -ne $null) { $HashTable.Add("company",$company) }
Set-ADUser $samAccountName -Replace $HashTable
if ($mbquota -ne "0") { ChangeQuota $mbquota $samAccountName}