Dynamic to Static Distribution Group

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 (

[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”)
)

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)

$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri ExchangeServer -Authentication Kerberos

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 
 
###########################################################################
 Thanks for reading and downloading
 Sukhija Vikas
 http://SysCloudPro.com

Leave a comment