Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,9 @@
/docs/M365/MDO/ @iserrano76 @rosspa05 @microsoft/css-exchange-admins

# EXO PF Team
/PublicFolders/Migration/ @vishmittal @microsoft/css-exchange-admins
/PublicFolders/Hybrid/ @vishmittal @microsoft/css-exchange-admins
/PublicFolders/Update-PublicFolderPermissions.ps1 @vishmittal @microsoft/css-exchange-admins
/docs/PublicFolders/Migration/ @vishmittal @microsoft/css-exchange-admins
/docs/PublicFolders/Hybrid/ @vishmittal @microsoft/css-exchange-admins
/docs/PublicFolders/Update-PublicFolderPermissions.md @vishmittal @microsoft/css-exchange-admins
154 changes: 154 additions & 0 deletions PublicFolders/Hybrid/Import-PublicFolderMailboxes.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.

# .SYNOPSIS
# Import-PublicFolderMailboxes.ps1
# Import the public folder mailboxes as mail enabled users from cloud to on-premise
#
# Example input to the script:
#
# Import-PublicFolderMailboxes.ps1 -ConnectionUri <cloud url>
#
# The above example imports public folder mailbox objects from cloud as mail enabled users to on-premise.
param (
[Parameter(Mandatory=$false)]
[PSCredential] $Credential,

[Parameter(Mandatory = $false)]
[ValidateNotNull()]
[string] $ConnectionUri = "https://outlook.office365.com/powerShell-liveID"
)

#cspell:words EXOV2

## Create a tenant PSSession.
function CreateTenantSession() {
Import-Module ExchangeOnlineManagement -ErrorAction SilentlyContinue
if (Get-Module ExchangeOnlineManagement) {
$sessionOption = (New-PSSessionOption -SkipCACheck)
Connect-ExchangeOnline -Credential $Credential -ConnectionURI $ConnectionUri -PSSessionOption $sessionOption -Prefix "Remote" -ErrorAction SilentlyContinue
} else {
Write-Warning $LocalizedStrings.EXOV2ModuleNotInstalled
exit
}
}

## Writes a dated information message to console
function WriteInfoMessage() {
param ($message)
Write-Host "[$($(Get-Date).ToString())]" $message
}

## Retrieve public folder mailboxes
function GetPublicFolderMailBoxes() {
$publicFolderMailboxes = Get-RemoteMailbox -PublicFolder -ResultSize:Unlimited -ErrorAction:SilentlyContinue -WarningAction:SilentlyContinue

# Return the results
if ($null -eq $publicFolderMailboxes -or ([array]($publicFolderMailboxes)).Count -lt 1) {
return $null
}

return $publicFolderMailboxes
}

## Sync public folder mailboxes from cloud to on-prem.
function SyncPublicFolderMailboxes(
[object[]] $publicFolderMailboxes) {
WriteInfoMessage ($LocalizedStrings.DeletingMailUsersInfo)
$remoteMailboxes = Get-OrganizationConfig | Select-Object RemotePublicFolderMailboxes

foreach ($adObjectId in $remoteMailboxes.RemotePublicFolderMailboxes) {
$mailUser = Get-MailUser $adObjectId -ErrorAction:SilentlyContinue -WarningAction:SilentlyContinue

if ($null -ne $mailUser) {
WriteInfoMessage ($LocalizedStrings.RemovingMailUsers -f $mailUser)
Set-OrganizationConfig -RemotePublicFolderMailboxes @{Remove =$mailUser }

WriteInfoMessage ($LocalizedStrings.DeleteMailUser -f $mailUser)
Remove-MailUser $mailUser -Confirm:$false
}
}
Set-OrganizationConfig -RemotePublicFolderMailboxes:$Null

$validExternalEmailAddresses = @()
$mailUserList = @()

if ($null -ne $publicFolderMailboxes) {
$hasPublicFolderServingHierarchy = $false
foreach ($publicFolderMailbox in $publicFolderMailboxes) {
if ($publicFolderMailbox.IsExcludedFromServingHierarchy -eq $false) {
$hasPublicFolderServingHierarchy = $true
$displayName = $publicFolderMailbox.Name.ToString().Trim()
$name = "RemotePfMbx-" + $displayName + "-" + [guid]::NewGuid()
$name = $(if ($name.length -gt 64) { $name.substring(0, 64) } else { $name })
$externalEmailAddress = $publicFolderMailbox.PrimarySmtpAddress.ToString()

WriteInfoMessage ($LocalizedStrings.SyncingPublicFolderMailbox -f $displayName)

$mailUser = Get-MailUser $externalEmailAddress -ErrorAction:SilentlyContinue -WarningAction:SilentlyContinue

if ($null -eq $mailUser) {
WriteInfoMessage ($LocalizedStrings.CreatingMailUser -f $displayName)
try {
$mailUser = New-MailUser -Name $name -ExternalEmailAddress $externalEmailAddress -DisplayName $displayName
$mailUserList += $mailUser
} catch {
Write-Host $error[0]
}
} else {
WriteInfoMessage ($LocalizedStrings.MailUserExists -f $mailUser)
}

WriteInfoMessage ($LocalizedStrings.ConfiguringMailUser -f $mailUser)

WriteInfoMessage ($LocalizedStrings.DoneSyncingPublicFolderMailbox -f $displayName)
Write-Host ""
}
}
}

if (-not $hasPublicFolderServingHierarchy) {
WriteInfoMessage ($LocalizedStrings.NoHierarchyPublicFolderMailbox)
Write-Host ""
}

foreach ($mailUser in $mailUserList) {
$validExternalEmailAddresses += $mailUser.ExternalEmailAddress
Set-OrganizationConfig -RemotePublicFolderMailboxes @{Add =$mailUser }
}
}

#load hashtable of localized string
$LocalizedStrings = ConvertFrom-StringData @'
SyncingPublicFolderMailbox = Syncing public folder mailbox '{0}'.
CreatingMailUser = Creating MailUser object '{0}'.
MailUserExists = MailUser object '{0}' already exists for this public folder mailbox.
ConfiguringMailUser = Adding '{0}' to RemotePublicFolderMailboxes.
DoneSyncingPublicFolderMailbox = Done syncing public folder mailbox '{0}'
NoHierarchyPublicFolderMailbox = There aren't any public folder mailboxes, serving hierarchy, to import.
DeletingMailUsersInfo = Deleting MailUsers, if any, that don't have corresponding public folder mailboxes in the cloud, serving hierarchy.
RemovingMailUsers = Removing '{0}' from RemotePublicFolderMailboxes.
DeleteMailUser = Deleting MailUser object '{0}'.
IncorrectCredentials = Please provide correct credentials to establish remote session.
StartedPublicFolderMailboxImport = Started import of public folder mailboxes.
CompletedPublicFolderMailboxImport = Completed import of public folder mailboxes.
EXOV2ModuleNotInstalled = This script uses modern authentication to connect to Exchange Online and requires EXO V2 module to be installed. Please follow the instructions at https://docs.microsoft.com/powershell/exchange/exchange-online-powershell-v2?view=exchange-ps#install-the-exo-v2-module to install EXO V2 module.
'@

# Create a tenant PSSession against Exchange Online with modern auth.
CreateTenantSession

WriteInfoMessage ($LocalizedStrings.StartedPublicFolderMailboxImport)
Write-Host ""

# Get mail enabled public folders in the organization
$publicFolderMailboxes = GetPublicFolderMailBoxes

# Create mail enabled users for remote public folder mailboxes
SyncPublicFolderMailboxes $publicFolderMailboxes

Write-Host ""
WriteInfoMessage ($LocalizedStrings.CompletedPublicFolderMailboxImport)

# Terminate the PSSession
Disconnect-ExchangeOnline -Confirm:$false -ErrorAction SilentlyContinue
Loading