Copy365UserGroups/Copy-User365Groups.ps1

122 lines
4.6 KiB
PowerShell

<#
.SYNOPSIS
Copies group memberships from one user to another in Microsoft 365 with detailed logging.
.DESCRIPTION
This script connects to Exchange Online and copies all group memberships (both Microsoft 365 Groups and Distribution Lists)
from a source user to a destination user, with comprehensive logging.
.NOTES
Author : Kyle Pope
File Name : Copy-User365Groups.ps1
Prerequisite : ExchangeOnlineManagement PowerShell module
#>
# Input parameters
$source = "user@domain.com.au"
$destination = "user@domain.com.au"
# Logging configuration
$logFolder = "C:\Logs\365UserCopy"
$logDate = Get-Date -Format "ddMMyyyy_HHmm"
$logFile = "$logFolder\365UserGroupCopy_$logDate.log"
# Create log directory if it doesn't exist
if (-not (Test-Path $logFolder)) {
New-Item -ItemType Directory -Path $logFolder -Force | Out-Null
}
# Function for consistent logging
function Write-Log {
param (
[string]$Message,
[string]$Level = "INFO"
)
$timestamp = Get-Date -Format "dd-MM-yyyy HH:mm:ss"
$logEntry = "[$timestamp] [$Level] $Message"
Write-Output $logEntry | Out-File -FilePath $logFile -Append -Encoding utf8
# Also display to console
switch ($Level) {
"ERROR" { Write-Host $logEntry -ForegroundColor Red }
"WARNING" { Write-Host $logEntry -ForegroundColor Yellow }
"SUCCESS" { Write-Host $logEntry -ForegroundColor Green }
default { Write-Host $logEntry }
}
}
try {
# Start logging
Write-Log "Script started"
Write-Log "Source user: $source"
Write-Log "Destination user: $destination"
# Connect to Exchange Online
Write-Log "Connecting to Exchange Online..."
Connect-ExchangeOnline -ShowBanner:$false -ErrorAction Stop
Write-Log "Successfully connected to Exchange Online"
# Get source user details
Write-Log "Retrieving source user information..."
$sourceMailbox = Get-EXOMailbox $source -ErrorAction Stop
if (-not $sourceMailbox) {
throw "Source user $source not found"
}
$dn = $sourceMailbox.DistinguishedName
Write-Log "Source user found: $($sourceMailbox.PrimarySmtpAddress) (DN: $dn)"
# Process Microsoft 365 Groups
Write-Log "Processing Microsoft 365 Groups..."
$o365Groups = Get-EXORecipient -Filter "Members -eq '$dn'" -RecipientTypeDetails GroupMailbox -ErrorAction Stop
Write-Log "Found $($o365Groups.Count) Microsoft 365 Groups for source user"
foreach ($group in $o365Groups) {
try {
Write-Log "Adding $destination to group: $($group.Name) ($($group.PrimarySmtpAddress))"
Add-UnifiedGroupLinks -Identity $group.Name -LinkType Member -Links $destination -ErrorAction Stop
Write-Log -Level "SUCCESS" "Successfully added $destination to Microsoft 365 Group: $($group.Name)"
}
catch {
Write-Log -Level "ERROR" "Failed to add $destination to Microsoft 365 Group $($group.Name): $_"
}
}
# Process Distribution Groups
Write-Log "Processing Distribution Groups..."
$distGroups = Get-EXORecipient -Filter "Members -eq '$dn'" -RecipientTypeDetails MailUniversalDistributionGroup -ErrorAction Stop
Write-Log "Found $($distGroups.Count) Distribution Groups for source user"
foreach ($group in $distGroups) {
try {
Write-Log "Adding $destination to distribution group: $($group.Name) ($($group.PrimarySmtpAddress))"
Add-DistributionGroupMember -Identity $group.Name -Member $destination -ErrorAction Stop
Write-Log -Level "SUCCESS" "Successfully added $destination to Distribution Group: $($group.Name)"
}
catch {
Write-Log -Level "ERROR" "Failed to add $destination to Distribution Group $($group.Name): $_"
}
}
# Summary report
Write-Log "Processing complete"
Write-Log "SUMMARY:"
Write-Log " Microsoft 365 Groups processed: $($o365Groups.Count)"
Write-Log " Distribution Groups processed: $($distGroups.Count)"
}
catch {
Write-Log -Level "ERROR" "Script encountered an error: $_"
Write-Log -Level "ERROR" "Error details: $($_.ScriptStackTrace)"
}
finally {
# Disconnect from Exchange Online
try {
Write-Log "Disconnecting from Exchange Online..."
Disconnect-ExchangeOnline -Confirm:$false -ErrorAction SilentlyContinue
Write-Log "Disconnected from Exchange Online"
}
catch {
Write-Log -Level "WARNING" "Failed to properly disconnect from Exchange Online: $_"
}
Write-Log "Script completed"
Write-Log "Log file saved to: $logFile"
}