Configure Delegation
“You can use the EAC or the Shell to assign permissions to users or groups (called delegates) that allow them to open or send messages from other mailboxes. Permissions can be assigned to user mailboxes, linked mailboxes, resource mailboxes, and shared mailboxes. You can also assign permissions to distribution groups, dynamic distribution groups, and mail-enabled security groups to allow delegates to send messages on behalf of the group. You can assign delegates the following permissions to access mailboxes or send messages on behalf of mailboxes or groups.”
SOURCE
# Code for menu 20 { # Configure Delegation configure-delegation } # Configure Delegation function Configure-delegation { $userA = read-host "What user needs delegation rights? [enter the user's alias]" $userB = read-host "What user mailbox will have access granted to it? [enter the user's alias]" $accessrights = read-host "What access rights will be granted? [use commas if more than one]" $folder = read-host "All folders or specific folder [a or s]" if ($folder -eq "a") { $folder2 = "*" $combo = $usera+":\"+$folder2 add-MailboxFolderPermission -Identity $userB -User $UserA -AccessRights $accessrights } if ($folder -eq "s") { $folder2 = read-host "Which folder will the rights apply to" $combo = $usera+":\"+$folder2 # Add the folder tothe user's mailbox being modified" $name = $userB+":\"+$folder2 add-MailboxFolderPermission -Identity $name -User $UserA -AccessRights $accessrights } } # End the Configure Delegation function
Sample run through of the Delegation part of the script:
Calendar Access
All Folder Access
As you can see from the script, you need to specify the folder, the user, who is assigned the right, etc. Make sure you have the right correctly typed, or the command will fail.
Room Lists
Room lists are like a little gem hidden in Exchange 2013. I am hoping to shed more light in this feature with my blog article earlier this month, to this advanced functionality included in the lab setup script. More information can be found at this TechNet page.
# Menu Choices 5 { # Create Rooms $choice = read-host "Do you want to [1] create rooms or [2] rooms and roomlists?[1 or 2]" if($choice -eq 1) { create-roommailboxes } else { # Added an move advanced option (1.3) New-RoomList } } # Create new Room Lists Function New-RoomList { write-host " " Write-host "This function will help you create rooms and room lists for your test environment, assuming" -ForegroundColor green write-host "the OU's and rooms are not created so far." -ForegroundColor green write-host " " $answer1 = read-host "Create room lists from scratch? [y or n]" If ($answer1 -eq "y") { $csvmanual = read-host "Do you want to [1] use a CSV file or [2] enter the rooms manually ? [1 or 2]" If ($csvmanual -eq 1) { # import rooms and room lists from CSV file # CSV format: # roomlist,room,ou $csvfile = read-host "Specify a CSV file to read from" $csv = Import-csv $csvfile write-host "No column validation here - use this at your own risk." # pausing Write-Host "Press any key to continue ..." $x = $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown") Foreach ($line in $csv) { # Check for the existence of the Room list, create if it does not exist if ((get-distributiongroup $line.roomlist) -eq $null) { New-DistributionGroup -Name $line.roomlist -OrganizationalUnit $line.ou -RoomList } $track = 0 $database = (get-mailboxdatabase).name write-host "For the new Room Mailboxe:" $mbx = $line.room $password = read-host "Enter password for the $mbx mailbox" -AsSecureString $dbcount = (get-mailboxdatabase).count $domain = read-host "Enter a domain to be used for the rooms SMTP address" # $source2 = import-csv c:\temp\roommailboxes.csv $name = $line.room $name = $name -replace '\s','' $upn = $name+"@"+$domain new-mailbox -userprincipalname $upn -alias $name -database $database[$track] -displayname $line.room -name $name -password $password -room $track++ if ($track -ge $dbcount) { $track = 0 } } # Add members according to the CSV file provided Add-DistributionGroupMember -Identity $line.roomlist -Member $line.room } If ($csvmanual -eq 2) { $norooms = read-host "How many rooms do you want to create?" $noroomlists = read-host "How many room lists do you want to create?" $counter = 0 while ($counter -lt $norooms) { $roomname = read-host "Enter a name for the room" $capacity = read-host "Enter a room capacity" $ou = read-host "Enter an OU to search for [i.e. rooms]" Get-OrganizationalUnit -SearchText $ou |ft *canonicalname* $ou = read-host "Copy one of the OUs above to use for placing the room mailboxes or enter a new one" New-mailbox -Name $roomname -OrganizationalUnit $ou -room -ResourceCapacity $capacity $counter++ } $counter = 0 while ($counter -lt $noroomlists) { $roomlist = read-host "Enter a name for the room list" $ou2 = read-host "Enter an OU for the room list" New-DistributionGroup -Name $roomlist -OrganizationalUnit $ou2 -RoomList $NoRoomMembers = read-host "How many rooms do you want to add to the $roomlist roomlist?" $counter2 = 0 while ($counter -lt $NoRoomMembers) { $RoomListMember = read-host "What room do you want to add to the $roomlist room list?" Add-DistributionGroupMember -Identity $roomlist -Member $RoomListMember $counter2++ } $counter++ } } } If ($answer1 -eq "n") { write-host " " write-host "Exiting room list function...." -foregroundcolor red write-host " " start-sleep 5 cls } } # End of the New-RoomList function
Sample run through of working through Room List options:
Enter Rooms and Room Lists Manually
Using a CSV File for the Process
The Room Lists script section provides options for creating lists via CSV files or entering the details manually.
Configure Journaling
“Journaling can help your organization respond to legal, regulatory, and organizational compliance requirements by recording inbound and outbound email communications. When planning for messaging retention and compliance, it’s important to understand journaling, how it fits in your organization’s compliance policies, and how Microsoft Exchange Server 2013 helps you secure journaled messages.”
SOURCE
# Menu Code 19 { # Configure Journaling configure-journaling } # Configure Journaling for Exchange function configure-journaling { $journaloption = read-host "Do you want to configure [1] Per User Journaling or [2] Journaling for all messages? [1 or 2]" # Scope options - Internal | External | Global $mailbox = read-host "Do you need to create a journal mailbox? [y or n]" $database = read-host "Do you need to create a journal database? [y or n]" $name = read-host "Provide a name for the journal rule" if ($database -eq "y") { write-host "The next part of the script will ask for how many databases to create. Choose 1." -foregroundcolor Green create-database } else { $dbname = read-host "What database would you like to use for journaling?" } if ($mailbox -eq "y") { $journalmailbox = read-host "What will you call the journaling mailbox?" $password = read-host "Enter a password" -AsSecureString $prefix = read-host "Enter a prefix for the User Principal Name [i.e. @domain.local]" $mailbox = $journalmailbox+$prefix write-host "The $journalmailbox will be created in the Users OU" new-mailbox -userprincipalname $mailbox -alias $journalmailbox -database $tbd -displayname $journalmailbox -name $journalmailbox -password $password } else { $journalmailbox = read-host "What is the name of the journaling mailbox?" } if ($journaloption -eq "1") { $nousers = read-host "How many users do you want to configure journaling for?" $counter = 0 $list = @() while ($counter -lt $nousers) { $user = read-host "What user do you want to configure for journaling? [user alias]" $email = (get-mailbox $user).primarysmtpaddress $smtp = $email.local+"@"+$email.domain $list += ,($smtp) $counter++ } # Configure journaling for the user New-JournalRule -Name $name -JournalEmailAddress $smtp -Scope Global -recipient $smtp -Enabled $true } else { # Configure journaling for the organization $email = (get-mailbox $journalmailbox).primarysmtpaddress $smtp = $email.local+"@"+$email.domain New-JournalRule -Name $name -JournalEmailAddress $smtp -Scope Global -Enabled $true } } # End the Configure Journaling function
Global
In the below sample run-through, I am attempting to simulate Journaling for all mailboxes, while creating a database (calls another function in the script), as well as creating a Journal mailbox to go with it.
Per User
The next sample is a run-through of adding journaling on a per user basis, without creating a database or journal mailbox.
Retention Policies
“In Microsoft Exchange Server 2013 and Exchange Online, Messaging records management (MRM) helps organizations to manage email lifecycle and reduce legal risks associated with e-mail and other communications. MRM makes it easier to keep messages needed to comply with company policy, government regulations, or legal needs, and to remove content that has no legal or business value. “
SOURCE
# Menu Code 10 {# Create retention Policies create-retentionpolices } # Create Retention Policies function create-retentionpolices { $createorapply = read-host "[1] Create or [2] Apply retention policies [1 or 2]" if ($createorapply -eq 1) { $polno = read-host "How many Retention Policies do you want to create" $polcounter = 0 while ($polcounter -lt $polno) { $currentpol = $polcounter +1 $polname = read-host "Specify a name for Rentention Policy number $currentpol" $tagno = read-host "How many Retention Tags do you want to create" $counter = 0 $alltags = @() $allpolicies = @() while ($counter -lt $tagno) { $current = $counter + 1 $name = read-host "Specify a name for Retention Tag number $current" $allpolicies += ,($name) $time = read-host "Specify a time frame to apply the tag (i.e. 60, 90, 120)" $RetentionAction = read-host "Specify a retention action (DeleteAndAllowRecovery, PermanentlyDelete, MoveToArchive)" if ($retentionaction -eq "MoveToArchive") { $type = "all" } else { $type = read-host "Specify which folders will be affect (All, Inbox, etc. )" } $comment = read-host "Specify a comment for the Retention Tag (optional)" $alltags += ,($name) if ($retentionaction -eq "permanentlyDelete") { $archive = $false } else { $archive = $true } New-RetentionPolicyTag -Name $name -Type $type -RetentionAction $retentionaction -RetentionEnabled:$archive -AgeLimitForRetention $time -Comment $comment $counter++ } new-retentionpolicy -name $polname -RetentionPolicyTagLinks $alltags $polcounter++ } $action = read-host "Do you want to apply these policies to your users now? [y or n]" } # After creating polcies - create them? if ($action -eq "y") {$createorapply = 2} if ($createorapply -eq 2) { $allpolicies = (get-retentionpolicy).name foreach ($line in $allpolicies) { $action2 = read-host "For the retention policy $line, do you want to apply this policy to any users? [y or n]" if ($action2 -eq "y") { $applyto = read-host "Do you want to apply the policies to [a] all users, [r] random users or [c] use a csv file? [a, r or c]" if ($applyto -eq "a") { get-mailbox | set-mailbox -retentionpolicy $line } if ($applyto -eq "r") { $mbxcount = (get-mailbox | where {$_.RecipientTypeDetails -ne "DiscoveryMailbox"}).count $range = get-random -minimum 0 -maximum $mbxcount $mailbox = (get-mailbox | where {$_.RecipientTypeDetails -ne "DiscoveryMailbox"}).alias $counter = 0 $userlist = @() while ($counter -lt $range) { $alias = $mailbox[$counter] get-mailbox $alias | set-mailbox -retentionpolicy $line $counter++ } } if ($applyto -eq "c") { # CSV format is just the mailbox alias, with a header of 'alias' $csv = read-host "Specify a CSV file to read from" foreach ($line in $csv) { get-mailbox $line.alias | set-mailbox -retentionpolicy $line } } } } } } # End of the create-retentionpolices function.
Applying Retention Policies
In the below example, the script will ask if you want to apply the listed retention policy to users in the environment.
Dynamic Distribution Groups
For distribution groups, the script initially created very generic groups with the “DistributionGroup” name and places a random 1 to 10 users into each distribution group. For this version, there will be a small menu to drive your choices for group creations and validations.
# Code for Menu 22 { #Configure dynamic DLs create-dynamicdistributiongroups } # Create Distribution Groups function create-dynamicdistributiongroups { $random = read-host "Create random [1] Dynamic Distribution Groups or [2] create with a CSV file? [1 or 2]" if ($random -eq 1) { $dlcount = read-host "How many distribution groups would you like to create" $alias1 = "DistributionGroup" $displayname1 = "Distribution Group " $dlcounter = 1 while ($dlcounter -lt $dlcount) { $displayname = $displayname1+$dlcounter $alias = $alias1+$dlcounter $orgunit = read-host "Enter the OU for the Dynamic Distribution Group" new-dynamicdistributiongroup -name $displayname -displayname $displayname -alias $alias -RecipientFilter {RecipientType -eq 'UserMailbox'} -OrganizationalUnit $orgunit $dlcounter++ } } if ($random -eq 2) { $csvfile = read-host "Specify CSV file for creating Dynamic Distribution Groups" $csv = import-csv $csvfile foreach ($line in $csv) { new-dynamicdistributiongroup -name $line.displayname -displayname $line.displayname -alias $line.alias -RecipientFilter {RecipientType -eq 'UserMailbox'} -OrganizationalUnit $line.orgunit } } write-host "Dynamic Distribution Groups step complete." -foregroundcolor green write-host " " start-sleep 5 CLS } # End of the create-dynamicdistributiongroups function
Sample Dynamic List Creation
Notice in the below example, a CSV file is specified. The CSV file contained pre-populated information to make the process go easier.
Archive Quotas
# Code for menu 21 { # Configure Archive Quotas Configure-ArchiveQuotas } # Enable Archives for all or some users function enable-archives { $selection = read-host "Do you want to enable archives for all mailboxes or random mailboxes [a or r]" $location = read-host "Would you like to create a new mailbox database for the archive mailboxes [y or n]" if ($location -eq "n") { $database = read-host "Which database will the archive mailboxes be placed in" } if ($location -eq "y") { $srv = ($server[0]).name write-host "The new archive database will bew placed on $srv." $directory1 = read-host "Please enter a valid directory to place the database files" $directory2 = read-host "Please enter a valid directory to place the log files" $archivename = "ArchiveDatabase" $edb = $directory1+"\"+$archivename+".edb" $log = $directory2+"\"+$archivename $server = get-mailboxserver new-mailboxdatabase -name $archivename -edbfilepath $edb -logfolderpath $log -server $srv -erroraction silentlycontinue } # Enable the mailboxes to have archive mailboxes if ($selection -eq "a") { $mailboxes = (get-mailbox | where {$_.RecipientTypeDetails -ne "DiscoveryMailbox"}).alias foreach ($line in $mailboxes) { enable-mailbox $line -Archive -ArchiveDatabase $database -erroraction silentlycontinue } $name = (get-mailbox $alias).displayname write-host "An archive mailbox for $name has been created." -foregroundcolor green } else { $mbxcount = (get-mailbox | where {$_.RecipientTypeDetails -ne "DiscoveryMailbox"}).count $range = get-random -minimum 0 -maximum $mbxcount $counter = 0 $mailbox = (get-mailbox | where {$_.RecipientTypeDetails -ne "DiscoveryMailbox"}).alias while ($counter -lt $range) { $alias = $mailbox[$counter] enable-mailbox $alias -Archive -ArchiveDatabase $database -erroraction silentlycontinue $counter++ } $name = (get-mailbox $alias).displayname write-host "All archive mailboxes have been created." -foregroundcolor green } } # End function for archive mailboxes
Using a CSV File
This example uses a CSV file to apply quotas to the Archive Mailboxes for users.
Random Users
This option allows a policy to applied randomly, which is usually only done for lab environments.
All Users
In the last example, the archive quota policies can be applied to all users as seen below:
Script Download
Now that the script has reach the more advance level, I am posting it to the web at a TechNet Wiki download. Once the script has been finalized or at least has 80% of the features I want, it will be placed in the GitHub universe to allow people to modify it.
Here is the Lab-Setup-1.3 script for download now. Remember to rename it as a .ps1 file.
Next Steps
In the next article or two I will finish up the Advanced parts of the script. Following that and possibly my last post in the series I will cover using DSC and xExchange with a lab setup as well as production uses. Look for those articles in the coming weeks.
Previous Articles in this Series
Part 1
Part 2
Part 3