My Big Fat Conference Room Conversion Script for Exchange 2007

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:

  1. 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).
  2. If it finds the mailbox is an "user" mailbox, it will convert it to a conference room resource.
  3. You will be given the option to specify who (mailbox, group) can book it.
  4. You will be given the option to specify who can delegate (administer) the room.
  5. 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.

 #Script to configure a resource mailbox
# - 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

The content of this field is kept private and will not be shown publicly.
  • Allowed HTML tags: <a> <blockquote> <center> <hr> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd> <img>
  • Lines and paragraphs break automatically.
  • Web page addresses and e-mail addresses turn into links automatically.
  • You can enable syntax highlighting of source code with the following tags: <code>, <blockcode>, <drupal6>, <html>, <java>, <javascript>, <php>, <posh>.

More information about formatting options