Automating with PowerShell: Creating dynamic distribution groups in all O365 tenants

Someone on the /r/msp reddit, and a Slack that I frequent asked if it is possible to create an “all users” distribution group with PowerShell, and keep it up to date. I figured to spend some time on it.

To achieve a list that is always up to date, we can use Dynamic Distribution groups. Dynamic groups allow you to add specific users based on their properties. for example; if a user has a full mailbox, it will be added. You can make these queries as complex as you want.

Our script uses the Secure Application Model to create a couple of new dynamic distribution groups; a single one that contains all users called “AllCompanyUsers” and one per domain that the client has. The domain group only contains people that use that domain’s email address. For example; Cybedrain.com@cyberdrain.com contains John, Hank, and Bob. It does not contain Janet because she uses @Janetdrain.com as an e-mail.

The script

$ApplicationId = 'APPLICATIONID'
$ApplicationSecret = 'APPLICATIONSECRET' | Convertto-SecureString -AsPlainText -Force
$TenantID = 'YOUURTENANTID'
$RefreshToken = 'Freakishly long refreshtoken'
$ExchangeRefreshToken = 'Freakishly long refresh'
$UPN = "UPN-Of-User-Generating-Tokens"

$credential = New-Object System.Management.Automation.PSCredential($ApplicationId, $ApplicationSecret)

$aadGraphToken = New-PartnerAccessToken -ApplicationId $ApplicationId -Credential $credential -RefreshToken $refreshToken -Scopes 'https://graph.windows.net/.default' -ServicePrincipal -Tenant $tenantID 
$graphToken = New-PartnerAccessToken -ApplicationId $ApplicationId -Credential $credential -RefreshToken $refreshToken -Scopes 'https://graph.microsoft.com/.default' -ServicePrincipal -Tenant $tenantID 

Connect-MsolService -AdGraphAccessToken $aadGraphToken.AccessToken -MsGraphAccessToken $graphToken.AccessToken
$customers = Get-MsolPartnerContract -All
foreach ($customer in $customers) {
    $token = New-PartnerAccessToken -ApplicationId 'a0c73c16-a7e3-4564-9a95-2bdf47383716'-RefreshToken $ExchangeRefreshToken -Scopes 'https://outlook.office365.com/.default' -Tenant $customer.TenantId
    $tokenValue = ConvertTo-SecureString "Bearer $($token.AccessToken)" -AsPlainText -Force
    $credential = New-Object System.Management.Automation.PSCredential($upn, $tokenValue)
    $customerId = $customer.DefaultDomainName
    $session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri "https://ps.outlook.com/powershell-liveid?DelegatedOrg=$($customerId)&BasicAuthToOAuthConversion=true" -Credential $credential -Authentication Basic -AllowRedirection
    Import-PSSession $session -AllowClobber -DisableNameChecking -CommandName "Get-DynamicDistributionGroup","New-DynamicDistributionGroup","Set-DynamicDistributionGroup"
    write-host "Logged into tenant $($customer.defaultdomainname)" -ForegroundColor Green
    write-host "Checking if all users list exist, if not, creating them." -ForegroundColor Green
    $ExisitingAllUserList = Get-DynamicDistributionGroup -anr "AllCompanyUsers"

    if (!$ExisitingAllUserList) { 
        write-host "Creating AllCompanyUsers group" -ForegroundColor Green
        New-DynamicDistributionGroup -Name "AllCompanyUsers" -RecipientFilter "(RecipientType -eq 'UserMailbox')" | out-null
        Get-DynamicDistributionGroup -anr "AllCompanyUsers" | Set-DynamicDistributionGroup -RequireSenderAuthenticationEnabled $False -HiddenFromAddressListsEnabled $true | out-null
    }
    
    write-host "Checking all domains, and creating a list for each domain."  -ForegroundColor Green
    $Domains = Get-MsolDomain -TenantId $customer.TenantId
    foreach ($Domain in $domains.name) {
        write-host "Checking domain $($Domain) creating if it does not exist."  -ForegroundColor Green
        $ExisitingDomainList = Get-DynamicDistributionGroup -anr $Domain
        if (!$ExisitingDomainList) {
            write-host "   Creating $domain list"  -ForegroundColor Green
            New-DynamicDistributionGroup -Name "$domain" -RecipientFilter "(RecipientType -eq 'UserMailbox') -and (EmailAddresses -like '$Domain')" | out-null
            Get-DynamicDistributionGroup -anr "$Domain" | Set-DynamicDistributionGroup -RequireSenderAuthenticationEnabled $False -HiddenFromAddressListsEnabled $true | out-null
        }
    }
    Remove-PSSession $session
}

So, that’s it! as always, Happy PowerShelling!

3 thoughts on “Automating with PowerShell: Creating dynamic distribution groups in all O365 tenants

  1. Pierre

    Should the GET / SET on dynamic groups not be in the IF statement ?
    IF is for create when it does not exists, then updates.
    But as the GET/SET is in the IF, it does not updates the list if it exists .. 🙂

    Am I Wrong ?

    Reply
  2. Pingback: ICYMI: PowerShell Week of 29-May-2020 | PowerShell.org

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.