From e7e0dfabe64b39243bcfbe124f651afd97d84ba1 Mon Sep 17 00:00:00 2001 From: Kyle Date: Fri, 11 Apr 2025 15:12:26 +0800 Subject: [PATCH] initial commit - adding main script. --- Copy-User365Groups.ps1 | 122 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 122 insertions(+) create mode 100644 Copy-User365Groups.ps1 diff --git a/Copy-User365Groups.ps1 b/Copy-User365Groups.ps1 new file mode 100644 index 0000000..ee61cb0 --- /dev/null +++ b/Copy-User365Groups.ps1 @@ -0,0 +1,122 @@ +<# +.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 + File Name : Copy-365GroupMembershipsV3.ps1 + Prerequisite : ExchangeOnlineManagement PowerShell module + Approved by SSE Chris Proudmore - 11/04/2025 - While working on #2627086 +#> + +# 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" +} \ No newline at end of file