Public/Import/Google/Import-GoogleToEXOGroup.ps1
function Import-GoogleToEXOGroup { <# .SYNOPSIS Import CSV of Google Groups into Office 365 as Distribution Groups .DESCRIPTION Import CSV of Google Groups into Office 365 as Distribution Groups .PARAMETER LogPath The full path and file name of the log ex. c:\scripts\AddGroupsLog.csv (use csv for best results) .PARAMETER Group Google Group(s) and respective attributes .PARAMETER DontAddOwnersToManagedBy Google Group "Owners" will not be added Office 365's "ManagedBy" .PARAMETER DontAddManagersToManagedBy Google Group "Managers" will not be added Office 365's "ManagedBy" .PARAMETER DontCopyManagedByToMember Unless you use this switch, all in "ManagedBy" will become members of the Distribution Group .PARAMETER INVITED_CAN_JOIN_TranslatesTo If Google Group's "whoCanJoin" attribute contains the option INVITED_CAN_JOIN, the default behavior sets, "MemberJoinRestriction" to 'ApprovalRequired'. Use this parameter to override with either 'Open' or 'Closed' .PARAMETER CAN_REQUEST_TO_JOIN_TranslatesTo If Google Group's "whoCanJoin" attribute contains the option CAN_REQUEST_TO_JOIN, the default behavior sets, "MemberJoinRestriction" to 'ApprovalRequired'. Use this parameter to override with either 'Open' or 'Closed' .EXAMPLE Import-Csv C:\scripts\GoogleGroups.csv | Import-GoogleToEXOGroup -LogPath C:\Scripts\EXOGroupResults.csv .NOTES Choosing both -DontAddOwnersToManagedBy & -DontAddManagersToManagedBy results in the ManagedBy field being populated with the account that runs this script. The same is true if the Google Group has both no managers and no owners #> [CmdletBinding()] Param ( [Parameter(Mandatory)] $LogPath, [Parameter(Mandatory, ValueFromPipeline)] $Group, [Parameter()] [switch] $DontAddOwnersToManagedBy, [Parameter()] [switch] $DontAddManagersToManagedBy, [Parameter()] [switch] $DontCopyManagedByToMember, [Parameter()] [ValidateSet('Open', 'Closed')] [string] $INVITED_CAN_JOIN_TranslatesTo, [Parameter()] [ValidateSet('Open', 'Closed')] [string] $CAN_REQUEST_TO_JOIN_TranslatesTo, [Parameter()] [ValidateSet('MemberJoinRestrictionTo_Closed', 'MemberJoinRestrictionTo_ApprovalRequired', 'MemberJoinRestrictionTo_Open')] [string] $NONE_CAN_ADD_members_Overrides ) Begin { } Process { ForEach ($CurGroup in $Group) { $Alias = ($CurGroup.Email -split "@")[0] # Managers and Owners $ManagedBy = [System.Collections.Generic.HashSet[string]]::new() if (-not $DontAddManagersToManagedBy -and -not [string]::IsNullOrWhiteSpace($CurGroup.Managers)) { $CurGroup.Managers -split "`r`n" | ForEach-Object { $ManagedBy.Add($_) > $null } } if (-not $DontAddOwnersToManagedBy -and -not [string]::IsNullOrWhiteSpace($CurGroup.Owners)) { $CurGroup.Owners -split "`r`n" | ForEach-Object { $ManagedBy.Add($_) > $null } } # whoCanJoin $MemberJoinRestriction = switch ($CurGroup.whoCanJoin) { 'ALL_IN_DOMAIN_CAN_JOIN' { 'Open' } 'ANYONE_CAN_JOIN' { 'Open' } 'CAN_REQUEST_TO_JOIN' { if ($CAN_REQUEST_TO_JOIN_TranslatesTo) { $CAN_REQUEST_TO_JOIN_TranslatesTo } else { 'ApprovalRequired' } } 'INVITED_CAN_JOIN' { if ($INVITED_CAN_JOIN_TranslatesTo) { $INVITED_CAN_JOIN_TranslatesTo } else { 'ApprovalRequired' } } } # When "whoCanAdd" is "NONE_CAN_ADD" this overrides any "MemberJoinRestriction" if ($NONE_CAN_ADD_members_Overrides) { $MemberJoinRestriction = switch ($NONE_CAN_ADD_members_Overrides) { 'MemberJoinRestrictionTo_Closed' { 'Closed' } 'MemberJoinRestrictionTo_ApprovalRequired' { 'ApprovalRequired' } 'MemberJoinRestrictionTo_Open' { 'Open' } } } # whoCanLeave $MemberDepartRestriction = switch ($CurGroup.whoCanLeaveGroup) { 'ALL_MEMBERS_CAN_LEAVE' { 'Open' } 'ALL_MANAGERS_CAN_LEAVE' { 'Closed' } 'NONE_CAN_LEAVE' { 'Closed' } Default { 'Open' } } $NewHash = @{ Name = $CurGroup.Name DisplayName = $CurGroup.Name Alias = $Alias ManagedBy = $ManagedBy PrimarySmtpAddress = $CurGroup.Email MemberJoinRestriction = $MemberJoinRestriction MemberDepartRestriction = $MemberDepartRestriction Notes = $CurGroup.Description } # Are Owners and/or Managers copied to the Group's Membership? if ($DontCopyManagedByToMember) { $NewHash['CopyOwnerToMember'] = $false } else { $NewHash['CopyOwnerToMember'] = $true } $SetHash = @{ Identity = $CurGroup.Email } if ($CurGroup.includeInGlobalAddressList) { $SetHash['HiddenFromAddressListsEnabled'] = -not [bool]::Parse($CurGroup.includeInGlobalAddressList) } # messageModerationLevel (A moderator approves messages sent to recipient before delivered) switch ($CurGroup.messageModerationLevel) { 'MODERATE_NONE' {$SetHash['ModerationEnabled'] = $false} 'MODERATE_ALL_MESSAGES' {$SetHash['ModerationEnabled'] = $true} 'MODERATE_NON_MEMBERS' { $SetHash['ModerationEnabled'] = $true $SetHash['BypassModerationFromSendersOrMembers'] = $CurGroup.Email } } switch ($CurGroup.sendMessageDenyNotification) { 'TRUE' {$SetHash['SendModerationNotifications'] = 'ALWAYS'} 'FALSE' {$SetHash['SendModerationNotifications'] = 'NEVER'} Default {$SetHash['SendModerationNotifications'] = 'NEVER'} } # whoCanPostMessage (who can email the DL) switch ($CurGroup.whoCanPostMessage) { 'ANYONE_CAN_POST' { $SetHash['RequireSenderAuthenticationEnabled'] = $false } 'ALL_IN_DOMAIN_CAN_POST' { $SetHash['RequireSenderAuthenticationEnabled'] = $true } 'ALL_MANAGERS_CAN_POST' { $SetHash['RequireSenderAuthenticationEnabled'] = $true $SetHash['AcceptMessagesOnlyFromSendersOrMembers'] = $ManagedBy } 'ALL_MEMBERS_CAN_POST' { $SetHash['RequireSenderAuthenticationEnabled'] = $true $SetHash['AcceptMessagesOnlyFromSendersOrMembers'] = $CurGroup.Email } } # Create a splat with only parameters with values for New-DistributionGroup $NewSplat = @{} ForEach ($Key in $NewHash.keys) { if ($NewHash.item($Key) -ne $null) { $NewSplat.add($Key, $($NewHash.item($Key))) } } # Create a splat with only parameters with values for Set-DistributionGroup $SetSplat = @{} ForEach ($Key in $SetHash.keys) { if ($SetHash.item($Key) -ne $null) { $SetSplat.add($Key, $($SetHash.item($Key))) } } try { $NewDL = New-DistributionGroup @NewSplat -ErrorAction Stop [PSCustomObject]@{ Time = (Get-Date).ToString("yyyy/MM/dd HH:mm:ss") Result = 'SUCCESS' Action = 'CREATING' Object = 'GROUP' Name = $CurGroup.Name Email = $CurGroup.Email Message = 'SUCCESS' ExtendedMessage = 'SUCCESS' } | Export-Csv -Path $LogPath -NoTypeInformation -Append Write-HostLog -Message "Creating`t$($NewDL.Name)`t$($NewDL.PrimarySmtpAddress)" -Status "Success" try { Set-DistributionGroup @SetSplat -ErrorAction Stop -WarningAction SilentlyContinue [PSCustomObject]@{ Time = (Get-Date).ToString("yyyy/MM/dd HH:mm:ss") Result = 'SUCCESS' Action = 'SETTING' Object = 'GROUP' Name = $CurGroup.Name Email = $CurGroup.Email Message = 'SUCCESS' ExtendedMessage = 'SUCCESS' } | Export-Csv -Path $LogPath -NoTypeInformation -Append Write-HostLog -Message "Setting`t$($NewDL.Name)`t$($NewDL.PrimarySmtpAddress)" -Status "Success" } catch { $Failure = $_.CategoryInfo.Reason [PSCustomObject]@{ Time = (Get-Date).ToString("yyyy/MM/dd HH:mm:ss") Result = 'FAILURE' Action = 'SETTING' Object = 'GROUP' Name = $CurGroup.Name Email = $CurGroup.Email Message = $Failure ExtendedMessage = $_.Exception.Message } | Export-Csv -Path $LogPath -NoTypeInformation -Append Write-HostLog -Message "Setting`t$($NewDL.Name)`t$($NewDL.PrimarySmtpAddress)" -Status "Failed" } } catch { $Failure = $_.CategoryInfo.Reason if ($_ -match 'The email address') { $Failure = "The email address $($CurGroup.Email) isn't correct" } if ($_ -match 'is already managed by recipient') { $Failure = 'DL already managed by recipient' } [PSCustomObject]@{ Time = (Get-Date).ToString("yyyy/MM/dd HH:mm:ss") Result = 'FAILURE' Action = 'CREATING' Object = 'GROUP' Name = $CurGroup.Name Email = $CurGroup.Email Message = $Failure ExtendedMessage = $_.Exception.Message } | Export-Csv -Path $LogPath -NoTypeInformation -Append Write-HostLog -Message "Creating`t$($CurGroup.Name)`t$Failure" -Status "Failed" } } } End { } } |