In Exchange 2007, they have finally done resources correct. Using Powershell, you can define a mailbox specifically as a conference room, laptop, projector or other resource. As a resource it will appear differently in Outlook 2007 and OWA. These resources can be defined to automagically accept meeting requests using specific permissions on these resources. No longer will you need to use the flaky AAA as in Exchange 2003.
The attached script is my very detailed, all-in-one convert a standard/migrated mailbox to a conference room resource in Exchange 2007.
Some specifics on the script:
- It is built to convert a Linked Mailbox (mailbox using external domain account for authentication). The script will convert your mailbox to a standard, disabled user mailbox. It has smarts enough that you can re-run the script with no negative impact (i.e. it won't attempt to convert it twice).
- If it finds the mailbox is an "user" mailbox, it will convert it to a conference room resource.
- You will be given the option to specify who (mailbox, group) can book it.
- You will be given the option to specify who can delegate (administer) the room.
- You will be given the option to specify room specifics.
We typically have a person on our Help Desk who has local mailbox rights. You will need to change/remove the HelpDesk@Example.com mailbox in the code.
The script uses both Exchange 2007 Powershell cmdlets and Quest Active Roles cmdlets. I may try re-writting the code someday so that it only relies on the Exchange cmdlets, but not right now.
# - Converts from LinkedMailbox to UserMailbox
# - Converts from UserMailbox to ROOMMailbox
# - Gathers and applies permissions for delegates
# - Gathers and grants permissions for authorized meeting requestors list
function DoesitHave($Resource){
$str = "Does this conference room have a/an "+$resource + "? (y/n)"
do {
$answer = Read-Host $str
} while ($answer -ne "y" -and $answer -ne "n")
if ($answer -eq "y") {
return $true
} else {
return $false
}
}
[reflection.assembly]::LoadWithPartialName("'Microsoft.VisualBasic")
function isNumeric ($a) {
$b = [Microsoft.VisualBasic.Information]::isnumeric($a)
return $b
}
function Convert-toUserMbx ($mbx) {
#"Convert" mailbox from LINKED to USER format.
#This unfortunately requires
if ($Mbx.RecipientTypeDetails -eq "LinkedMailbox") {
Write-Host "This is a LINKED mailbox, need to convert to a USER"
Write-Host "Converting... DO NOT STOP THE SCRIPT OR YOU MAY HAVE TO RECONNECT THE ACCOUNT!"
$mbxAlias = $mbx.Alias
$MyMailbox = $Mbx.DisplayName
"Linked mailbox - converting to UserMailbox"
Disable-mailbox $MyMailbox -erroraction stop -outvariable Result
$mbxUPN = $mbx.UserPrincipalName
$DB = $Mbx | select database| % {Get-MailboxDatabase -Identity $_.database}
#Pausing script while waiting for the Disable-Mailbox command to process.
do {
$isDisabled = get-user -identity $mbxUPN
} while ( $isDisabled.recipienttype -eq "UserMailbox")
#Create a new password for the account based on the UPN field.
Write-Host "Setting account password to :'" $mbxUPN "'"
$pwd = new-object Security.SecureString
$mbxUPN.ToCharArray() | foreach { $pwd.AppendChar($_)}
Set-QADUser -Identity $mbxUPN -UserPassword $pwd
write-host "Reconnecting mailbox to domain account"
## found I needed to enble the AD account to get next step to work.
enable-qaduser -identity $mbxUPN
Connect-mailbox -identity $MyMailbox -database $DB -user $mbxUPN -Alias $mbxalias
#Conference room processing wants disabled account.
disable-qaduser -identity $mbxUPN
#Pausing script to wait for AD replication
do {
$isDisabled = get-user -identity $MyMailbox
} while ( $isDisabled.recipienttype -ne "UserMailbox")
$Mbx = get-mailbox $MyMailbox
Write-Host "Finished converting mailbox. "
}
return $mbx
}
function Convert-toResource ($mbx) {
#Convert standard mailbox to conference room resource
if ($Mbx.RecipientTypeDetails -eq "UserMailbox") {
write-host "Converting to Conference Room mailbox"
$mbxAlias = $mbx.Alias
$MyMailbox = $Mbx.DisplayName
$mbxUPN = $mbx.UserPrincipalName
$DB = $Mbx | select database| % {Get-MailboxDatabase -Identity $_.database}
Set-Mailbox -identity $mbx.DistinguishedName -Type room
do {
$isDisabled = get-user -identity $mbxUPN
} while ( $isDisabled.RecipientTypeDetails -ne "RoomMailbox")
$Mbx = get-mailbox $mbx.DistinguishedName
}
return $mbx
}
cls
$ConfRoomName = Read-Host "What is the name of the conference room?"
if ($confroomname.Trim() -eq "") {break}
$CRObj = Get-Mailbox $ConfRoomName -ErrorAction silentlycontinue
if ($crobj -eq $null) {Write-Host "cannot find conference room";exit}
#If Mailbox on Exchange 2003 server, break
$MBXServer = Get-ExchangeServer $crobj.servername
if ($mbxserver.ExchangeVersion.ExchangeBuild.Major -eq 6) {Write-Host "Mailbox is on Exchange 2003 server. Needs moved.";exit}
if ($AuthRequestors -ne $null) {
#If you ran the script dot sourced, it will allow you to use the previous values.
write-host " -------------------"
write-host "Currently Authorized Requestors (" ($AuthRequestors.Count)"):"
($AuthRequestors | sort| ft)
write-host " -------------------"
}
$answer = read-host "Would you like to define new authorized requestors? (y/n)"
if ($answer.Trim() -eq "y") {
Write-Host "Who is allowed to invite this conference room?"
Write-Host "Hit ENTER to end input"
$AuthRequestors = @()
do {
$name = Read-Host "Authorized Requestor (" ($AuthRequestors.Count+1)")"
if ($name.trim() -ne "") {
$mbx = Get-QADObject $name -ErrorAction silentlycontinue
if ($mbx -ne $null -and $mbx.count -lt 2) {
Write-Host $mbx.displayname " -> " $mbx.email
$correct = Read-Host "Is this the correct person? (y/n)"
if ($correct.trim() -eq "y") {
$AuthRequestors += $mbx.email.tostring()
write-host " -------------------"
write-host "Current Requestors:"
($AuthRequestors | sort| ft)
write-host " -------------------"
}
} else {
write-host " -> Object not found"
}
}
} while ($name.trim() -ne "")
}
$isDisabled = get-user -identity $crobj.distinguishedname
if ( $isDisabled.RecipientTypeDetails -ne "RoomMailbox") {
$crobj = Convert-toUserMbx $crObj
$crobj = Convert-toResource $crObj
do {
$isDisabled = get-user -identity $crobj.distinguishedname
} while ( $isDisabled.RecipientTypeDetails -ne "RoomMailbox")
}
$COnfRoomObj = Get-MailboxCalendarSettings $ConfRoomName
if ($ConfRoomObj.ResourceDelegates.Count -gt 0) {
#Populate with delegates already assigned on conference room mailbox.
write-host "pulling delegates from live resource"
$resourceDelegates = $ConfRoomObj.ResourceDelegates | % {$_.name}
}
if ($resourceDelegates -ne $null) {
#If you ran the script dot sourced, or against an existing c.room, it will allow you to use the previous values.
write-host " -------------------"
write-host "Currently Delegates (" ($ResourceDelegates.Count)"):"
($resourceDelegates | sort| ft)
write-host " -------------------"
}
$answer = read-host "Would you like to define new delegates? (y/n)"
if ($answer.Trim() -eq "y") {
if ($resourceDelegates -ne $null) {
Write-Host "Removing Full Mailbox permissions for former Delegates"
Write-Host "Press ENTER or Y to process"
$delegates = $ResourceDelegates | % {get-mailbox $_}
$Delegates | % {remove-MailboxPermission -AccessRights FullAccess -Identity $crObj -User $_.linkedmasteraccount}
}
#Loop through building new delegates list
$ResourceDelegates = @()
do {
Write-Host "Hit ENTER to end input"
$name = Read-Host "Delegate Name or email (" ($ResourceDelegates.Count+1)")"
if ($name.trim() -ne "") {
$mbx = Get-Mailbox $name -ErrorAction silentlycontinue
if ($mbx -ne $null) {
Write-Host $mbx.displayname " -> " $mbx.primarysmtpaddress
$correct = Read-Host "Is this the correct person? (y/n)"
if ($correct.trim() -eq "y") {
$ResourceDelegates += $mbx.primarysmtpaddress.tostring()
write-host " -------------------"
write-host "Currently Delegates:"
($resourceDelegates | sort| ft)
write-host " -------------------"
}
} else {
write-host " -> mailbox not found"
}
}
} while ($name.trim() -ne "")
}
#Verify delegates that are assigned are all still valid.
if ($resourceDelegates.Count -gt 1) {
$delegates = $resourceDelegates | % {Get-Mailbox $_}
if ($resourceDelegates.Count -ne $delegates.count) {Write-Host "Can't locate all delegates in list.";break}
} elseif ($resourceDelegates.Count -eq 1) {
$delegates = $resourceDelegates | % {Get-Mailbox $_}
if ($delegates -eq $null) {Write-Host "Can't locate all delegates in list.";break}
}
#Apply default settings
Set-MailboxCalendarSettings -Identity $CRobj.distinguishedname -AddAdditionalResponse $true -AutomateProcessing AutoAccept -AddNewRequestsTentatively $true -AddOrganizerToSubject $true -AllowConflicts $false -AllowRecurringMeetings $true -BookingWindowInDays 366 -ConflictPercentageAllowed 10 -DeleteAttachments $true -DeleteComments $true -DeleteNonCalendarItems $true -DeleteSubject $false -DisableReminders $true -EnableResponseDetails $true -EnforceSchedulingHorizon $true -ForwardRequestsToDelegates $true -MaximumDurationInMinutes 720 -OrganizerInfo $true -ProcessExternalMeetingMessages $false -RemoveForwardedMeetingNotifications $true -RemoveOldMeetingMessages $true -RemovePrivateProperty $true -ScheduleOnlyDuringWorkHours $false -TentativePendingApproval $true
if ($ResourceDelegates -ne $null) {
#Determine what role Delegates will play with this c.room.
write-host "You have defined "$Resourcedelegates.count" delegates"
Write-Host "Do you want them to:"
Write-Host " 0. stop, let me change my delegates."
write-host " 1. process all meeting requests"
Write-Host " 2. only Out-of-Policy requests"
do {
$answer = Read-Host "Choice (0,1,2)"
} while ($Answer -ne "1" -and $answer -ne "2" -and $answer -ne "0")
if ($answer -eq "0") {break}
if ($answer -eq "1") {
#All Meeting Requests processed by the Delegates
Set-MailboxCalendarSettings -identity $crobj.distinguishedname -ResourceDelegates $ResourceDelegates
Set-MailboxCalendarSettings -Identity $crobj.distinguishedname –AllBookInPolicy $False –AllRequestInPolicy $False –AllRequestOutOfPolicy $False -RequestInPolicy $AuthRequestors
} else {
#Only Out-of-policy requests are processed by Delegates.
Set-MailboxCalendarSettings -identity $crobj.distinguishedname -ResourceDelegates $ResourceDelegates
Set-MailboxCalendarSettings -Identity $crobj.distinguishedname –AllBookInPolicy $False –AllRequestInPolicy $false –AllRequestOutOfPolicy $False -RequestOutOfPolicy $AuthRequestors
}
#Grant Delegates full Mailbox rights.
$delegates = $ResourceDelegates | % {get-mailbox $_}
$Delegates | % {Add-MailboxPermission -AccessRights FullAccess -Identity $crObj -User $_.linkedmasteraccount}
} else {
#No delegates, so grant BOOKINPolicy permissions to the Authorized Requestor's group.
Set-MailboxCalendarSettings -Identity $crobj.distinguishedname –BookInPolicy $AuthRequestors -resourcedelegates $null
}
if ($AuthRequestors -eq $null) {
#No authorized requestors defined, so grant all Exchange users rights to book c.room.
write-host "No Authorized Senders - Setting to AllBookInPolicy to TRUE"
Set-MailboxCalendarSettings -Identity $crobj.distinguishedname -AllBookInPolicy $true
}
$answer = Read-host "Would you like to define options (capacity, TV,VCR, etc.) on this resource? (y/n)"
if ($answer.trim() -eq "y") {
#Source for Room Capacity and Options
#http://msexchangeteam.com/archive/2009/02/26/450776.aspx
$Capacity = Read-Host "What is the room's maximum capacity?"
$isNum = isNumeric $Capacity
if ($isNum){
$cap = [int]$capacity
Set-Mailbox -Identity $crobj.distinguishedname -ResourceCapacity $Cap
}
$crobj = Get-Mailbox -identity $crobj.DistinguishedName
$Modified = $false
if (DoesItHave "TV") {
$modified = $true
$crObj.ResourceCustom.Add("TV")
}
if (DoesItHave "Whiteboard") {
$modified = $true
$crObj.ResourceCustom.Add("Whiteboard")
}
if (DoesItHave "VCR") {
$modified = $true
$crObj.ResourceCustom.Add("VCR")
}
if (DoesItHave "PC or Workstation") {
$modified = $true
$crObj.ResourceCustom.Add("PC/Workstation")
}
if (DoesItHave "LCD Projector") {
$modified = $true
$crObj.ResourceCustom.Add("LCD Projector")
}
if ($Modified) {Set-Mailbox -Instance $crobj}
}
#Display current c.room settings to screen.
get-mailboxcalendarsettings $crobj.distinguishedname | fl
#Grant Help Desk permissions to conference room.
Get-Mailbox "HelpDesk@example.com" | % {Add-MailboxPermission -AccessRights FullAccess -Identity $crObj -User $_.linkedmasteraccount}
Comments
Post new comment