8/22/14 Update: I’ve made some improvements to the script, make sure you get the latest version from: http://izzy.org/scripts/Exchange/Admin/Create-Mailbox.ps1
One of the most common tasks for Exchange admin is creating mailboxes. This can easily be done with the GUI (EMC\EAC) but some settings can’t be set using the creation wizard or in the GUI at all. So I always recommend my clients automate the creation of mailboxes to ensure that they are created with the correct attributes. So I’ve decided to share my mailbox creation script with everyone!
This script will not only create a mailbox, but it will also copy an existing user and some of their attribute (using New-ADUser -Instance $objSourceUser) and optionally send them a “Welcome” e-mail. When creating the mailbox the script will get the smallest database, by size, that matches a filter provided and finally set the retention and arching policy on it.
The latest source of this script should always be here: https://gallery.technet.microsoft.com/Script-Excahnge-Copy-an-1b7f1553
Usage example: .\Create-Mailbox.ps1 -NewUserID “JoeSales” -GivenName “Joe” -Surname “Sales” -SourceUserID “_SalesTemplate” -CustomAttrib “Team 1”
The example above will create a new user account for “Joe Sales” based on the “_SalesTemplate” account. By default it will copy the following attributes from the template: MemberOf, Description, Company, Department, Office, Title, streetAddress, City, State, PostalCode, Country. In addition, it will optionally set CustomAttribute10 to “Team 1”; this is handy if you have EAPs that use a custom attribute.
The script has some basic error handling and by default will continue the mailbox creation process if the new user ID already exist.
The following lines should be customized for your environment:
$Group = ‘Mail Users’ # Only used if $AddToGroup = $True
$Password = “P@ssW0rD!”
$UPNSufix = “@izzy.org”
$SMTPServer = “mail.altered.com”
$From = “ExchangeAdmins@company.com”
$MsgSubject = “Welcome to the Company!”
$MsgBody = Get-Content “D:\Tools\Welcome.htm” # (Example here: http://izzy.org/scripts/Exchange/Admin/Welcome.htm)
# This script create a new mailbox on the smallest mailbox database that matches a filter and set other attributes # Created by Jason Sherry (izzy@izzy.org) 4/20/2012 # Last Updated: 8/22/2014 # 5/24/12: Added support to add user to a group & set CustomAttribute10 # 7/8/13: Added support to copy a template user account, including a list of attributes and group membership # 7/23/13: Fixed an issue with $Null detection for parameters # 8/22/14: Added error handling for when no databases are returned, when no other name values are provided, & when source member of is empty # Source: https://gallery.technet.microsoft.com/Script-Excahnge-Copy-an-1b7f1553 # Partial code source: http://powershell.com/cs/media/p/3981.aspx param( [Parameter(Mandatory = $true)][String]$NewUserID, [String]$SourceUserID = $Null, [String]$DisplayName = $Null, [String]$GivenName = $Null, [String]$Surname = $Null, [String]$CustomAttrib = $Null, [String]$SendWelcome = $True) $DBFilter = "Primary*" # Limit databases to only those that start with "Primary" $RetentionPolicy = "Default Archive and Retention Policy" $ContiuneOnExist = $True # Option good for testing $CopyAttributes = "MemberOf","Description","Company","Department","Office","Title","streetAddress","City","State","PostalCode","Country" # List of properties: http://social.technet.microsoft.com/wiki/contents/articles/12037.active-directory-get-aduser-default-and-extended-properties.aspx $AddToGroup = $False $Group = 'Mail Users' $Password = "P@ssW0rD!" $UPNSufix = "@izzy.org" $SMTPServer = "mail.altered.com" $From = "ExchangeAdmins@company.com" $MsgSubject = "Welcome to the Company!" $MsgBody = Get-Content "D:\Tools\Welcome.htm" | out-string Function Get-SmallestDB { Try { $MBXDbs = Get-MailboxDatabase | ? {$_.Identity -like $DBFilter } $MBXDBCount = $PSSessions.Count } Catch { $MBXDBCount = 0 } If (!$MBXDbs) {ExitScript "find databases with a name that matches a filter of [$DBFilter]." $False} # Loop through each of the MBXDbs ForEach ($MBXDB in $MBXDbs) { # Get current mailboxes sizes by summing the size of all mailboxes and "Deleted Items" in the database $TotalItemSize = Get-MailboxStatistics -Database $MBXDB | %{$_.TotalItemSize.Value.ToMB()} | Measure-Object -sum $TotalDeletedItemSize = Get-MailboxStatistics -Database $MBXDB.DistinguishedName | %{$_.TotalDeletedItemSize.Value.ToMB()} | Measure-Object -sum #XXX $TotalDeletedItemSize = Get-MailboxStatistics -Database $MBXDB| %{$_.TotalDeletedItemSize.Value.ToMB()} | Measure-Object -sum #Get-MailboxDatabase and the DatabaseSize property was not used since it does not return a value in some environments as of 2010 SP2 $TotalDBSize = $TotalItemSize.Sum + $TotalDeletedItemSize.Sum # Compare the sizes to find the smallest DB If (($TotalDBSize -lt $SmallestDBsize) -or ($SmallestDBsize -eq $null)) { $SmallestDBsize = $DBsize $SmallestDB = $MBXDB }} return $SmallestDB } Function ExitScript ($ErrorText,$ShowFullError) { Write-Host "`nAn error occurred when trying to $ErrorText, exiting script`r`n" -ForegroundColor Red If ($ShowFullError) { Write-Host "Error: " $error[0] -ForegroundColor Red } Break } Function CopyUser ($SourceUser,$NewUser,$GivenName,$Surname,$DisplayName) { Import-module ActiveDirectory If ($DisplayName -eq "") { If ($GivenName -eq "" -And $SurName -eq "") { $DisplayName = $NewUserID } Else { $DisplayName = "$GivenName $SurName" # Set DisplayName if it's blank } $DisplayName = $DisplayName.Trim() # Removes the leading & trailing spaces } Write-Host "New user account will be based on user: [$SourceUser]" -ForegroundColor Green Try {$UserTemp = Get-User $SourceUser -ErrorAction SilentlyContinue} Catch {ExitScript "run [Get-User $SourceUser], confirm user ID exist" $False} $UserTemp = $Null $UserTemp = Get-User $NewUser -ErrorAction SilentlyContinue If ($UserTemp -and !$ContiuneOnExist) { Write-Host "User ID $NewUser already exist, script exiting." -ForegroundColor Red Exit } ElseIf ($UserTemp -and $ContiuneOnExist) { Return } $SecurePassword = convertto-securestring $Password -asplaintext -force Try {$objSourceUser = Get-ADUser -Identity $SourceUser -Properties $CopyAttributes -ErrorAction Stop} Catch {ExitScript "run [Get-ADUser $SourceUser], confirm user ID exist" $False} $OUPath = $objSourceUser.DistinguishedName.Replace("CN=$($objSourceUser.Name),","") Write-Host "`tCreating user -> DisplayName: [$DisplayName] GivenName: [$GivenName] SurName: [$SurName] `n`tCreating in OU: [$OUPath]" -ForegroundColor Cyan New-ADUser -Instance $objSourceUser -UserPrincipalName "$NewUser$UPNSufix" -SAMAccountName $NewUser -Name $DisplayName -DisplayName $DisplayName -AccountPassword $SecurePassword -GivenName $GivenName -Surname $Surname -Path $OUPath Set-ADUser -Identity $NewUser -Enabled $True # I've seen the accounts randomly not being enabled without this # -Instance required Windows 2008 R2 DCs: http://technet.microsoft.com/en-us/library/dd378959(v=ws.10).aspx Sleep 1 # Delay to prevent object not found error with below command If ($objSourceUser.memberOf) { Get-ADUser -Identity $NewUser | Add-ADPrincipalGroupMembership -MemberOf $objSourceUser.memberOf } } If ($SourceUserID){ CopyUser $SourceUserID $NewUserID $GivenName $Surname $DisplayName } Else { Write-Host "SourceUserID not specified, script will assume user [$NewUserID] already exist and will Mailbox enabled it only." -ForegroundColor Yellow } Try {$UserTemp = Get-User $NewUserID -ErrorAction Stop} Catch {ExitScript "run [Get-User $NewUserID], confirm user ID exist" $False} Write-Host "`nGetting smallest Exchange DB that matches filter [$DBFilter]..." -ForegroundColor Green -NoNewLine $TargetDB = Get-SmallestDB Write-Host " Found, [$TargetDB] will be used." -ForegroundColor Green Write-Host "`nCreating mailbox for [$NewUserID] on [$TargetDB]" -ForegroundColor Cyan Try {Enable-Mailbox $NewUserID -Database $TargetDB -ErrorAction Stop} Catch { If ($_.Exception.Message -like '*is of type UserMailbox*') { Write-Host `t "[$NewUserID] already has a mailbox, continuing to next step " -ForegroundColor Yellow} Else {ExitScript "run [Enable-Mailbox $NewUserID -Database $TargetDB]" $True}} Write-Host "Enabling retention policy and single item recovery" -ForegroundColor Cyan Try {Set-Mailbox $NewUserID -RetentionPolicy $RetentionPolicy -SingleItemRecoveryEnabled $true -CustomAttribute10 $CustomAttrib -ErrorAction Stop} Catch {ExitScript "run [Set-Mailbox $NewUserID -RetentionPolicy $RetentionPolicy -SingleItemRecoveryEnabled $true]" $True} If ($AddToGroup) { Try {Add-DistributionGroupMember -Identity $Group -Member $NewUserID -BypassSecurityGroupManagerCheck -ErrorAction Stop} Catch { If ($_.Exception.Message -like '*already a member of the group*') { Write-Host `t "Object [$NewUserID] is already in [$Group]" } Else {ExitScript "run [Add-DistributionGroupMember -Identity $Group -Member $NewUserID]" $True}} } If ($SendWelcome) { $objNewUser = Get-ADUser $NewUserID -Properties "EmailAddress" $EmailAddress = $objNewUser.EmailAddress If ($EmailAddress -eq $Null) { Write-Host "New user [$NewUserID] not found, waiting 5 seconds and retying..." Start-Sleep -s 5 $objNewUser = Get-ADUser $NewUserID -Properties "EmailAddress" $EmailAddress = $objNewUser.EmailAddress If ($EmailAddress -eq $Null) { Write-Host "New user still not found, Welcome e-mail not sent. Exiting." Exit } } Write-Host "`nSending Welcome message to [$EmailAddress], waiting 10 seconds for mailbox creation process to finish" -ForegroundColor Cyan start-sleep 10 # This delay is sometimes needed # See http://www.thegenerationv.com/2012/01/using-rich-html-with-send-mailmessage.html for Send-Mail HTML examples Try {Send-MailMessage -From $From -To $EmailAddress -Subject $MsgSubject -Body $MsgBody -SmtpServer $SMTPServer -BodyAsHtml} Catch {ExitScript "run [Send-MailMessage -From $From -To $EmailAddress -SmtpServer $SMTPServer]" $True} }
Pingback: Script: Set-MailboxPolicies.ps1 | Jason (Izzy) Sherry's Blog
Looks promising, but I’m getting this for line 125:
The Try statement is missing its Catch or Finally block.
LikeLike
Just ran multiple test against it, found one issue with $Null detection when an account is not being copied. Ran fine otherwise and I’ve updated the code above with a fix for the $null issue.
Note: This script has only been tested against Exchange 2010, might work with 2013 but won’t with 2007 due to PowerShell 2.0 usage.
LikeLike
I still get the same thing, only now it is on line 128 instead. Exchange 2010 here btw.
I’ll keep banging on it and see if I can get it going.
LikeLike
Try the version posted here:
http://izzy.org/scripts/Exchange/Admin/Create-Mailbox.ps1
Something must be getting changed when you are coping it from the blog.
LikeLike
I wish it was that, I tried both of them.
LikeLike
I just copied the text from the blog to a new file on and it ran fine.
Get ride of the Try\Catch stuff and see if it works without it. Let’s take this off-line too, you can e-mail me at izzy [at] izzy.org
LikeLike
I found a few hidden\odd\HTML characters in the script on the blog. I’ve updated it, but I suggest people download the PS1 file directly from my servers to prevent this issue. I’ve seen WordPress mess up code a few times now.
LikeLike
In addition to, can one add permissions to others mailbox within that script.
LikeLike
Pingback: Script: Set-UPN-O365.ps1 – Sets UPNs on-premises and in Office 365 | Jason (Izzy) Sherry's Blog