functions/folder/Export-EXCContactFolder.ps1
function Export-EXCContactFolder { <# .SYNOPSIS Exports contacts from a mailbox/public folder to file. .DESCRIPTION Exports contacts from a mailbox/public folder to file. Currently, only export to CSV is being supported. .PARAMETER MailboxName The name of the mailbox to access. .PARAMETER Credentials Credentials that are authorized to access that mailbox. .PARAMETER Folder Default: Contacts The relative path to a folder with contacts within the mailbox. Example: Contacts\Private .PARAMETER PublicFolderPath The relative path to a public folder with contacts to export. .PARAMETER FileName Name of the file to export to. - File will be overwritten if it exists. - File needs not exist - Parent Folder must exist - User must have write access to the target path. .PARAMETER OutputType Default: CSV Currently, only CSV is supported as output type. .EXAMPLE PS C:\> Export-EXCContactFolder -MailboxName 'ben@example.com' -Credentials $Credentials -FileName 'C:\temp\contacts.csv' Exports the content of ben@example.com's default contacts folder to file. #> [CmdletBinding(DefaultParameterSetName = "Default")] param ( [Parameter(Position = 0, Mandatory = $true)] [string] $MailboxName, [Parameter(Position = 1, Mandatory = $false)] [System.Management.Automation.PSCredential] $Credentials, [Parameter(Position = 2, Mandatory = $false, ParameterSetName = "Default")] [string] $Folder, [Parameter(Position = 2, Mandatory = $true, ParameterSetName = "PublicFolder")] [string] $PublicFolderPath, [Parameter(Position = 3, Mandatory = $true)] [string] $FileName, [Parameter(Position = 4, Mandatory = $false)] [switch] $Recurse, [Parameter(Position = 5, Mandatory = $false)] [switch] $RecurseMailbox, [Parameter(Position = 6, Mandatory = $False)] [switch] $ModernAuth, [Parameter(Position = 7, Mandatory = $False)] [String] $ClientId, [Parameter(Position = 8, Mandatory = $false)] [switch] $SkypeForBusinessContacts, [Parameter(Position = 9, Mandatory = $False)] [String] $RedirectUri= "urn:ietf:wg:oauth:2.0:oob", [Parameter(Position = 10, Mandatory = $False)] [String] $CertificateFilePath, [Parameter(Position = 11, Mandatory = $False)] [Security.SecureString] $CertificatePassword, [ValidateSet('CSV')] [string] $OutputType = "CSV" ) begin { #region Utility functions function Get-Contacts { [CmdletBinding()] param ( [Parameter(Position = 1, Mandatory = $true)] [Microsoft.Exchange.WebServices.Data.Folder] $ContactFolder ) process { $FolderCollection = @() $FolderCollection += $ContactFolder $PR_Folder_Path = new-object Microsoft.Exchange.WebServices.Data.ExtendedPropertyDefinition(26293, [Microsoft.Exchange.WebServices.Data.MapiPropertyType]::String); if ($Recurse.IsPresent) { Write-Host Getting Children $FolderCollection = Get-ChildFolders -ContactFolder $ContactFolder -FolderCollection $FolderCollection } if ($RecurseMailbox.IsPresent) { $FolderCollection = Get-AllContactFolders -SMTPAddress $MailboxName -ContactFolder $ContactFolder } foreach ($Folder in $FolderCollection) { Write-Host ("Processing " + $Folder.DisplayName) if ($Folder.TotalCount -gt 0) { $psPropset = new-object Microsoft.Exchange.WebServices.Data.PropertySet([Microsoft.Exchange.WebServices.Data.BasePropertySet]::FirstClassProperties) $PR_Gender = New-Object Microsoft.Exchange.WebServices.Data.ExtendedPropertyDefinition(14925, [Microsoft.Exchange.WebServices.Data.MapiPropertyType]::Short) $psPropset.Add($PR_Gender) #Define ItemView to retrive just 1000 Items $ivItemView = New-Object Microsoft.Exchange.WebServices.Data.ItemView(1000) $fiItems = $null do { $fiItems = $service.FindItems($Folder.Id, $ivItemView) [Void]$Folder.Service.LoadPropertiesForItems($fiItems, $psPropset) foreach ($Item in $fiItems.Items) { if ($Item -is [Microsoft.Exchange.WebServices.Data.Contact]) { if ($Recurse.IsPresent -bor $RecurseMailbox.IsPresent) { $expObj = "" | Select-Object FolderName, DisplayName, GivenName, Surname, Gender, Email1DisplayName, Email1Type, Email1EmailAddress, BusinessPhone, MobilePhone, HomePhone, BusinessStreet, BusinessCity, BusinessState, HomeStreet, HomeCity, HomeState $expObj.FolderName = $Folder.DisplayName $foldpathval = $null if ($Folder.TryGetProperty($PR_Folder_Path, [ref] $foldpathval)) { $binarry = [Text.Encoding]::UTF8.GetBytes($foldpathval) $hexArr = $binarry | ForEach-Object { $_.ToString("X2") } $hexString = $hexArr -join '' $hexString = $hexString.Replace("FEFF", "5C00") $fpath = ConvertToString($hexString) $expObj.FolderName = $fpath } } else { $expObj = "" | Select-Object DisplayName, GivenName, Surname, Gender, Email1DisplayName, Email1Type, Email1EmailAddress, BusinessPhone, MobilePhone, HomePhone, BusinessStreet, BusinessCity, BusinessState, HomeStreet, HomeCity, HomeState } $expObj.DisplayName = $Item.DisplayName $expObj.GivenName = $Item.GivenName $expObj.Surname = $Item.Surname $expObj.Gender = "" $Gender = $null if ($item.TryGetProperty($PR_Gender, [ref]$Gender)) { if ($Gender -eq 2) { $expObj.Gender = "Male" } if ($Gender -eq 1) { $expObj.Gender = "Female" } } $BusinessPhone = $null $MobilePhone = $null $HomePhone = $null if ($Item.PhoneNumbers -ne $null) { if ($Item.PhoneNumbers.TryGetValue([Microsoft.Exchange.WebServices.Data.PhoneNumberKey]::BusinessPhone, [ref]$BusinessPhone)) { $expObj.BusinessPhone = $BusinessPhone } if ($Item.PhoneNumbers.TryGetValue([Microsoft.Exchange.WebServices.Data.PhoneNumberKey]::MobilePhone, [ref]$MobilePhone)) { $expObj.MobilePhone = $MobilePhone } if ($Item.PhoneNumbers.TryGetValue([Microsoft.Exchange.WebServices.Data.PhoneNumberKey]::HomePhone, [ref]$HomePhone)) { $expObj.HomePhone = $HomePhone } } if ($Item.EmailAddresses.Contains([Microsoft.Exchange.WebServices.Data.EmailAddressKey]::EmailAddress1)) { $expObj.Email1DisplayName = $Item.EmailAddresses[[Microsoft.Exchange.WebServices.Data.EmailAddressKey]::EmailAddress1].Name $expObj.Email1Type = $Item.EmailAddresses[[Microsoft.Exchange.WebServices.Data.EmailAddressKey]::EmailAddress1].RoutingType $expObj.Email1EmailAddress = $Item.EmailAddresses[[Microsoft.Exchange.WebServices.Data.EmailAddressKey]::EmailAddress1].Address } $HomeAddress = $null $BusinessAddress = $null if ($item.PhysicalAddresses -ne $null) { if ($item.PhysicalAddresses.TryGetValue([Microsoft.Exchange.WebServices.Data.PhysicalAddressKey]::Home, [ref]$HomeAddress)) { $expObj.HomeStreet = $HomeAddress.Street $expObj.HomeCity = $HomeAddress.City $expObj.HomeState = $HomeAddress.State } if ($item.PhysicalAddresses.TryGetValue([Microsoft.Exchange.WebServices.Data.PhysicalAddressKey]::Business, [ref]$BusinessAddress)) { $expObj.BusinessStreet = $BusinessAddress.Street $expObj.BusinessCity = $BusinessAddress.City $expObj.BusinessState = $BusinessAddress.State } } $expObj } } $ivItemView.Offset += $fiItems.Items.Count } while ($fiItems.MoreAvailable -eq $true) } } } } #endregion Utility functions function ConvertToString($ipInputString) { $Val1Text = "" for ($clInt = 0; $clInt -lt $ipInputString.length; $clInt++) { $Val1Text = $Val1Text + [Convert]::ToString([Convert]::ToChar([Convert]::ToInt32($ipInputString.Substring($clInt, 2), 16))) $clInt++ } return $Val1Text } function Get-ChildFolders { [CmdletBinding()] param ( [Parameter(Position = 1, Mandatory = $true)] [Microsoft.Exchange.WebServices.Data.Folder] $ContactFolder, [Parameter(Position = 2, Mandatory = $true)] [psObject] $FolderCollection ) Process { $fvFolderView = New-Object Microsoft.Exchange.WebServices.Data.FolderView(1000) #Deep Transval will ensure all folders in the search path are returned $fvFolderView.Traversal = [Microsoft.Exchange.WebServices.Data.FolderTraversal]::Shallow; $psPropertySet = new-object Microsoft.Exchange.WebServices.Data.PropertySet([Microsoft.Exchange.WebServices.Data.BasePropertySet]::FirstClassProperties) $PR_Folder_Path = new-object Microsoft.Exchange.WebServices.Data.ExtendedPropertyDefinition(26293, [Microsoft.Exchange.WebServices.Data.MapiPropertyType]::String); #Add Properties to the Property Set $psPropertySet.Add($PR_Folder_Path); $fvFolderView.PropertySet = $psPropertySet; $fiResult = $null #The Do loop will handle any paging that is required if there are more the 1000 folders in a mailbox do { $fiResult = $ContactFolder.FindFolders($fvFolderView) foreach ($ffFolder in $fiResult.Folders) { $foldpathval = $null #Try to get the FolderPath Value and then covert it to a usable String if ($ffFolder.TryGetProperty($PR_Folder_Path, [ref] $foldpathval)) { $binarry = [Text.Encoding]::UTF8.GetBytes($foldpathval) $hexArr = $binarry | ForEach-Object { $_.ToString("X2") } $hexString = $hexArr -join '' $hexString = $hexString.Replace("FEFF", "5C00") $fpath = ConvertToString($hexString) } write-host ("FolderPath : " + $fpath + " : " + $ffFolder.TotalCount) $FolderCollection += $ffFolder if ($ffFolder.ChildFolderCount -gt 0) { $FolderCollection = Get-ChildFolders -ContactFolder $ffFolder -FolderCollection $FolderCollection } } $fvFolderView.Offset += $fiResult.Folders.Count }while ($fiResult.MoreAvailable -eq $true) return , $FolderCollection } } function Get-AllContactFolders { [CmdletBinding()] param ( [Parameter(Position = 1, Mandatory = $true)] [String] $SMTPAddress, [Parameter(Position = 2, Mandatory = $true)] [Microsoft.Exchange.WebServices.Data.Folder] $ContactFolder ) Process { $FolderCollection = @() $folderid = new-object Microsoft.Exchange.WebServices.Data.FolderId([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::MsgFolderRoot, $SMTPAddress) $RootFolder = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($ContactFolder.Service, $folderid) $fvFolderView = New-Object Microsoft.Exchange.WebServices.Data.FolderView(1000) #Deep Transval will ensure all folders in the search path are returned $fvFolderView.Traversal = [Microsoft.Exchange.WebServices.Data.FolderTraversal]::Deep; $psPropertySet = new-object Microsoft.Exchange.WebServices.Data.PropertySet([Microsoft.Exchange.WebServices.Data.BasePropertySet]::FirstClassProperties) $PR_Folder_Path = new-object Microsoft.Exchange.WebServices.Data.ExtendedPropertyDefinition(26293, [Microsoft.Exchange.WebServices.Data.MapiPropertyType]::String); $PR_ATTR_HIDDEN = new-object Microsoft.Exchange.WebServices.Data.ExtendedPropertyDefinition(0x10F4, [Microsoft.Exchange.WebServices.Data.MapiPropertyType]::Boolean); #Add Properties to the Property Set $psPropertySet.Add($PR_Folder_Path); $psPropertySet.Add($PR_ATTR_HIDDEN) $fvFolderView.PropertySet = $psPropertySet; $fiResult = $null #The Do loop will handle any paging that is required if there are more the 1000 folders in a mailbox do { $fiResult = $RootFolder.FindFolders($fvFolderView) foreach ($ffFolder in $fiResult.Folders) { if ($ffFolder.FolderClass -contains "IPF.Contact") { $BoolIsHidden = $false [Void]$ffFolder.TryGetProperty($PR_ATTR_HIDDEN, [ref]$BoolIsHidden) if (!$BoolIsHidden) { $foldpathval = $null #Try to get the FolderPath Value and then covert it to a usable String if ($ffFolder.TryGetProperty($PR_Folder_Path, [ref] $foldpathval)) { $binarry = [Text.Encoding]::UTF8.GetBytes($foldpathval) $hexArr = $binarry | ForEach-Object { $_.ToString("X2") } $hexString = $hexArr -join '' $hexString = $hexString.Replace("FEFF", "5C00") $fpath = ConvertToString($hexString) } $FolderCollection += $ffFolder } } } $fvFolderView.Offset += $fiResult.Folders.Count }while ($fiResult.MoreAvailable -eq $true) return , $FolderCollection } } # Connect $service = Connect-EXCExchange -MailboxName $MailboxName -Credentials $Credentials -ModernAuth:$ModernAuth.IsPresent -ClientId $ClientId } process { if ($PublicFolderPath) { $service.HttpHeaders.Add("X-AnchorMailbox", $MailboxName) $fldId = Get-PublicFolderIdFromPath -FolderPath $PublicFolderPath -SmtpAddress $MailboxName -service $service $contactsId = New-Object Microsoft.Exchange.WebServices.Data.FolderId($fldId) $contactFolder = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($service, $contactsId) Set-PublicFolderRoutingHeader -Service $service -Credentials $Credentials -MailboxName $MailboxName -Header "X-AnchorMailbox" } else { if ($Folder) { $contactFolder = Get-EXCContactFolder -Service $service -FolderPath $Folder -SmptAddress $MailboxName } else { if ($SkypeForBusinessContacts.IsPresent) { $folderid = new-object Microsoft.Exchange.WebServices.Data.FolderId([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::Contacts, $MailboxName) } else { $folderid = new-object Microsoft.Exchange.WebServices.Data.FolderId([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::Contacts, $MailboxName) } $contactFolder = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($service, $folderid) } } switch ($OutputType) { "CSV" { Get-Contacts -ContactFolder $contactFolder | Export-Csv -NoTypeInformation -Path $FileName -encoding "UTF8"} default { throw "Invalid output type: $OutputType" } } } } |