Importing PFDAVAdmin or ExFolders Exports Without PFDAVAdmin or ExFolders
It’s almost May and I haven’t posted anything yet this year, so it’s definitely time to post a new script.
I recently worked with a customer that needed to export the public folder permissions from one Exchange organization and import them into another. The trick was that on the import side, some of the accounts were only mail-enabled – not mailbox-enabled. This creates a problem for ExFolders, because the API it uses does not consider mail-enabled accounts to be valid security principals. However, if you use the Add-PublicFolderClientPermission cmdlet to set the permissions, it has no problem with such an account.
I looked at changing ExFolders to better support this, but the changes would be complex and I just didn’t have that kind of time. Instead, I decided to write a script to import the permissions using the cmdlet. There are a few things to be aware of about the script.
First, the script will be much slower than using PFDAVAdmin or ExFolders to run the import. This is because the cmdlets only let you modify one user at a time, and unless you want to do a lot of complicated calculations, you need to remove the existing permissions for the user before adding the new ones. This means we end up running two cmdlets for every user permission. If you are importing permissions for 5 users on a folder, it will take 10 commands to assign those permissions.
Second, the script currently only works with exports that are in legacyExchangeDN format. If you used NT Account format (domain\user), this script can’t handle them. This means the legacyExchangeDNs from the old environment have to be resolvable in the new one. That is usually the case, since they are brought over as X500 addresses in most migrations.
And finally, this script works only with public folder permissions exports from PFDAVAdmin or ExFolders. If you exported replicas or properties or something, this script won’t help you.
Anyway, here is the script. Enjoy!
# Import-PFPermissions.ps1
#
# The purpose of this script is to import permissions from an export
# file generated using PFDAVAdmin or ExFolders.
#
# Syntax example:
#
# .\Import-PFPermissions C:\someimportfile.txt MYPFSERVER
param([string]$importFile, [string]$server)
function ConvertRightsString([string]$pfdavRightsString)
{
$pfdavRights = $pfdavRightsString.Split(@(' '))
$powershellRights = ""
foreach ($right in $pfdavRights)
{
if ($right -eq "All")
{
$powershellRights += "Owner,"
}
elseif ($right -eq "Owner")
{
$powershellRights += "CreateItems,ReadItems,CreateSubfolders,FolderOwner,FolderVisible,EditOwnedItems,EditAllItems,DeleteOwnedItems,DeleteAllItems,"
}
elseif ($right -eq "Contact")
{
$powershellRights += "FolderContact,"
}
elseif ($right -eq "Create")
{
$powershellRights += "CreateItems,"
}
elseif ($right -eq "CreateSubfolder")
{
$powershellRights += "CreateSubfolders,"
}
elseif ($right -eq "Delete")
{
$powershellRights += "DeleteAllItems,"
}
elseif ($right -eq "DeleteOwn")
{
$powershellRights += "DeleteOwnedItems,"
}
elseif ($right -eq "Write")
{
$powershellRights += "EditAllItems,"
}
elseif ($right -eq "WriteOwn")
{
$powershellRights += "EditOwnedItems,"
}
elseif ($right -eq "o")
{
$powershellRights += "FolderOwner,"
}
elseif ($right -eq "Visible")
{
$powershellRights += "FolderVisible,"
}
elseif ($right -eq "Read")
{
$powershellRights += "ReadItems,"
}
else
{
$powershellRights += ($right + ",")
}
}
$powershellRights = $powershellRights.TrimEnd(@(','))
return $powershellRights
}
function RemoveFolderVisibleWithTrap([string]$folderPath, [string]$server, [string]$userString)
{
trap [Exception]
{
continue
}
$returnedValue = Remove-PublicFolderClientPermission -Identity $folderPath -Server $server -User $userString -AccessRights FolderVisible
}
$fileReader = new-object System.IO.StreamReader($importFile)
while ($null -ne ($buffer = $fileReader.ReadLine()))
{
if ($buffer.StartsWith("SETACL`t"))
{
$columns = $buffer.Split(@("`t"))
# Resolve the folder path, which should always be the second column.
$folderPath = $columns[1]
if ($folderPath.StartsWith("Public Folders\"))
{
$folderPath = $folderPath.Substring(14)
}
elseif ($folderPath.StartsWith("System Folders\"))
{
$folderPath = ("\NON_IPM_SUBTREE" + $folderPath.Substring(14))
}
("Updating folder: " + $folderPath)
for ($x = 2; $x -lt $columns.Length; $x+=2)
{
$userString = $columns[$x]
if ($userString.StartsWith("/o="))
{
$recipient = Get-Recipient $userString
if ($recipient -ne $null)
{
$userString = $recipient.Identity
}
else
{
(" Could not resolve: " + $userString)
continue
}
}
elseif ($userString -ne "Default" -and $userString -ne "Anonymous")
{
(" Skipping unrecognized user format: " + $userString)
continue
}
(" Processing user: " + $userString)
(" Checking for existing permissions...")
$permsForUser = Get-PublicFolderClientPermission -Identity $folderPath -Server $server -User $userString
if ($permsForUser -ne $null)
{
(" Removing existing permissions...")
$permsForUser | Remove-PublicFolderClientPermission -Identity $folderPath -Server $server -Confirm:$false
}
(" Adding new permissions...")
$rightsString = ConvertRightsString $columns[$x+1]
(" AccessRights: " + $rightsString)
$rightsArray = $rightsString.Split(@(','))
if ($permissionString -eq "None")
{
# This requires special handling. In the cmdlet, there is no way to grant a user no permissions,
# denying the ability to even see the folder, because the None role includes the FolderVisible
# right. When a user has None without folder visible, it still shows up as None, but IsRole is
# false. We need to check for that situation here to make sure None is really None. In the
# export, None really means no rights at all.
#
# So, what we do here, is first we set rights of None. Then, we try to remove FolderVisible,
# and ignore any errors that happen. If it succeeds, we don't have FolderVisible anymore, and
# if it fails, we didn't have FolderVisible in the first place, so it doesn't matter.
$returnedValue = Add-PublicFolderClientPermission -Identity $folderPath -Server $server -User $userString -AccessRights $rightsArray
RemoveFolderVisibleWithTrap $folderPath $server $userString
}
else
{
$returnedValue = Add-PublicFolderClientPermission -Identity $folderPath -Server $server -User $userString -AccessRights $rightsArray
}
}
}
}
Comments
Anonymous
January 01, 2003
Hi Aresh, Unfortunately, no, I don't have a script for that. You can export the mailbox folder permissions from a 2003 org using PFDAVAdmin, and import them into a 2010 org using ExFolders. The problem is that the mailbox folder path format changed between these two tools. PFDAVAdmin exports using just the alias. ExFolders expects an smtp address. So you can't use the PFAVAdmin export with ExFolders. It would be possible to write a script that takes the PFDAVAdmin output and imports it using the Set-MailboxFolderPermission cmdlet, but I don't have one. Maybe I'll get around to writing it one day.Anonymous
January 01, 2003
Hi Thorsten, Yes, if you can somehow replace all the aliases with SMTP addresses, then the import should work.Anonymous
January 01, 2003
Yes, you should be able to export with PFDAVAdmin from one org and import that file with ExFolders in another org. This is one of the scenarios I had in mind when I wrote ExFolders. Note that you have two export formats to choose from. The users can be specified in legacyExchangeDN format or in DOMAINuser format. In most inter-org migration scenarios, the legacyExchangeDN of the users is preserved as an X500 proxy address, so you'll want to use the legacyExchangeDN format. But if that's not the case, you may need to use DOMAINuser, and then do a find/replace on the domain name to reflect the domain of the new org.Anonymous
January 01, 2003
Hi Bill, I have exchange 2003 org and exchange 2010 org. I will export the public folders to pst and import to exchange 2010. Is it possible to export exch 2003 public folder permissions using pfdavadmin and import to exch 2010 public folders using exfolders? I understand another way would be to use interorg connector, but wondering would export/import perms work without having to setup interorg connector? thanksAnonymous
April 29, 2011
Do you have any script that can export the Mailbox Folder Permission? I am planning to take the permission from one org(exch 2003) to another org (exch 2010) without any trust. All your help would be highly appreciated.Anonymous
May 19, 2011
Hi, im in the same situation as Aresh only that we will have a trust between the Forests. Is the alias/smtp-address missmatch the only Problem here? so could i simply replace alias with smtp-address in the Export file before importing? ThanksAnonymous
September 25, 2013
The comment has been removed