Using Powershell to Create Distribution Groups in Office 365 from Secondary Mailboxes

IT departments typically will create a secondary account for a user in the event that they have multiple domains. They usually do this because they want the user to send as both email addresses. On Exchange server you do not pay for each email account. This is not the case now that companies are moving to Office 365 as their email provider. In Office 365 you will be paying for each user so this is not a good method. We are going to use Powershell to fix this problem.

You first create the user’s primary account or allow tools such as AD Connect to create it. This is what we did. We used AD Connect to push the primary accounts to Office 365. You can then create the secondary email addresses as distribution groups and assign SendAs rights to the primary email address.

I recently was a part of an Office 365 migration where the client had 5 separate domains. Not every user had all 5 domains but many had multiple. Some users had many additional aliases for each of those domains. Our plan was to create OU’s in AD for each domain and move the primary accounts inside of those OU’s. We then created a distribution groups OU for all of the secondary accounts. Last we set the UPN of all users to their public record instead of the .local internal FQDN. Here is a link to an article on a Powershell solution to this…Powershell Set UPN in Active Directory

This script was written to be executed from the Exchange server. You can easily change it to connect remotely to the Exchange server but I did not use it that way.

The first thing that you must do is load the active directory module. This is needed to get the cmdlets to get the users from AD. Next is to load the msoline module to be able to connect to Office 365.

Let’s Begin using Powershell

Loading modules

# import the Active Directory module to get the cmdlets
Import-Module activedirectory
Install-Module MSOnline 

I always set the $verbosepreference to continue since I use the Write-Verbose cmdlet instead of the Write-Host. $username and $password variables are for the credentials for the Office 365 tenant. The $path variable is for the DN of the OU that contains the accounts that you want to convert to groups.

Initializing variables

# set verbose preference for the Write-Verbose cmdlet
$VerbosePreference = 'Continue'
$username = ''
$passwd = ''
$path = ''

Now that we got all of the prep work done it is time to connect to Office 365. First we will convert the password to a secure string and then creating a PSCredential object to store the password. Next, we will create a PSSession to https://ps.outlook.com/powershell/ using the credentials and import that session to the console.

Connecting to Office 365

# connect to office 365
$password = ConvertTo-SecureString $passwd -AsPlainText -Force
$creds = New-Object System.Management.Automation.PSCredential ("$username", $password)
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://ps.outlook.com/powershell/ -Credential $creds -Authentication Basic –AllowRedirection
Import-PSSession $Session -AllowClobber

We are now also going to use the Connect-MsolService. There are 2 ways to connect to Office 365 and each way allows you to manage different aspects. I had to use this way since I was running the script from the Exchange server itself. Every time I tried to use the normal cmdlets to create a distribution group it would try to create the distribution group locally. I needed to use the Get-UnifiedGroup and the Set-UnifiedGroup to create the distribution groups so that it would create them in Office 365.

Connect-MsolService -Credential $creds

Now go into Active Directory and extract a list of user objects from the OU we created earlier. Place them in the $users variable. $users is now an array that stores multiple user objects that we can now begin to manipulate.

Gathering data from Exchange

# get the the list of OUs from the root SBSUsers OU
$DLOU = Get-ADOrganizationalUnit -Identity $path
$users = Get-Aduser -filter * -Properties * -SearchBase $DLOU -SearchScope OneLevel

Now we are going to loop through each user in the $users array and place the current object into the $user variable. Once we are done with the current object and the loop begins again on the 2nd object in the array the contents of the $user variable will be overwritten with the new user.

Creating the groups!

# loop through each user
foreach ($user in $users){

We are going to create a new variable and place in it the group object that matches the user if it is already created. Check to see if the contents of $dl is empty by comparing it to $null. This basically means empty and later on we will output a message if it is already created but for now we will continue on to create the group if it is empty.

Write-Verbose "Checking to see if the group $($user.name) was created "
    $dl = Get-UnifiedGroup "$($user.name)"
    if ($dl -eq $null){
        Write-Verbose "Group $($user.name) did not exist, creating now......"

So now comes the tricky part, which is to find the user account in Office 365 that is the primary account for the user. To do this we are going to use the display name property. First ensure that the display name property in AD was the same for each account for the user. Then will use the Get-MsolUser cmdlet to get the Office 365 user (primary account) whose display name matches the display name of the user in Active Directory (secondary account).

$365user = (Get-MsolUser | Where {$_.DisplayName -match "$($user.DisplayName)"}).UserPrincipalName
        $365display = (Get-MsolUser | Where {$_.DisplayName -match "$($user.DisplayName)"}).DisplayName
        Write-Host "$($user.name)"

Now we will use the New-UnifiedGroup cmdlet to create the new group and set the owner of the group to the primary Office 365 account.

Write-Verbose "Creating group named $($user.name)...."
New-UnifiedGroup "$($user.name)" -DisplayName "$($user.name)" -PrimarySmtpAddress $($user.EmailAddress) -Owner $365display

After we create the group, we want to verify that it was indeed created. Then if it was created we can begin to set some of the settings. We get the group and place it in the $dlcheck variable and then compare that variable to see if it does not equal null

Write-Verbose "Checking to see if the group was created "
$dlcheck = Get-UnifiedGroup "$($user.name)"
if ($dlcheck -ne $null){

We are now going to add the primary Office 365 account as a membor of the group using the Add-UnifiedGroupsLinks cmdlet. Create aliases on the group for each proxy address on the secondary user account using the -emailaddresses parameter on the Set-UnifiedGroup cmdlet. Most users had more than one proxy. Create an array of them in the $proxies variable. We will now loop through them using a foreach statement placing the current one in the loop into the $proxy variable.

            Write-Verbose "Adding member $365user to group $($user.name)"
            Add-UnifiedGroupLinks -Identity "$($user.name)" -LinkType Members -Links $365user
            Write-Verbose "Checking for the list of proxy addresses for $($user.name)"
            $proxies = $user.proxyaddresses | where {$_ -notmatch ''}
            foreach ($proxy in $proxies){
                $proxy = $proxy.split(":")[1]
                Write-Verbose "$proxy"
                Set-UnifiedGroup "$($user.name)" -emailaddresses @{Add=$proxy}
            }
        }

Here is the exit code that outputs to the console if the group already existed. It is always good practive to write your code to first check for what you want to change and then exit if it is already correct.

     } else {
        Write-Host "A group named $($user.name) exists "
    }
}

Followup post cutover edits

After we ran the above script we noticed a problem. The script created the group. It also added the primary account as the owner and the Send On Behalf Of. This is not what we wanted, though. We wanted to have Send As rights so we had to make this change. I reconnected to Office 365 and got a list of all Office 365 groups. Then I set the SendAs permission equal to the Send On Behalf Of permissions using the Add-RecipientPermission cmdlet.

 $dls = Get-UnifiedGroup
foreach ($dl in $dls){
    Add-RecipientPermission -Identity $dl.Name -Trustee $($dl.GrantSendOnBehalfTo) -AccessRights SendAs -Confirm
}

We ran into another issue in that no one was allowed to send emails to the distribution groups. I went into the portal (gasp, I know right) and checked a few. There is a check box that needs to be checked for this. When I was in there I noticed that they were also all set to Public. This would be a big big no no!! I get all of the groups again into the $dls array. I then loop through them one at a time. I set the property RequireSenderAuthenticationEnabled to false. This means you are not required to be authenticated to send an email to the group. Next I set the AccessType property to Private so only the user can see the contents.

 $dls = Get-UnifiedGroup
foreach ($dl in $dls){
    $dl | Set-UnifiedGroup -RequireSenderAuthenticationEnabled $false
    $dl | Set-UnifiedGroup -AccessType 'Private'
}

I hope this helps you learn Powershell and some of the powerful ways it can be used to make life easier.

Here is the full code, enjoy!!!….

# import the Active Directory module to get the cmdlets
Import-Module activedirectory
Install-Module MSOnline 

# set verbose preference for the Write-Verbose cmdlet
$VerbosePreference = 'Continue'
$username = ''
$passwd = ''
$path = ''

# connect to office 365
$password = ConvertTo-SecureString $passwd -AsPlainText -Force
$creds = New-Object System.Management.Automation.PSCredential ("$username", $password)
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://ps.outlook.com/powershell/ -Credential $creds -Authentication Basic –AllowRedirection
Import-PSSession $Session -AllowClobber
Connect-MsolService -Credential $creds

# get the the list of OUs from the root SBSUsers OU
$DLOU = Get-ADOrganizationalUnit -Identity $path
$users = Get-Aduser -filter * -Properties * -SearchBase $DLOU -SearchScope OneLevel

# loop through each user
foreach ($user in $users){
    Write-Verbose "Checking to see if the group $($user.name) was created "
    $dl = Get-UnifiedGroup "$($user.name)"
    if ($dl -eq $null){
        Write-Verbose "Group $($user.name) did not exist, creating now......"
        $365user = (Get-MsolUser | Where {$_.DisplayName -match "$($user.DisplayName)"}).UserPrincipalName
        $365display = (Get-MsolUser | Where {$_.DisplayName -match "$($user.DisplayName)"}).DisplayName
        Write-Host "$($user.name)"
        Write-Verbose "Creating group named $($user.name)...."
        New-UnifiedGroup "$($user.name)" -DisplayName "$($user.name)" -PrimarySmtpAddress $($user.EmailAddress) -Owner $365display
        Write-Verbose "Checking to see if the group was created "
        $dlcheck = Get-UnifiedGroup "$($user.name)"
        if ($dlcheck -ne $null){
            Write-Verbose "Adding member $365user to group $($user.name)"
            Add-UnifiedGroupLinks -Identity "$($user.name)" -LinkType Members -Links $365user
            Write-Verbose "Checking for the list of proxy addresses for $($user.name)"
            $proxies = $user.proxyaddresses | where {$_ -notmatch 'INPUT_LOCAL_DOMAIN_HERE'}
            foreach ($proxy in $proxies){
                $proxy = $proxy.split(":")[1]
                Write-Verbose "$proxy"
                Set-UnifiedGroup "$($user.name)" -emailaddresses @{Add=$proxy}
            }
        }
    } else {
        Write-Host "A group named $($user.name) exists "
    }
}

Updated edits….

SendAs permissions

$dls = Get-UnifiedGroup
foreach ($dl in $dls){
    Add-RecipientPermission -Identity $dl.Name -Trustee $($dl.GrantSendOnBehalfTo) -AccessRights SendAs -Confirm
}

Allowing people to send to the group and making it private

$dls = Get-UnifiedGroup foreach ($dl in $dls){ $dl | Set-UnifiedGroup -RequireSenderAuthenticationEnabled $false $dl | Set-UnifiedGroup -AccessType 'Private' }

Leave a Reply

Your email address will not be published.