Public/Configuration/Baseline/Add-EOPPolicies.ps1

function Add-EOPPolicies {
    param(
        [Parameter(Mandatory)]
        [string]$TenantId
    )

    try {
        Connect-CustomerExchange -CustomerTenantId $TenantId

        # Quarantine Policies and notifications
        $QuarantinePolicies = Get-QuarantinePolicy
        $QuarantinePolicyFiles = Get-ChildItem -Path "$script:ModuleRoot\Public\Configuration\Baseline\EOPPolicies\QuarantinePolicies" -Filter *.json
        foreach($QuarantinePolicyFile in $QuarantinePolicyFiles) {
            $QuarantinePolicy = Get-Content -Path $QuarantinePolicyFile.FullName | ConvertFrom-Json -Depth 100 -AsHashtable
            if($QuarantinePolicies.Identity -contains $QuarantinePolicy.Name) {
                Write-ModuleLog -Message "Quarantine policy '$($QuarantinePolicy.Name)' already exists, not creating.." -Level Info -Component 'EOPPolicies'
            }
            else {
                # If "DefaultGlobalTag" (used for global settings)
                if($QuarantinePolicyFile.BaseName -eq "GlobalQuarantinePolicy") {
                    $DefaultDomainName = Get-AcceptedDomain | Where-Object { $_.Default -eq $true } | Select-Object -ExpandProperty DomainName
                    $QuarantinePolicy.EndUserSpamNotificationCustomFromAddress = "quarantine@$($DefaultDomainName)"
                    # Force create global policy if hasn't been updated manually
                    $GlobalQuarantinePolicy = New-QuarantinePolicy -QuarantinePolicyType GlobalQuarantineTag -Name "DefaultGlobalTag" -ErrorAction SilentlyContinue

                    $GlobalQuarantinePolicy = Get-QuarantinePolicy -QuarantinePolicyType GlobalQuarantinePolicy
                    $GlobalQuarantinePolicy | Set-QuarantinePolicy @QuarantinePolicy
                    Write-ModuleLog -Message "Updated global quarantine policy." -Level Info -Component 'EOPPolicies'
                } else {
                    # Parse the quarantine permissions
                    $RegexMatches = [regex]::Matches($QuarantinePolicy.EndUserQuarantinePermissions, '\b(\w+)\s*:\s*(\w+)\b')
                    $QuarantinePermissions = @{}
                    foreach ($match in $RegexMatches) {
                        $key = $match.Groups[1].Value.TrimStart('n')
                        $value = if ($match.Groups[2].Value -eq "True") { $true } else { $false }
                        $QuarantinePermissions[$key] = $value
                    }              
                    $QuarantinePolicy.EndUserQuarantinePermissions = New-QuarantinePermissions @QuarantinePermissions
                    $QuarantinePolicy = New-QuarantinePolicy @QuarantinePolicy
                    Write-ModuleLog -Message "Created quarantine policy '$($QuarantinePolicy.Name)'" -Level Info -Component 'EOPPolicies'
                }
            }
        }

        # Anti-phishing policies
        $AntiPhishingPolicies = Get-AntiPhishPolicy 
        $AntiPhishingPolicyFiles = Get-ChildItem -Path "$script:ModuleRoot\Public\Configuration\Baseline\EOPPolicies\AntiPhishingPolicies" -Filter *.json
        foreach($AntiPhishingPolicyFile in $AntiPhishingPolicyFiles) {
            $AntiPhishingPolicy = Get-Content -Path $AntiPhishingPolicyFile.FullName | ConvertFrom-Json -Depth 100 -AsHashtable
            if($AntiPhishingPolicies.Identity -contains $AntiPhishingPolicy.Name) {
                Write-Host "Anti-phishing policy '$($AntiPhishingPolicy.Name)' already exists, not creating.." -ForegroundColor Yellow
            }
            else {
                $ValidParameters = (Get-Command New-AntiPhishPolicy).Parameters.Keys
                # Filter out parameters that are not valid for New-AntiPhishPolicy using a foreach loop returning an orderedhashtable with only valid parameters
                $ValidAntiPhishingPolicy = [ordered]@{}
                foreach ($key in $AntiPhishingPolicy.Keys) {
                    if ($ValidParameters -contains $key) {
                        $ValidAntiPhishingPolicy[$key] = $AntiPhishingPolicy[$key]
                    }
                }
                $AntiPhishingPolicy = New-AntiPhishPolicy @ValidAntiPhishingPolicy
                Write-ModuleLog -Message "Created anti-phishing policy '$($AntiPhishingPolicy.Name)'" -Level Info -Component 'EOPPolicies'
            }
        }

        # Anti-spam (inbound) policies
        $AntiSpamInboundPolicies = Get-HostedContentFilterPolicy
        $AntiSpamInboundPolicyFiles = Get-ChildItem -Path "$script:ModuleRoot\Public\Configuration\Baseline\EOPPolicies\AntiSpamInboundPolicies" -Filter *.json

        foreach($AntiSpamInboundPolicyFile in $AntiSpamInboundPolicyFiles) {
            $AntiSpamInboundPolicy = Get-Content -Path $AntiSpamInboundPolicyFile.FullName | ConvertFrom-Json -Depth 100 -AsHashtable
            if($AntiSpamInboundPolicies.Identity -contains $AntiSpamInboundPolicy.Name) {
                Write-Host "Anti-spam (inbound) policy '$($AntiSpamInboundPolicy.Name)' already exists, not creating.." -ForegroundColor Yellow
            }
            else {
                $AntiSpamInboundPolicy = New-HostedContentFilterPolicy @AntiSpamInboundPolicy
                $AntiSpamInboundPolicy | Set-HostedContentFilterPolicy -MakeDefault:$true
                Write-Host "Created anti-spam (inbound) policy '$($AntiSpamInboundPolicy.Name)'." -ForegroundColor Green
            }
        }

        # Anti-spam (outbound) policies
        $AntiSpamOutboundPolicies = Get-HostedOutboundSpamFilterPolicy
        $AntiSpamOutboundPolicyFiles = Get-ChildItem -Path "$script:ModuleRoot\Public\Configuration\Baseline\EOPPolicies\AntiSpamOutboundPolicies" -Filter *.json

        foreach($AntiSpamOutboundPolicyFile in $AntiSpamOutboundPolicyFiles) {
            $AntiSpamOutboundPolicy = Get-Content -Path $AntiSpamOutboundPolicyFile.FullName | ConvertFrom-Json -Depth 100 -AsHashtable
            if($AntiSpamOutboundPolicies.Identity -contains $AntiSpamOutboundPolicy.Name) {
                Write-ModuleLog -Message "Anti-spam (outbound) policy '$($AntiSpamOutboundPolicy.Name)' already exists, not creating.." -Level Info -Component 'EOPPolicies'
            }
            else {
                # New can't be created, does not work correctly. Have to edit the default one.
                $DefaultAntiSpamOutboundPolicy = Get-HostedOutboundSpamFilterPolicy -Identity "Default"
                $DefaultAntiSpamOutboundPolicy | Set-HostedOutboundSpamFilterPolicy @AntiSpamOutboundPolicy
                Write-ModuleLog -Message "Modified default anti-spam (outbound) policy '$($DefaultAntiSpamOutboundPolicy.Name)'" -Level Info -Component 'EOPPolicies'
            }
        }

        # Safe links policies
        if(Get-Command "Get-SafeLinksPolicy" -ErrorAction SilentlyContinue)
        {
            $SafeLinksPolicies = Get-SafeLinksPolicy
            $SafeLinksPolicyFiles = Get-ChildItem -Path "$script:ModuleRoot\Public\Configuration\Baseline\EOPPolicies\SafeLinksPolicies" -Filter *.json
            foreach($SafeLinksPolicyFile in $SafeLinksPolicyFiles) {
                $SafeLinksPolicy = Get-Content -Path $SafeLinksPolicyFile.FullName | ConvertFrom-Json -Depth 100 -AsHashtable
                if($SafeLinksPolicies.Identity -contains $SafeLinksPolicy.Name) {
                    Write-ModuleLog -Message "Safe links policy '$($SafeLinksPolicy.Name)' already exists, not creating.." -Level Info -Component 'EOPPolicies'
                }
                else {
                    $SafeLinksPolicy = New-SafeLinksPolicy @SafeLinksPolicy
                    Write-Host "Created safe links policy '$($SafeLinksPolicy.Name)'." -ForegroundColor Green
                    $AcceptedDomains = Get-AcceptedDomain
                    $SafeLinksRule = New-SafeLinksRule -Name $SafeLinksPolicy.Name -SafeLinksPolicy $SafeLinksPolicy.Name -RecipientDomainIs $AcceptedDomains.DomainName
                    Write-ModuleLog -Message "Added all accepted domains to Safe Links Rule." -Level Info -Component 'EOPPolicies'
                }
            }
        }
        # Safe attachments policies
        if(Get-Command "Get-SafeAttachmentPolicy" -ErrorAction SilentlyContinue)
        {
            $SafeAttachmentsPolicies = Get-SafeAttachmentPolicy
            $SafeAttachmentsPolicyFiles = Get-ChildItem -Path "$script:ModuleRoot\Public\Configuration\Baseline\EOPPolicies\SafeAttachmentsPolicies" -Filter *.json
            foreach($SafeAttachmentsPolicyFile in $SafeAttachmentsPolicyFiles) {
                $SafeAttachmentsPolicy = Get-Content -Path $SafeAttachmentsPolicyFile.FullName | ConvertFrom-Json -Depth 100 -AsHashtable
                if($SafeAttachmentsPolicies.Identity -contains $SafeAttachmentsPolicy.Name) {
                    Write-ModuleLog -Message "Safe attachments policy '$($SafeAttachmentsPolicy.Name)' already exists, not creating.." -Level Info -Component 'EOPPolicies'
                }
                else {
                    $SafeAttachmentsPolicy = New-SafeAttachmentPolicy @SafeAttachmentsPolicy
                    Write-ModuleLog "Created safe attachments policy '$($SafeAttachmentsPolicy.Name)'" -Level Info -Component 'EOPPolicies'
                    $AcceptedDomains = Get-AcceptedDomain
                    $SafeAttachmentsRule = New-SafeAttachmentRule -Name $SafeAttachmentsPolicy.Name -SafeAttachmentPolicy $SafeAttachmentsPolicy.Name -RecipientDomainIs $AcceptedDomains.DomainName
                }
            }
        }
    }
    catch {
        Write-ModuleLog -Message "Failed to create Exchange Online Protection (EOP) policies" -Level Error -ErrorRecord $_ -Component 'EOPPolicies'
    }
}