Here's what I've learned about these issues.
The waiting period between setting these up and when they work is related to the directory cache on the Exchange. I've found an article here which describes this. Our solution to this is to set appropriate expectations; we wait 24hours between creating the shared mailbox and advising the users it's ready.
With regards to functionality, I've still found no guidance on what the best practice for this is. I have however discovered the following two facts:
- Creating the mailbox and user account directly in Exchange as a Shared Mailbox works far more reliably
- Creating a group with access to the mailbox, then adding users to that group, works. Using nested groups does not work reliably
Apparently the second issue has been fixed in the latest service pack, although I have not tested this yet. Also, the groups we are now creating are security enabled distribution groups. I have created a script to automate the whole process, and this is working very well. We are currently in the process of migrating our existing shared mailboxes to new mailboxes created with this script.
I've inclluded the script below for anyone who is interested. Any suggestions or improvements would be most welcome.
# ===================================================================
# Purpose: Creates a shared mailbox, a group with appropriate permissions, and adds members
# Author: Matt Goldman
# Revision: 1.0; 31/5/2011
# ===================================================================
Function ImportMembers
{
param($csvpath,$dgalias)
$Title = "CSV Import Options"
$headingquery = "Please choose from the following CSV formatting options:"
$alias = New-Object System.Management.Automation.Host.ChoiceDescription "&Alias", `
"CSV Contains an alias column."
$fullname = New-Object System.Management.Automation.Host.ChoiceDescription "&Full Name", `
"CSV contains a full name column."
$firstlast = New-Object System.Management.Automation.Host.ChoiceDescription "First and &Last Name", `
"CSV contains a first name column and a last name column"
$options = [System.Management.Automation.Host.ChoiceDescription[]] ($alias, $fullname, $firstlast)
$result = $host.ui.PromptForChoice($title, $headingquery, $options, 0)
Switch ($result)
{
0 {
# Has an alias column
$aliascolumn = Read-Host "Please enter the column heading for the alias column"
$members = Import-CSV $csvpath
foreach ($row in $members)
{
$member = $row.$aliascolumn
Add-DistributionGroupMember -Identity $dgalias -Member $member
}
}
1 {
# Has a full name column
$fullnamecolumn = Read-Host "Please enter the column heading for the Full Name column"
$members = Import-csv $csvpath
foreach ($row in $members)
{
$member = $row.$fullnamecolumn
Add-DistributionGroupMember -Identity $dgalias -Member $member
}
}
2 {
# Has a first name and a last name column
$firstnamecol = Read-Host "Please enter the column heading for the First Name column"
$lastnamecol = Read-Host "Please enter the column heading for the Last Name column"
$members = Import-csv $csvpath
foreach ($row in $members)
{
$fullname = $row.$firstnamecol + " " + $row.$lastnamecol
Add-DistributionGroupMember -Identity $dgalias -Member $fullname
}
}
}
Write-Host "The following members have been added to the group:"
Get-DistributionGroupMember $dgalias | FT -AutoSize Name
Write-Host "Thank you for using SMBuilder."
}
Write-Host "Shared Mailbox Builder v0.1`n"
# Write-Host "Script to create a shared mailbox, create a corresponding group with appropriate permissions, and populate group membership"
# Write-Host "User-input driven"
# Create the shared mailbox
$mbname = Read-Host "Please enter a (full) name for the new mailbox (e.g. Sales Team or Emplyee Enquiries)"
$mbalias = Read-Host "`nPlease enter an alias for the new mailbox (e.g. salesteam or empenq)"
$addomain = Read-Host "`nPlease enter your Active Directory domain (NOT your SMTP domain if they are different)"
$upn = $mbalias + "@" + $addomain
$mbmessage = "`nDo you want to specify an OU for the mailbox object? (Default will be $addomain/users)"
$yes = New-Object System.Management.Automation.Host.ChoiceDescription "&Yes", `
"Specifies an OU."
$no = New-Object System.Management.Automation.Host.ChoiceDescription "&No", `
"Accepts default OU."
$options = [System.Management.Automation.Host.ChoiceDescription[]]($yes, $no)
$result = $host.ui.PromptForChoice($title, $mbmessage, $options, 1)
switch ($result)
{
0 {
$ou = Read-Host "Please specify the Organizational Unit - $addomain/"
$mbou = $addomain + "/" + $ou
New-Mailbox -Name $mbname -Alias $mbalias -UserPrincipalName $upn -OrganizationalUnit $mbou -Shared | Out-Null
}
1 {
New-Mailbox -Name $mbname -Alias $mbalias -UserPrincipalName $upn -Shared | Out-Null
}
}
Write-Host "The following mailbox has been created:"
Get-Mailbox $mbalias | FT -AutoSize Name,OrganizationalUnit
# Create the security-enabled distribution group
$dgname = Read-Host "Please enter a (full) name for the new Distribution Group (e.g. Sales Team Full Access)"
$dgalias = Read-Host "`nPlease enter an alias for the new Distribution Group (e.g. STMailBoxFA)"
$dgmessage = "`nDo you want to specify an OU for the Distribution Group? (Default will be $addomain/users)"
$yes = New-Object System.Management.Automation.Host.ChoiceDescription "&Yes", `
"Specifies an OU."
$no = New-Object System.Management.Automation.Host.ChoiceDescription "&No", `
"Accepts default OU."
$options = [System.Management.Automation.Host.ChoiceDescription[]]($yes, $no)
$result = $host.ui.PromptForChoice($title, $dgmessage, $options, 1)
switch ($result)
{
0 {
$ou = Read-Host "Please specify the Organizational Unit - $addomain/"
$dgou = $addomain + "/" + $ou
new-DistributionGroup -Name $dgname -Type 'Security' -SamAccountName $dgname -Alias $dgalias -OrganizationalUnit $dgou | Out-Null
}
1 {
new-DistributionGroup -Name $dgname -Type 'Security' -SamAccountName $dgname -Alias $dgalias | Out-Null
}
}
Set-DistributionGroup -identity $dgalias -HiddenFromAddressListsEnabled $true
Write-Host "The following Distribution Group has been created:"
Get-DistributionGroup $dgalias | FT -AutoSize Name,OrganizationalUnit
# Apply full access and send as permissions to the group on the mailbox
Add-MailboxPermission -Identity $mbalias -AccessRights FullAccess -User $dgalias | Out-Null
Write-Host "`nFull-Access rights applied..."
Get-Mailbox $mbalias | Add-ADPermission -ExtendedRights Send-As -User $dgalias | Out-Null
Write-Host "Send-As permission applied..."
# Populate the group
$listmessage = "`nDo you have a .csv file listing the users/groups you wish to add to this group?"
$yes = New-Object System.Management.Automation.Host.ChoiceDescription "&Yes", `
"Allows you to import a list of users in .csv format"
$no = New-Object System.Management.Automation.Host.ChoiceDescription "&No", `
"Allows you to manually type in a comma seperated list of users, or skip and add them manually"
$options = [System.Management.Automation.Host.ChoiceDescription[]] ($yes, $no)
$result = $host.ui.PromptForChoice($title, $listmessage, $options, 1)
Switch ($result)
{
0 {
"You wish to import from CSV..."
$csvpath = Read-Host "Please enter the full path to your CSV file"
ImportMembers $csvpath $dgalias
}
1 {
"You do not wish to import from CSV. Thank you for using SMBuilder."
}
}