|
| 1 | +function Invoke-CIPPStandardGlobalQuarantineSettings { |
| 2 | + <# |
| 3 | + .FUNCTIONALITY |
| 4 | + Internal |
| 5 | + .COMPONENT |
| 6 | + (APIName) GlobalQuarantineSettings |
| 7 | + .SYNOPSIS |
| 8 | + (Label) Configure Global Quarantine Notification Settings |
| 9 | + .DESCRIPTION |
| 10 | + (Helptext) Configures the Global Quarantine Policy settings including sender name, custom subject, disclaimer, from address, org branding, and notification frequency. |
| 11 | + (DocsDescription) Configures the full set of Global Quarantine Policy settings for the tenant. This includes the quarantine notification sender display name, custom subject line, disclaimer text, the from address used for notifications, whether to use org branding, and how often notifications are sent to end users. |
| 12 | + .NOTES |
| 13 | + CAT |
| 14 | + Exchange Standards |
| 15 | + TAG |
| 16 | + ADDEDCOMPONENT |
| 17 | + {"type":"textField","name":"standards.GlobalQuarantineSettings.SenderName","label":"Sender Display Name (e.g. Office365Alerts)","required":false} |
| 18 | + {"type":"textField","name":"standards.GlobalQuarantineSettings.CustomSubject","label":"Subject","required":false} |
| 19 | + {"type":"textField","name":"standards.GlobalQuarantineSettings.CustomDisclaimer","label":"Disclaimer (Max 200 characters)","required":false} |
| 20 | + {"type":"textField","name":"standards.GlobalQuarantineSettings.FromAddress","label":"Specify Sender Address (must be an internal mailbox, e.g. security@contoso.com)","required":false} |
| 21 | + {"type":"switch","name":"standards.GlobalQuarantineSettings.OrganizationBrandingEnabled","label":"Use Organization Branding (logo)"} |
| 22 | + IMPACT |
| 23 | + Low Impact |
| 24 | + ADDEDDATE |
| 25 | + 2026-04-03 |
| 26 | + POWERSHELLEQUIVALENT |
| 27 | + Set-QuarantinePolicy (GlobalQuarantinePolicy) |
| 28 | + RECOMMENDEDBY |
| 29 | + UPDATECOMMENTBLOCK |
| 30 | + Run the Tools\Update-StandardsComments.ps1 script to update this comment block |
| 31 | + .LINK |
| 32 | + https://docs.cipp.app/user-documentation/tenant/standards/list-standards |
| 33 | + #> |
| 34 | + param($Tenant, $Settings) |
| 35 | + $TestResult = Test-CIPPStandardLicense -StandardName 'QuarantineTemplate' -TenantFilter $Tenant -RequiredCapabilities @('EXCHANGE_S_STANDARD', 'EXCHANGE_S_ENTERPRISE', 'EXCHANGE_S_STANDARD_GOV', 'EXCHANGE_S_ENTERPRISE_GOV', 'EXCHANGE_LITE') #No Foundation because that does not allow powershell access |
| 36 | + |
| 37 | + if ($TestResult -eq $false) { |
| 38 | + return $true |
| 39 | + } #we're done. |
| 40 | + |
| 41 | + try { |
| 42 | + $CurrentState = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-QuarantinePolicy' -cmdParams @{ QuarantinePolicyType = 'GlobalQuarantinePolicy' } | |
| 43 | + Select-Object -ExcludeProperty '*data.type' |
| 44 | + } catch { |
| 45 | + $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message |
| 46 | + Write-LogMessage -API 'Standards' -Tenant $Tenant -Message "Could not get the GlobalQuarantineSettings state for $Tenant. Error: $ErrorMessage" -Sev Error |
| 47 | + return |
| 48 | + } |
| 49 | + |
| 50 | + $SenderName = $Settings.SenderName |
| 51 | + $CustomSubject = $Settings.CustomSubject |
| 52 | + $CustomDisclaimer = $Settings.CustomDisclaimer |
| 53 | + $FromAddress = $Settings.FromAddress |
| 54 | + $UseOrgBranding = [bool]$Settings.OrganizationBrandingEnabled |
| 55 | + |
| 56 | + $ExistingLanguages = if ($CurrentState.MultiLanguageSetting -and $CurrentState.MultiLanguageSetting.Count -gt 0) { |
| 57 | + $CurrentState.MultiLanguageSetting |
| 58 | + } else { |
| 59 | + @('Default') |
| 60 | + } |
| 61 | + $LangCount = $ExistingLanguages.Count |
| 62 | + $SenderNames = 1..$LangCount | ForEach-Object { $SenderName } |
| 63 | + $Subjects = 1..$LangCount | ForEach-Object { $CustomSubject } |
| 64 | + $Disclaimers = 1..$LangCount | ForEach-Object { $CustomDisclaimer } |
| 65 | + |
| 66 | + $StateIsCorrect = ( |
| 67 | + ($CurrentState.MultiLanguageSenderName -contains $SenderName) -and |
| 68 | + ($CurrentState.ESNCustomSubject -contains $CustomSubject) -and |
| 69 | + ($CurrentState.MultiLanguageCustomDisclaimer -contains $CustomDisclaimer) -and |
| 70 | + ($CurrentState.EndUserSpamNotificationCustomFromAddress -eq $FromAddress) -and |
| 71 | + ($CurrentState.OrganizationBrandingEnabled -eq $UseOrgBranding) |
| 72 | + ) |
| 73 | + |
| 74 | + if ($Settings.remediate -eq $true) { |
| 75 | + if ($StateIsCorrect) { |
| 76 | + Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Global Quarantine Settings are already configured correctly.' -sev Info |
| 77 | + } else { |
| 78 | + try { |
| 79 | + $Params = @{ |
| 80 | + MultiLanguageSetting = $ExistingLanguages |
| 81 | + MultiLanguageSenderName = $SenderNames |
| 82 | + ESNCustomSubject = $Subjects |
| 83 | + MultiLanguageCustomDisclaimer = $Disclaimers |
| 84 | + EndUserSpamNotificationCustomFromAddress = $FromAddress |
| 85 | + OrganizationBrandingEnabled = $UseOrgBranding |
| 86 | + } |
| 87 | + |
| 88 | + if ($CurrentState.Name -eq 'DefaultGlobalPolicy') { |
| 89 | + $Params['Name'] = 'DefaultGlobalTag' |
| 90 | + $Params['QuarantinePolicyType'] = 'GlobalQuarantinePolicy' |
| 91 | + $null = New-ExoRequest -tenantid $Tenant -cmdlet 'New-QuarantinePolicy' -cmdParams $Params |
| 92 | + } else { |
| 93 | + $Params['Identity'] = $CurrentState.Identity |
| 94 | + $null = New-ExoRequest -tenantid $Tenant -cmdlet 'Set-QuarantinePolicy' -cmdParams $Params |
| 95 | + } |
| 96 | + |
| 97 | + Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Successfully configured Global Quarantine Settings.' -sev Info |
| 98 | + } catch { |
| 99 | + $ErrorMessage = Get-CippException -Exception $_ |
| 100 | + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to configure Global Quarantine Settings. Error: $($ErrorMessage.NormalizedError)" -sev Error -LogData $ErrorMessage |
| 101 | + } |
| 102 | + } |
| 103 | + } |
| 104 | + |
| 105 | + if ($Settings.alert -eq $true) { |
| 106 | + if ($StateIsCorrect) { |
| 107 | + Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Global Quarantine Settings are configured correctly.' -sev Info |
| 108 | + } else { |
| 109 | + Write-StandardsAlert -message 'Global Quarantine Settings do not match the desired configuration.' -object $CurrentState -tenant $Tenant -standardName 'GlobalQuarantineSettings' -standardId $Settings.standardId |
| 110 | + Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Global Quarantine Settings do not match the desired configuration.' -sev Info |
| 111 | + } |
| 112 | + } |
| 113 | + |
| 114 | + if ($Settings.report -eq $true) { |
| 115 | + $CurrentValue = @{ |
| 116 | + MultiLanguageSenderName = $CurrentState.MultiLanguageSenderName |
| 117 | + ESNCustomSubject = $CurrentState.ESNCustomSubject |
| 118 | + MultiLanguageCustomDisclaimer = $CurrentState.MultiLanguageCustomDisclaimer |
| 119 | + EndUserSpamNotificationCustomFromAddress = $CurrentState.EndUserSpamNotificationCustomFromAddress |
| 120 | + OrganizationBrandingEnabled = $CurrentState.OrganizationBrandingEnabled |
| 121 | + } |
| 122 | + $ExpectedValue = @{ |
| 123 | + MultiLanguageSenderName = @($SenderName) |
| 124 | + ESNCustomSubject = @($CustomSubject) |
| 125 | + MultiLanguageCustomDisclaimer = @($CustomDisclaimer) |
| 126 | + EndUserSpamNotificationCustomFromAddress = $FromAddress |
| 127 | + OrganizationBrandingEnabled = $UseOrgBranding |
| 128 | + } |
| 129 | + |
| 130 | + Set-CIPPStandardsCompareField -FieldName 'standards.GlobalQuarantineSettings' -CurrentValue $CurrentValue -ExpectedValue $ExpectedValue -TenantFilter $Tenant |
| 131 | + Add-CIPPBPAField -FieldName 'GlobalQuarantineSettingsConfigured' -FieldValue $StateIsCorrect -StoreAs bool -Tenant $Tenant |
| 132 | + } |
| 133 | +} |
0 commit comments