We had a requirement from one of the product team that connects their application to office 365 Exchange Online thru Exchange Web Services to collect distribution group members and than send them newsletters. They stumbled upon a issue, they were not able to fetch members on few of the distribution groups.
As you could have now got the idea, reason is that these are all Dynamic distribution groups.
To resolve this for them we have written this powershell solution that fetches the members from Dynamic Distribution group and populates the Static group with same members. if members are added based on the criteria inside the Dynamic distribution group filter than these are added to static group , if members are removed from the Dynamic distribution group than same happens with Static group.
Download the script solution from below link and update the parameters (below params are self explanatory)
https://github.com/VikasSukhija/Downloads/blob/master/Dynamic2StaticDL.ps1
param (
You can create the batch file and schedule it.(you can have multiple entries in batch file to convert multiple Dynamic groups)
On first run keep the countofchanges values to large enough to cover all the members, after that you can schedule it to run daily and reduce the count of changes to the amount that you think can not get added in a day.(This parameter is just for safety sake)
powershell -noprofile -executionpolicy bypass -file .\Dynamic2StaticDL.ps1 -dynamicgroup “Test Dynamic Group1” -staticgroup “Test static Group1” -smtpserver smtpserver -from “DoNotReply@labtest.com” -erroremail “reports@labtest.com” -countofchanges 200
powershell -noprofile -executionpolicy bypass -file .\Dynamic2StaticDL.ps1 -dynamicgroup “Test Dynamic Group2” -staticgroup “Test static Group2” -smtpserver smtpserver -from “DoNotReply@labtest.com” -erroremail “reports@labtest.com” -countofchanges 200
powershell -noprofile -executionpolicy bypass -file .\Dynamic2StaticDL.ps1 -dynamicgroup “Test Dynamic Group3” -staticgroup “Test static Group3” -smtpserver smtpserver -from “DoNotReply@labtest.com” -erroremail “reports@labtest.com” -countofchanges 200
Please update the Exchange server Name to connect to in the below command at line 109 (Start script section)
Script will create logs in logs folder and will recycle them after 60 days.
Note: Exchange Management Shell and Active Directory Module are required to run this script.
I hope this solution will assist you if you are in the similar situation.
There can be other use case, if you want static groups but still want these updated frequently.(office 365 does not support Exchange on-premise dynamic groups, so using this solution, you can create static groups instead of creating contacts and pointing them to onprem dynamic group. – This will also assist in adding this group to team, use for share point permissions provided it is security DL)
<# .NOTES =========================================================================== Created with: ISE Created on: 7/25/2019 Created by: Vikas Sukhija Organization: Filename: Dynamic2StaticDL.ps1 =========================================================================== .DESCRIPTION This Script is converting the Dynamic Dls to Static Dls #> param ( [string]$dynamicgroup = $(Read-Host "Enter the dynamic Group"), [string]$staticgroup = $(Read-Host "Enter the static Group"), [string]$smtpserver = $(Read-Host "Enter SMTP Server"), [string]$from = $(Read-Host "Enter From Address"), [string]$erroremail = $(Read-Host "Enter Address for Report and Errors"), $countofchanges = $(Read-Host "Enter Count of changes") ) function Write-Log { [CmdletBinding()] param ( [Parameter(Mandatory = $true,ParameterSetName = 'Create')] [array]$Name, [Parameter(Mandatory = $true,ParameterSetName = 'Create')] [string]$Ext, [Parameter(Mandatory = $true,ParameterSetName = 'Create')] [string]$folder, [Parameter(ParameterSetName = 'Create',Position = 0)][switch]$Create, [Parameter(Mandatory = $true,ParameterSetName = 'Message')] [String]$Message, [Parameter(Mandatory = $true,ParameterSetName = 'Message')] [String]$path, [Parameter(Mandatory = $false,ParameterSetName = 'Message')] [ValidateSet('Information','Warning','Error')] [string]$Severity = 'Information', [Parameter(ParameterSetName = 'Message',Position = 0)][Switch]$MSG ) switch ($PsCmdlet.ParameterSetName) { "Create" { $log = @() $date1 = Get-Date -Format d $date1 = $date1.ToString().Replace("/", "-") $time = Get-Date -Format t $time = $time.ToString().Replace(":", "-") $time = $time.ToString().Replace(" ", "") foreach ($n in $Name) {$log += (Get-Location).Path + "\" + $folder + "\" + $n + "_" + $date1 + "_" + $time + "_.$Ext"} return $log } "Message" { $date = Get-Date $concatmessage = "|$date" + "| |" + $Message +"| |" + "$Severity|" switch($Severity){ "Information"{Write-Host -Object $concatmessage -ForegroundColor Green} "Warning"{Write-Host -Object $concatmessage -ForegroundColor Yellow} "Error"{Write-Host -Object $concatmessage -ForegroundColor Red} } Add-Content -Path $path -Value $concatmessage } } } #Function Write-Log function ProgressBar { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] $Title, [Parameter(Mandatory = $true)] [int]$Timer ) For ($i = 1; $i -le $Timer; $i++) { Start-Sleep -Seconds 1; Write-Progress -Activity $Title -Status "$i" -PercentComplete ($i /10 * 100) } } #################Check if logs folder is created#### $logpath = (Get-Location).path + "\logs" $testlogpath = Test-Path -Path $logpath if($testlogpath -eq $false) { ProgressBar -Title "Creating logs folder" -Timer 10 New-Item -Path (Get-Location).path -Name Logs -Type directory } ####################Load variables and log########## $log = Write-Log -Name "Dynamic2staticdl-Log" -folder "logs" -Ext "log" ########################Start Script################ Write-Log -Message "Start script" -path $log try { Import-Module ActiveDirectory $Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri ExchangeServer -Authentication Kerberos import-pssession $session -AllowClobber Write-Log -Message "loaded.... AD and Exchange Module" -path $log } catch { $exception = $_.Exception Write-Log -Message "Error loading AD and Exchange Module" -path $log -Severity Error Write-Log -Message $exception -path $log -Severity error Send-MailMessage -SmtpServer $smtpserver -From $from -To $erroremail -Subject "Error has occured loading AD and Exchange Module - Dynamic2staticDL" -Body $($_.Exception.Message) exit; } try{ Write-Log -Message "Start fetching group membership information $dynamicgroup" -path $log $colldynamicgroup = Get-DynamicDistributionGroup -id $dynamicgroup $colldynamicgroupmem = Get-Recipient -RecipientPreviewFilter $colldynamicgroup.LdapRecipientFilter -resultsize unlimited | Select samaccountname Write-Log -Message "Finished fetching group membership information $dynamicgroup" -path $log } catch{ $exception = $_.Exception Write-Log -Message "Error fetching group membership information $dynamicgroup" -path $log -Severity Error Write-Log -Message $exception -path $log -Severity error Send-MailMessage -SmtpServer $smtpserver -From $from -To $erroremail -Subject "Error has occured fetching group membership information $dynamicgroup - Dynamic2staticDL" -Body $($_.Exception.Message) exit; } try{ Write-Log -Message "Start fetching group membership information $staticgroup" -path $log $collstaticgroupmem = Get-ADGroup $staticgroup -Properties Member | Select-Object -ExpandProperty Member | Get-ADUser | Select-Object samaccountname Write-Log -Message "Finished fetching group membership information $staticgroup" -path $log } catch{ $exception = $_.Exception Write-Log -Message "Error fetching group membership information $staticgroup" -path $log -Severity Error Write-Log -Message $exception -path $log -Severity error Send-MailMessage -SmtpServer $smtpserver -From $from -To $erroremail -Subject "Error has occured fetching group membership information $staticgroup - Dynamic2staticDL" -Body $($_.Exception.Message) exit; } try{ Write-Log -Message "Start comparing $staticgroup $dynamicgroup" -path $log $changes = Compare-Object -ReferenceObject $colldynamicgroupmem -DifferenceObject $collstaticgroupmem -Property samaccountname | Select-Object -Property samaccountname, @{ n = 'State' e = {If ($_.SideIndicator -eq "=>"){"Removal" } Else { "Addition" }} } if($Changes){ $removal = $Changes | Where-Object -FilterScript {$_.State -eq "Removal"} | Select -ExpandProperty samaccountname $Addition = $Changes | Where-Object -FilterScript {$_.State -eq "Addition"} | Select -ExpandProperty samaccountname if($Addition){ $addcount = $Addition.count Write-Log -Message "Adding members to $staticgroup count $addcount" -path $log if($addcount -le $countofchanges){ $Addition | ForEach-Object{ $amem = $_ Write-Log -Message "ADD $amem to $staticgroup" -path $log ADD-ADGroupMember -identity $staticgroup -Members $amem -Confirm:$false } }else{ Write-Log -Message "ADD count $addcount is more than $countofchanges" -path $log -Severity Error Send-MailMessage -SmtpServer $smtpserver -From $from -To $erroremail -Subject "Error has occured ADD count $addcount is more than $countofchanges - Dynamic2staticDL" -Body "Error has occured ADD count $addcount is more than $countofchanges - Dynamic2staticDL" } } if($removal){ $remcount = $removal.count Write-Log -Message "Removing members from $staticgroup count $remcount" -path $log if($remcount -le $countofchanges){ $removal | ForEach-Object{ $rmem = $_ Write-Log -Message "Remove $rmem from $staticgroup" -path $log Remove-ADGroupMember -identity $staticgroup -Members $rmem -Confirm:$false } }else{ Write-Log -Message "Remove count $remcount is more than $countofchanges" -path $log -Severity Error Send-MailMessage -SmtpServer $smtpserver -From $from -To $erroremail -Subject "Error has occured Remove count $remcount is more than $countofchanges - Dynamic2staticDL" -Body "Error has occured Remove count $remcount is more than $countofchanges - Dynamic2staticDL" } } } } catch{ $exception = $_.Exception Write-Log -Message "Error comparing $staticgroup $dynamicgroup" -path $log -Severity Error Write-Log -Message $exception -path $log -Severity error Send-MailMessage -SmtpServer $smtpserver -From $from -To $erroremail -Subject "Error has occured comparing $staticgroup $dynamicgroup - Dynamic2staticDL" -Body $($_.Exception.Message) } ########################Recycle reports & logs############## $path1 = $logpath $limit = (Get-Date).AddDays(-60) #for report recycling Get-ChildItem -Path $path1 | Where-Object -FilterScript {$_.CreationTime -lt $limit} | Remove-Item -Recurse -Force Write-Log -Message "Script Finished" -path $log Send-MailMessage -SmtpServer $smtpserver -From $from -To $erroremail -Subject "Transcript Log - Dynamic2staticDL" -Body "Transcript Log - Dynamic2staticDL" -Attachments $log ###########################################################################