RSS Subscription 168 Posts and 2,769 Comments

Archive for May, 2009

Exchange 2007 Shared Mailbox Permission/Delegates Issues

This post is a bit different than the other shared mailbox posts out there.   A couple articles in regards to shared mailbox permissions  include:

http://knicksmith.blogspot.com/2007/03/exchange-2007-and-shared-mailboxes.html

http://blogs.technet.com/msukucc/archive/2009/02/23/shared-mailboxes.aspx

As you can see, these articles including adding SendAs and/or FullAccess.  But what if you don’t want to provide FullAccess and/or SendAs and just want some basic permissions?  This is where we ran into depending on how you create the shared mailbox.  We were giving Editor+ permssions on a calendar for another user.  This would allow us to create/edit/etc.  You can see specifically what it allows by looking at the screenshot below.

So let’s say we have a shared mailbox called Aaron Tiensivu.  Yes, I’m sure many of you recognize his name from his blog here.  He’s a coworker of mine so I’m using him as an example.   I am going to open his calendar from my Outlook client and try to modify his calendar.  In order to do this, we need the following permissions:

This allows us me to open the shared mailbox’s calendar by going to File > Open > Other User’s Folder… and choosing the following options:

Again, in the case of my article, just think of Aaron Tiensivu as a shared mailbox here. :)

So I open the mailbox Aaron Tiensivu and verify that his calendar opens.

The Problem: The problem though, is that when you try to create an calendar item, you hear an error beep but no error shows up and you aren’t able to create/modify/etc. to the shared mailbox’s calendar.  Turning up Outlook Logging doesn’t reveal any pertinent information.  I did find two workarounds though which I don’t really care for and a third workaround which may or may not be considered a workaround to some.

Workaround 1:  The first workaround was by giving FullAccess Permissions on Aaron Tiensivu’s Shared Mailbox to Elan Shudnow either via EMC or EMS.  You can find out how to do that here.

Workaround 2:  The second workaround is to convert the shared mailbox to a user mailbox and start using the shared mailbox concept utilizing a user mailbox (which enables the AD account) using the following command:

Set-Mailbox -Identity “Aaron Tiensivu” -Type User

Now the interesting thing is that this only happens when you create a shared mailbox, not convert it.  What I mean by this, is this when you create a shared mailbox using the following PowerShell command, the issue occurs:

new-Mailbox -alias ATiensivu -name “Aaron Tiensivu” -database “Mailbox Database” -org Users -shared -UserPrincipalName aarontiensivu@example.com

What I noticed is that when you create a brand new user mailbox (not shared) using either the Exchange Management Console or the Exchange Management Shell, all the above delegation that previously failed with a brand new shared mailbox works as intended.  And even when we convert the user mailbox to a shared mailbox, delegate access works as intended as long as it was first created as a user mailbox instead of a shared mailbox.  It’s almost as if there’s some issue when you create a shared mailbox but it’s fine when creating a regular user mailbox and converting it to a shared mailbox.

A fellow MVP, Glen Scales, had recommended I try using a MAPI Editor and/or pfdavadmin to check the local freebusy folder in the NON_IPM_Subtree to see whether the correct permissions are being applied.  Glen did point out that the Outlook client should be taking care of this permission.  Unfortunately because we see that Shared Mailboxes work after converting them, our team moved onto other things for the remainder of the day due to a tight schedule.  If I do find time, I’ll try creating a shared mailbox from scratch and check this out and update this post.

Now of course, you may not encounter this issue as I have.  As IT people, we all know that sometimes things work in one environment and not the other.  So if you do happen to have this issue and find yourself reading this blog entry, please submit a comment with your findings/information.

Share

Another Exchange Scriplet (Moving Mailboxes)

This one I created for the following reasons:
1. Mailbox Database was filling up
2. Wanted to take the filled up database and split them across two different databases.

The script will sort all the mailboxes by size and take 40% of the largest mailboxes and move them to a specified database and take the remaining 60% and move them to the other database.

If you don’t want to specify the exact database name and just want PowerShell to use part of the name you specify to find a matching database, you can change the part where it states {$_.Name -eq $sourceDB} to have -like instead of -eq. Do the same for the following two pieces of code: {$_.Name -eq $targetDBLarge} and {$_.Name -eq $targetDBSmall}. -eq needs the exact match for the database name and -like basically takes the database name and puts wild cards around it so it’s more like *databaseyouspecify* and then finds a matching database that is like the name you specified.

Important: I added -whatif switches to the move-mailbox commands below to be extra safe. To actually move the mailboxes, you’ll need to remove the -whatif.  And as always, MAKE SURE YOU TEST THIS IN LAB BEFORE RUNNING IT IN PRODUCTION AND HAVE A GOOD BACKUP UP AD/EXCHANGE/ETC AS WELL!

?View Code POWERSHELL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$sourceDB = "Specify your Source Database Here"
$targetDBLarge = "Specify your larger database in which 40% of the largest mailboxes will be moved to"
$targetDBSmall = "Specify your smaller database in which the remaining 60% of the smaller mailboxes will be moved to"
 
############################################
####### Don't modify below this line #######
############################################
 
$a = Get-MailboxStatistics -Database $(Get-Mailboxdatabase | Where-Object {$_.Name -eq $sourceDB}) | where {$_.ObjectClass -NotMatch '(SystemAttendantMailbox|ExOleDbSystemMailbox)'} | Sort-Object Totalitemsize
 
$rounded = [math]::round($a.count * .4)
$first = $rounded
$last = $a.count - $first
 
$a | Select-object -First $first | Move-Mailbox -TargetDatabase $(Get-Mailboxdatabase | Where-Object {$_.Name -eq $targetDBLarge}) -whatif
$a | Select-object -Last $last | Move-Mailbox -TargetDatabase $(Get-Mailboxdatabase | Where-Object {$_.Name -eq $targetDBSmall}) -whatif
Share

A few Exchange PowerShell scriptlets

Figured I would share a few scriptlets I’ve written recently.  Hopefully some of you may find them useful at some point at least.

Scriptlet 1

Find out all users who live on a specific mailbox without having to type the entire mailbox database name:

?View Code POWERSHELL
1
get-mailbox -database $(get-mailboxdatabase | where-object {$_.name -like "*Database1*"}) | Format-Table Name,Database -wrap -autosize

Scriptlet 2

Get statistics on a specific user without knowing the entire name or if you’d want to find out statistics on all users who have the first name John or last name Doe:

?View Code POWERSHELL
1
Get-MailboxStatistics -server serverhere | Where-Object {$_.DisplayName -like "*MailboxUserName*"} | Format-Table DisplayName,ItemCount,TotalItemSize

Scriptlet 3

When you are in an environment with multiple Mailbox Servers, it may be annoying to find what disconnected mailbox lives on which server since the Exchange Management Console will only connect to one server at a time and when connected, it’ll only show disconnected mailboxes for that specific server.  This scriptlet will cycle through all mailbox servers and report back all disconnected mailbox servers and which disconnected mailbox lives on which mailbox server.

?View Code POWERSHELL
1
2
3
4
$mbx = Get-ExchangeServer | Where-Object {$_.IsMailboxserver -eq $true}
foreach ($server in $mbx) {
	Get-Mailboxstatistics -Server $Server | Where-Object { $_.DisconnectDate -ne $null } | Format-Table DisplayName,ItemCount,OriginatingServer -wrap
}

Scriptlet 4

Based on a CSV file, export users contacts that were created after a certain start date to a PST file.  A copy of how the CSV should be formatted is located here.  While the CSV contains multiple columns, the script only utilizes the Account Name column by default.  If you want to modify what columns it uses, you can change the line below that starts with $AdName =.  After the script pulls the name in the Account Name field, it finds the mailbox using the Get-Mailbox command with the name that was specified in the Account Name field.

?View Code POWERSHELL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
$file = "pstusers.csv"
$PSTLocation = "C:\PSTs"
$StartDate = "03/20/2009"
 
############################################
####### Don't modify below this line #######
############################################
$erroractionpreference = "SilentlyContinue"
if (!(Test-Path -path $PSTLocation)) {
	Write-Host "Creating the Directory $PSTLocation" -ForegroundColor Yellow
	New-Item -ItemType "Directory" -Path $PSTlocation
}
if (Test-Path $file) {
	$excel = Import-CSV $file
	foreach ($line in $excel) {
		$AdName = $line."Account Name"
		$Mailbox = Get-Mailbox $AdName
		if ($Mailbox) {
			Write-Host "$AdName is being exported to $PSTLocation"
			$Mailbox | Export-Mailbox -PSTFolderPath $PSTLocation -StartDate $StartDate -ExcludeFolders "\Inbox","\Deleted Items","\Drafts","\Junk E-mail","\Outbox","\Sent Items","\Journal","\Calendar","\Notes","\Tasks"
		}
		else { Write-Warning "$ADName Mailbox Does not Exist" }
	}
}
else {
	Write-Warning "The file $file does not exist"
}

Scriptlet 5

If you are familiar with Quest Notes Migrator for Exchange, you may have had the chance to migrate data to a PST file.  What you will see, is that the PST gets migrated with the Display Name of the user.  For example, we if migrated the Notes mailbox of Elan Shudnow to a PST, the PST file name would be Elan Shudnow.PST. A lot of people won’t want to migrate the PST directly from Quest NME to a user’s home share because that user’s home share may be located in a remote site and opening a PST file across a network isn’t really a good idea; especially over long distances.

So I wrote a script so you can migrate all the PST files locally and then it’ll check the Display Name portion of the PST file and use that display name to find a matching user in AD and then find their home directory and then copy that PST file to that home share.

?View Code POWERSHELL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# Set Location to where the PST files are started
Set-Location "E:\"
 
$pstData = Get-ChildItem -recurse | Where-Object {$_.Name -like "*.pst"}
 
function Get-HomeDirectory ($displayName) {
	$ads = New-Object System.DirectoryServices.DirectorySearcher([ADSI]'')
	$ads.filter = "(&(objectClass=Person)(displayName=$displayName))"
	$s = $ads.FindOne()
	return $s.GetDirectoryEntry().homeDirectory
}
 
foreach ($pstUser in $pstData) {
	$PSTName = $pstUser.Name
	$PSTDisplayName = $pstUser.Name.split(".")[0]
	$PSTDisplayName = $PSTDisplayName.split("-")[0]
	$Path = $PSTUser.DirectoryName + "\" + $PSTUser.Name
	$Directory = Get-HomeDirectory $PSTDisplayName
	Copy-Item $Path $Directory
}
Share