SendGridTools.psm1

#Region '.\Classes\SGCustom.ps1' 0
class UnixTime {
    [datetime]$DateTime
    [int]$UnixTimestamp

    static [datetime]EpochStart() {
        return ([datetime]::new(1970, 1, 1, 0, 0, 0, ([DateTimeKind]::Utc)))
    }
    
    static [datetime] FromUnixTime([int]$UnixTimestamp) {
        return [datetime]::new(1970, 1, 1, 0, 0, 0, 0).AddSeconds($UnixTimestamp)
    }

    static [int64] FromDateTime([datetime]$DateTime) {
        return [int64]([datetime]$DateTime - ([UnixTime]::EpochStart())).TotalSeconds
    }

    UnixTime () {
        $this.DateTime = Get-Date
        $this.UnixTimestamp = $this.ToUnixTime()
    }
    UnixTime([datetime]$DateTime) {
        $this.DateTime = $DateTime
        $this.UnixTimestamp = $this.ToUnixTime()
        #$EpochStart = [datetime]::new(1970, 1, 1, 0, 0, 0, ([DateTimeKind]::Utc))
        #$EpochStart = [UnixTime]::EpochStart()
        #$this.UnixTimestamp = [int]([datetime]$DateTime - $EpochStart).TotalSeconds
        
    }
    
    UnixTime([int]$UnixTimestamp) {
        $this.UnixTimestamp = $UnixTimestamp
        $this.DateTime = $this.ToDateTime()
    }

    UnixTime([string]$DateTimeString) {
        $this.DateTime = [datetime]::Parse($DateTimeString)
        $this.UnixTimestamp = $this.ToUnixTime()
    }

    [datetime] ToDateTime() {
        return [datetime]::new(1970, 1, 1, 0, 0, 0, 0).AddSeconds($this.UnixTimestamp)
    }

    [datetime] ToDateTimeUTC() {
        return ([UnixTime]::EpochStart()).AddSeconds($this.UnixTimestamp)
    }

    [int] ToUnixTime() {
        $EpochStart = [UnixTime]::EpochStart()
        return [int]([datetime]$this.DateTime - $EpochStart).TotalSeconds
    }

    [string] ToSendGridTime() {
        return ([datetime]::new(1970, 1, 1, 0, 0, 0, 0).AddSeconds($this.UnixTimestamp)).ToString('yyyy-MM-dd')
    }

    [string] ToString() {
        return $this.UnixTimestamp.ToString()
    }
}
class SGASM {
    [int]$GroupId
    [int[]]$GroupsToDisplay

    SGASM() {
        $this.GroupId = 0
        $this.GroupsToDisplay = @()
    }

    SGASM([int]$GroupId) {
        $this.GroupId = $GroupId
        $this.GroupsToDisplay = @()
    }
    SGASM([int]$GroupId, [int[]]$GroupsToDisplay) {
        $this.GroupId = $GroupId
        $this.GroupsToDisplay = @()
    }
    [string] ToString() {
        return $this.GroupId.ToString()
    }
}
#EndRegion '.\Classes\SGCustom.ps1' 82
#Region '.\Classes\SGScopes.ps1' 0
class SendGridScopes : System.Management.Automation.IValidateSetValuesGenerator {
    [string[]]$Scopes

    SendGridScopes () {
    }
    
    SendGridScopes ([string[]]$Scopes) {
        $this.ValidateScopes($Scopes)
    }
    
    hidden [void] ValidateScopes([string[]]$Scopes) {
        $InvalidScopes = $Scopes | Where-Object { $_ -notin $this.GetValidValues() }
        if ($InvalidScopes) {
            throw "Invalid scope(s): $($invalidScopes -join ', ')"
        }
        $this.Scopes = $Scopes
    }

    static [string[]] ValidScopes() {
        return [string[]]@('access_settings.activity.read',
            'access_settings.whitelist.create',
            'access_settings.whitelist.delete',
            'access_settings.whitelist.read',
            'access_settings.whitelist.update',
            'alerts.create',
            'alerts.delete',
            'alerts.read',
            'alerts.update',
            'api_keys.create',
            'api_keys.delete',
            'api_keys.read',
            'api_keys.update',
            'asm.groups.create',
            'asm.groups.delete',
            'asm.groups.read',
            'asm.groups.update',
            'billing.create',
            'billing.delete',
            'billing.read',
            'billing.update',
            'browsers.stats.read',
            'categories.create',
            'categories.delete',
            'categories.read',
            'categories.stats.read',
            'categories.stats.sums.read',
            'categories.update',
            'clients.desktop.stats.read',
            'clients.phone.stats.read',
            'clients.stats.read',
            'clients.tablet.stats.read',
            'clients.webmail.stats.read',
            'devices.stats.read',
            'email_activity.read',
            'geo.stats.read',
            'ips.assigned.read',
            'ips.pools.create',
            'ips.pools.delete',
            'ips.pools.ips.create',
            'ips.pools.ips.delete',
            'ips.pools.ips.read',
            'ips.pools.ips.update',
            'ips.pools.read',
            'ips.pools.update',
            'ips.read',
            'ips.warmup.create',
            'ips.warmup.delete',
            'ips.warmup.read',
            'ips.warmup.update',
            'mail_settings.address_whitelist.read',
            'mail_settings.address_whitelist.update',
            'mail_settings.bounce_purge.read',
            'mail_settings.bounce_purge.update',
            'mail_settings.footer.read',
            'mail_settings.footer.update',
            'mail_settings.forward_bounce.read',
            'mail_settings.forward_bounce.update',
            'mail_settings.forward_spam.read',
            'mail_settings.forward_spam.update',
            'mail_settings.plain_content.read',
            'mail_settings.plain_content.update',
            'mail_settings.read,',
            'mail_settings.template.read',
            'mail_settings.template.update',
            'mail.batch.create',
            'mail.batch.delete',
            'mail.batch.read',
            'mail.batch.update',
            'mail.send',
            'mailbox_providers.stats.read',
            'marketing_campaigns.create',
            'marketing_campaigns.delete',
            'marketing_campaigns.read',
            'marketing_campaigns.update',
            'partner_settings.new_relic.read',
            'partner_settings.new_relic.update',
            'partner_settings.read',
            'stats.global.read',
            'stats.read',
            'subusers.create',
            'subusers.credits.create',
            'subusers.credits.delete',
            'subusers.credits.read',
            'subusers.credits.remaining.create',
            'subusers.credits.remaining.delete',
            'subusers.credits.remaining.read',
            'subusers.credits.remaining.update',
            'subusers.credits.update',
            'subusers.delete',
            'subusers.monitor.create',
            'subusers.monitor.delete',
            'subusers.monitor.read',
            'subusers.monitor.update',
            'subusers.read',
            'subusers.reputations.read',
            'subusers.stats.monthly.read',
            'subusers.stats.read',
            'subusers.stats.sums.read',
            'subusers.summary.read',
            'subusers.update',
            'suppression.blocks.create',
            'suppression.blocks.delete',
            'suppression.blocks.read',
            'suppression.blocks.update',
            'suppression.bounces.create',
            'suppression.bounces.delete',
            'suppression.bounces.read',
            'suppression.bounces.update',
            'suppression.create',
            'suppression.delete',
            'suppression.invalid_emails.create',
            'suppression.invalid_emails.delete',
            'suppression.invalid_emails.read',
            'suppression.invalid_emails.update',
            'suppression.read',
            'suppression.spam_reports.create',
            'suppression.spam_reports.delete',
            'suppression.spam_reports.read',
            'suppression.spam_reports.update',
            'suppression.unsubscribes.create',
            'suppression.unsubscribes.delete',
            'suppression.unsubscribes.read',
            'suppression.unsubscribes.update',
            'suppression.update',
            'teammates.create',
            'teammates.read',
            'teammates.update',
            'teammates.delete',
            'templates.create',
            'templates.delete',
            'templates.read',
            'templates.update',
            'templates.versions.activate.create',
            'templates.versions.activate.delete',
            'templates.versions.activate.read',
            'templates.versions.activate.update',
            'templates.versions.create',
            'templates.versions.delete',
            'templates.versions.read',
            'templates.versions.update',
            'tracking_settings.click.read',
            'tracking_settings.click.update',
            'tracking_settings.google_analytics.read',
            'tracking_settings.google_analytics.update',
            'tracking_settings.open.read',
            'tracking_settings.open.update',
            'tracking_settings.read',
            'tracking_settings.subscription.read',
            'tracking_settings.subscription.update',
            'user.account.read',
            'user.credits.read',
            'user.email.create',
            'user.email.delete',
            'user.email.read',
            'user.email.update',
            'user.multifactor_authentication.create',
            'user.multifactor_authentication.delete',
            'user.multifactor_authentication.read',
            'user.multifactor_authentication.update',
            'user.password.read',
            'user.password.update',
            'user.profile.read',
            'user.profile.update',
            'user.scheduled_sends.create',
            'user.scheduled_sends.delete',
            'user.scheduled_sends.read',
            'user.scheduled_sends.update',
            'user.settings.enforced_tls.read',
            'user.settings.enforced_tls.update',
            'user.timezone.read',
            'user.username.read',
            'user.username.update',
            'user.webhooks.event.settings.read',
            'user.webhooks.event.settings.update',
            'user.webhooks.event.test.create',
            'user.webhooks.event.test.read',
            'user.webhooks.event.test.update',
            'user.webhooks.parse.settings.create',
            'user.webhooks.parse.settings.delete',
            'user.webhooks.parse.settings.read',
            'user.webhooks.parse.settings.update',
            'user.webhooks.parse.stats.read',
            'whitelabel.create',
            'whitelabel.delete',
            'whitelabel.read',
            'whitelabel.update')
    }

    [string[]] GetValidValues() {
        return [SendGridScopes]::ValidScopes()
    }
}
#EndRegion '.\Classes\SGScopes.ps1' 213
#Region '.\Classes\SGSession.ps1' 0
# The SendGridSession class manages a SendGrid session for the user.
class SendGridSession {
    # URL endpoint to the SendGrid API.
    [uri]$EndpointURL
    # Base URL to the SendGrid API.
    hidden [uri]$_BaseURL = 'https://api.sendgrid.com/v3'
    # Specifies if the session is connected.
    hidden [bool]$_Connected = $false
    # Stores the user's SendGrid API credentials.
    hidden [PSCredential]$_Credential
    # Tracks the time when the session was created.
    hidden [DateTime]$_CreateDateTime

    # Constructor function for SendGridSession.
    SendGridSession () {
        $null = [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
    }
    
    <#
    .SYNOPSIS
        Constructs the URL for accessing the SendGrid API.
 
    .DESCRIPTION
        This private method builds a URL for accessing a specific resource in the SendGrid API.
 
    .PARAMETER Resource
        The specific resource to access in the SendGrid API.
    #>

    hidden [void]BuildEndpointURL([string]$Resource) {
        if ($null -eq $Resource -or $Resource -eq [String]::Empty) {
            # Remove old Endpoint URL to avoid old resource
            $this.EndpointURL = $null
        }
        else {
            [Text.StringBuilder]$URLBuild = [Text.StringBuilder]::new()
        
            $null = $URLBuild.Append($this._BaseURL)
            $null = $URLBuild.Append('/')
            $null = $URLBuild.Append($Resource)

            $this.EndpointURL = [uri]$URLBuild.ToString()
        }
    }

    <#
    .SYNOPSIS
        Connects to the SendGrid API.
 
    .DESCRIPTION
        This function establishes a connection to the SendGrid API by using the user's stored credentials.
    #>

    [void] Connect () {
        $SessionLifeTime = (Get-Date).AddHours(-1)
        if ($null -eq $this._CreateDateTime -or $SessionLifeTime -gt $this._CreateDateTime) {
            $this.Disconnect()
            throw 'Session lifetime exceeded, reconnect.'
        }
        if ($this._Credential -is [PSCredential]) {
            $this.BuildEndpointURL([string]'scopes')
            try {
                $Headers = @{
                    'Authorization' = ('Bearer {0}' -f $this._Credential.GetNetworkCredential().Password)
                    'Content-Type'  = 'application/json'
                }
                $null = Invoke-RestMethod -Method Get -Uri  $this.EndpointURL -Headers $Headers -ErrorAction Stop
                $this._Connected = $true
                $this._CreateDateTime = Get-Date # Used to refresh "session lifetime"
            }
            catch {
                $this._Connected = $false
                throw ('Unable to connect to SendGrid. {0}' -f $_.Exception.Message)
            }
        }
        else {
            $this._Connected = $false
            throw ('Unable to connect to SendGrid. No credentials saved in context.')
        }
    }
    <#
    .SYNOPSIS
        Connects to the SendGrid API with specified credentials.
 
    .DESCRIPTION
        This function establishes a connection to the SendGrid API by using the specified credentials.
 
    .PARAMETER Credential
        The user's SendGrid API credentials.
    #>

    [void] Connect ([PSCredential]$Credential) {
        $this._Credential = $Credential
        $this.BuildEndpointURL([string]'scopes')
        try {
            $Headers = @{
                'Authorization' = ('Bearer {0}' -f $this._Credential.GetNetworkCredential().Password)
                'Content-Type'  = 'application/json'
            }
            $null = Invoke-RestMethod -Method Get -Uri  $this.EndpointURL -Headers $Headers -ErrorAction Stop
            $this._Connected = $true
            $this._CreateDateTime = Get-Date
        }
        catch {
            $this._Connected = $false
            throw ('Unable to connect to SendGrid. {0}' -f $_.Exception.Message)
        }
    }

    <#
    .SYNOPSIS
        Disconnects from the SendGrid API.
 
    .DESCRIPTION
        This function disconnects the current session from the SendGrid API.
    #>

    [void] Disconnect () {
        $this.BuildEndpointURL($null)
        $this._Credential = $null
        $this._Connected = $false
        $this._CreateDateTime = 0
    }

    <#
    .SYNOPSIS
        Sends a query to the SendGrid API.
 
    .DESCRIPTION
        This method sends a query to the SendGrid API and returns the results.
 
    .PARAMETER WebRequestMethod
        The HTTP method to use for the query (GET, POST, etc.).
 
    .PARAMETER Endpoint
        The specific endpoint in the SendGrid API to send the query to.
 
    .INPUTS
        Microsoft.PowerShell.Commands.WebRequestMethod, string.
 
    .OUTPUTS
        PSCustomObject[]
    #>

    [PSCustomObject[]] InvokeQuery ([Microsoft.PowerShell.Commands.WebRequestMethod]$WebRequestMethod, [string]$Endpoint) {
        if ($this._Connected -eq $false) {
            throw 'You must call the Connect-SendGrid cmdlet before calling any other cmdlets.'
        }
        $SessionLifeTime = (Get-Date).AddHours(-1)
        if ($null -eq $this._CreateDateTime -or $SessionLifeTime -gt $this._CreateDateTime) {
            $this.Disconnect()
            return 'Session lifetime exceeded, reconnect.'
        }
        else {
            $this.BuildEndpointURL($Endpoint)
            try {
                $Headers = @{
                    'Authorization' = "Bearer $($this._Credential.GetNetworkCredential().Password)"
                    'Content-Type'  = 'application/json'
                }
                $Query = (Invoke-RestMethod -Method $WebRequestMethod -Uri $this.EndpointURL -Headers $Headers -ErrorAction Stop)
                $this.BuildEndpointURL($null)
                $this._CreateDateTime = Get-Date
                return $Query
            }
            catch {
                $this.BuildEndpointURL($null)
                if ($null -ne $_.ErrorDetails.Message) {
                    throw ('SendGrid Error: "{0}"' -f ($_.ErrorDetails.Message | ConvertFrom-Json | Select-Object -ExpandProperty errors | Select-Object -ExpandProperty message) -join ', ' )
                }
                else {
                    throw ('Unable to query SendGrid: {0}' -f $_.Exception.Message)
                }
            }
        }
    }
    
    <#
    .SYNOPSIS
        Sends a query to the SendGrid API.
 
    .DESCRIPTION
        This method sends a query to the SendGrid API and returns the results.
 
    .PARAMETER WebRequestMethod
        The HTTP method to use for the query (GET, POST, etc.).
 
    .PARAMETER Endpoint
        The specific endpoint in the SendGrid API to send the query to.
 
    .PARAMETER ContentBody
        The payload to send to the specified endpoint.
 
    .INPUTS
        Microsoft.PowerShell.Commands.WebRequestMethod, string, hashtable.
 
    .OUTPUTS
        PSCustomObject[]
    #>

    [PSCustomObject[]] InvokeQuery ([Microsoft.PowerShell.Commands.WebRequestMethod]$WebRequestMethod, [string]$Endpoint, [hashtable]$ContentBody) {
        foreach ($Key in $ContentBody.Keys) {
            Write-Verbose -Message ('ContentBody: Key: {0}, Value: {1}, Type:{2}' -f $Key, $ContentBody[$Key], $ContentBody[$Key].GetType())
        }
        $Body = $ContentBody | ConvertTo-Json -Depth 5 -ErrorAction Stop
        $SessionLifeTime = (Get-Date).AddHours(-1)
        if ($null -eq $this._CreateDateTime -or $SessionLifeTime -gt $this._CreateDateTime) {
            $this.Disconnect()
            return 'Session lifetime exceeded, reconnect.'
        }
        else {
            $this.BuildEndpointURL($Endpoint)
            try {
                $Headers = @{
                    'Authorization' = "Bearer $($this._Credential.GetNetworkCredential().Password)"
                    'Content-Type'  = 'application/json'
                }
                $Query = (Invoke-RestMethod -Method $WebRequestMethod -Uri $this.EndpointURL -Headers $Headers -Body $Body -ErrorAction Stop)
                $this.BuildEndpointURL($null)
                $this._CreateDateTime = Get-Date
                return $Query
            }
            catch {
                $this.BuildEndpointURL($null)
                if ($null -ne $_.ErrorDetails.Message) {
                    throw ('SendGrid Error: "{0}"' -f ($_.ErrorDetails.Message | ConvertFrom-Json | Select-Object -ExpandProperty errors | Select-Object -ExpandProperty message) -join ', ' )
                }
                else {
                    throw ('Unable to query SendGrid: {0}' -f $_.Exception.Message)
                }
            }
        }
    }

    <#
    .SYNOPSIS
        Sends a query to the SendGrid API using on behalf of.
 
    .DESCRIPTION
        This method sends a query to the SendGrid API and returns the results using on behalf of.
 
    .PARAMETER WebRequestMethod
        The HTTP method to use for the query (GET, POST, etc.).
 
    .PARAMETER Endpoint
        The specific endpoint in the SendGrid API to send the query to.
 
    .PARAMETER OnBehalfOf
        The username of the subuser to send the query on behalf of.
 
    .INPUTS
        Microsoft.PowerShell.Commands.WebRequestMethod, string.
 
    .OUTPUTS
        PSCustomObject[]
    #>

    [PSCustomObject[]] InvokeQuery ([Microsoft.PowerShell.Commands.WebRequestMethod]$WebRequestMethod, [string]$Endpoint, [string]$OnBehalfOf) {
        if ($this._Connected -eq $false) {
            throw 'You must call the Connect-SendGrid cmdlet before calling any other cmdlets.'
        }
        $SessionLifeTime = (Get-Date).AddHours(-1)
        if ($null -eq $this._CreateDateTime -or $SessionLifeTime -gt $this._CreateDateTime) {
            $this.Disconnect()
            return 'Session lifetime exceeded, reconnect.'
        }
        else {
            $this.BuildEndpointURL($Endpoint)
            try {
                $Headers = @{
                    'Authorization' = "Bearer $($this._Credential.GetNetworkCredential().Password)"
                    'on-behalf-of'  = $OnBehalfOf
                    'Content-Type'  = 'application/json'
                }
                $Query = (Invoke-RestMethod -Method $WebRequestMethod -Uri $this.EndpointURL -Headers $Headers -ErrorAction Stop)
                $this.BuildEndpointURL($null)
                $this._CreateDateTime = Get-Date
                return $Query
            }
            catch {
                $this.BuildEndpointURL($null)
                if ($null -ne $_.ErrorDetails.Message) {
                    throw ('SendGrid Error: "{0}"' -f ($_.ErrorDetails.Message | ConvertFrom-Json | Select-Object -ExpandProperty errors | Select-Object -ExpandProperty message) -join ', ' )
                }
                else {
                    throw ('Unable to query SendGrid: {0}' -f $_.Exception.Message)
                }
            }
        }
    }

    <#
    .SYNOPSIS
        Sends a query to the SendGrid API.
 
    .DESCRIPTION
        This method sends a query to the SendGrid API and returns the results.
 
    .PARAMETER WebRequestMethod
        The HTTP method to use for the query (GET, POST, etc.).
 
    .PARAMETER Endpoint
        The specific endpoint in the SendGrid API to send the query to.
 
    .PARAMETER ContentBody
        The payload to send to the specified endpoint.
     
    .PARAMETER OnBehalfOf
        The username of the subuser or account-id to send the query on behalf of.
 
    .INPUTS
        Microsoft.PowerShell.Commands.WebRequestMethod, string, hashtable.
 
    .OUTPUTS
        PSCustomObject[]
    #>

    [PSCustomObject[]] InvokeQuery ([Microsoft.PowerShell.Commands.WebRequestMethod]$WebRequestMethod, [string]$Endpoint, [hashtable]$ContentBody, [string]$OnBehalfOf) {
        $Body = $ContentBody | ConvertTo-Json -Depth 5 -ErrorAction Stop
        $SessionLifeTime = (Get-Date).AddHours(-1)
        if ($null -eq $this._CreateDateTime -or $SessionLifeTime -gt $this._CreateDateTime) {
            $this.Disconnect()
            return 'Session lifetime exceeded, reconnect.'
        }
        else {
            $this.BuildEndpointURL($Endpoint)
            try {
                $Headers = @{
                    'Authorization' = "Bearer $($this._Credential.GetNetworkCredential().Password)"
                    'on-behalf-of'  = $OnBehalfOf
                    'Content-Type'  = 'application/json'
                }
                $Query = (Invoke-RestMethod -Method $WebRequestMethod -Uri $this.EndpointURL -Headers $Headers -Body $Body -ErrorAction Stop)
                $this.BuildEndpointURL($null)
                $this._CreateDateTime = Get-Date
                return $Query
            }
            catch {
                $this.BuildEndpointURL($null)
                if ($null -ne $_.ErrorDetails.Message) {
                    throw ('SendGrid Error: "{0}"' -f ($_.ErrorDetails.Message | ConvertFrom-Json | Select-Object -ExpandProperty errors | Select-Object -ExpandProperty message) -join ', ' )
                }
                else {
                    throw ('Unable to query SendGrid: {0}' -f $_.Exception.Message)
                }
            }
        }
    }

    [string]ToString() {
        return $this._Connected
    }
}
#EndRegion '.\Classes\SGSession.ps1' 346
#Region '.\Private\ConvertTo-FilterQuery.ps1' 0
function ConvertTo-FilterQuery {
    [CmdletBinding()]
    param (
        [Parameter(
            Mandatory,
            ValueFromPipeline,
            ValueFromPipelineByPropertyName
        )]
        [string]$Filter
    )

    $OperatorFormatStructure = @{
        'EQ'          = ('(Property{0})' -f ([uri]::EscapeDataString('=Value')))
        'NE'          = ('(Property{0})' -f ([uri]::EscapeDataString('!=Value')))
        'GT'          = ('(Property{0})' -f ([uri]::EscapeDataString('>Value')))
        'LT'          = ('(Property{0})' -f ([uri]::EscapeDataString('<Value')))
        'IN'          = ('(Property+IN+({0}))' -f ([uri]::EscapeDataString('Value'))) # Array = ("Value1", "Value2")
        'NotIn'       = ('(Property+NOT+IN ({0}))' -f ([uri]::EscapeDataString('Value'))) # Array = ("Value1", "Value2")
        'Like'        = ('(Property+LIKE+{0})' -f ([uri]::EscapeDataString('%Value%'))) #'(Property LIKE "%Value%")'
        'NotLike'     = ('(Property+NOT+LIKE+{0})' -f ([uri]::EscapeDataString('%Value%'))) #'(Property NOT LIKE "%Value%")'
        'Contains'    = ('(Contains(Property{0}))' -f ([uri]::EscapeDataString(',Value'))) #'(Contains(Property,"Value"))'
        'NotContains' = ('(Not Contains(Property{0}))' -f ([uri]::EscapeDataString(',Value'))) #'(Not Contains(Property,"Value"))'
        'IsEmpty'     = '(Property+IS+NULL)'
        'IsNotEmpty'  = '(Property+IS+NOT NULL)'
        'Between'     = '(Property+BETWEEN+TIMESTAMP+Value1+AND+TIMESTAMP+Value2)' # (last_event_time BETWEEN TIMESTAMP "2024-06-30T00:00:00.000Z" AND TIMESTAMP "2024-07-02T23:59:59.999Z")
        'OR'          = '+OR+'
        'AND'         = '+AND+'
    }
    $Properties = @{
        'MessageId'             = 'msg_id'
        'FromEmail'             = 'from_email'
        'Subject'               = 'subject'
        'ToEmail'               = 'to_email'
        'Status'                = 'status'
        'TemplateId'            = 'template_id'
        'MarketingCampaignName' = 'marketing_campaign_name'
        'MarketingCampaignId'   = 'marketing_campaign_id'
        'ApiKeyId'              = 'api_key_id'
        'ApiKeyName'            = 'api_key_id'
        'Events'                = 'events'
        'Categories'            = 'categories'
        'UniqueArgs'            = 'unique_args'
        'OutboundIp'            = 'outbound_ip'
        'LastEventTime'         = 'last_event_time'
        'Clicks'                = 'clicks'
        'AsmGroupId'            = 'asm_group_id'
        'AsmGroupName'          = 'asm_group_id'
        'Teammate'              = 'teammate'
        'Date'                  = 'last_event_time'
        'timestamp'             = 'last_event_time'
    }
    # Regular expression to match the conditions and logical operators
    $MultiSeparateRegex = '(-AND|-OR)'
    $Regex = '^(?<Property>\w+)\s*(?<operator>-eq|-ne|-gt|-lt|-in|-notin|-like|-notlike|-contains|-notcontains|isempty|-isnotempty|-between)\s*(?<Value>.*?)$'

    # Match the logical operators
    $MatchesSeparator = [regex]::Matches($Filter, $MultiSeparateRegex, [System.Text.RegularExpressions.RegexOptions]::IgnoreCase)
    # Initialize an list to hold the operators in order
    $LogicalOperatorsInOrder = [System.Collections.Generic.List[string]]::new()

    # Process each match to extract the operators
    foreach ($Match in $MatchesSeparator) {
        $LogicalOperatorsInOrder.Add($Match.Value)
    }
    # Filter out the logical operators and remove double whitespaces
    $FilterWithOutSeparator = $Filter -replace $MultiSeparateRegex, '_SPLITTING_' #-replace '\s+', ' '
    $Filters = $FilterWithOutSeparator -split '_SPLITTING_'

    # Create a loop for the number of matches using the separator list
    [System.Text.StringBuilder]$QueryString = [System.Text.StringBuilder]::new()
    for ($i = 0; $i -le $LogicalOperatorsInOrder.Count; $i++) {
        $DateTime = $false
        $RegMatches = [regex]::Matches(($Filters[$i].Trim()), $Regex, [System.Text.RegularExpressions.RegexOptions]::IgnoreCase)
        $Match = $RegMatches[0]
        $Property = $Match.Groups[1].Value.Trim()
        $Operator = $Match.Groups[2].Value.Trim()
        $Value = $Match.Groups[3].Value.Trim()

        # Define the properties that require the -Between operator
        $PropertiesRequiringBetween = @('LastEventTime', 'Date', 'Timestamp', 'last_event_time')

        # Check if the current property requires the -Between operator
        if ($PropertiesRequiringBetween -contains $Property) {
            if ($Operator -ne '-between') {
                throw "The property $Property requires the use of the -Between operator."
            }
            elseif ($Operator -eq '-between') {
                $MultipleValues = foreach ($MValue in ($Value -split ',')) {
                    $ModifiedValue = $MValue.Trim() -replace '^''|"|''|"$'
                    $ParsedDate = [DateTime]::Parse($ModifiedValue, [System.Globalization.CultureInfo]::InvariantCulture, [System.Globalization.DateTimeStyles]::AdjustToUniversal)
                    '"{0:yyyy-MM-ddTHH:mm:ss.fffZ}"' -f [DateTime]::Parse($ParsedDate)
                }
                if ($MultipleValues.Count -ne 2) {
                    throw 'The -Between operator requires two values separated by a comma.'
                }
                $Value = $MultipleValues -join ','
                $DateTime = $true
            }
        }
        elseif ($Operator -eq '-between') {
            # If the operator is -Between, ensure it's used with a correct property
            if ($PropertiesRequiringBetween -notcontains $Property) {
                throw "The -Between operator can only be used with the following properties: $($PropertiesRequiringBetween -join ', ')."
            }
            elseif ($PropertiesRequiringBetween -contains $Property) {
                $MultipleValues = foreach ($MValue in ($Value -split ',')) {
                    $ModifiedValue = $MValue.Trim() -replace '^''|"|''|"$'
                    $ParsedDate = [DateTime]::Parse($ModifiedValue, [System.Globalization.CultureInfo]::InvariantCulture, [System.Globalization.DateTimeStyles]::AdjustToUniversal)
                    '"{0:yyyy-MM-ddTHH:mm:ss.fffZ}"' -f [DateTime]::Parse($ParsedDate)
                }
                if ($MultipleValues.Count -ne 2) {
                    throw 'The -Between operator requires two values separated by a comma.'
                }
                $Value = $MultipleValues -join ','
                $DateTime = $true
            }
        }
        if ($Properties.Keys -notcontains $Property) {
            if ($Properties.Values -notcontains $Property) {
                throw ('Invalid property: {0}. Valid properties are: {1}' -f $Property, ($Properties.Keys -join ', '))
            }
        }
        else {
            $Property = $Properties[$Property]
            if ($null -eq $OperatorFormatStructure[$Operator.Replace('-', '')]) {
                throw ('Invalid operator: {0}. Valid operators are: {1}' -f $Operator, ($OperatorFormatStructure.Keys -join ', '))
            }
        }
        if ($Operator -eq '-in' -or $Operator -eq '-notin') {
            $MultipleValues = foreach ($MValue in ($Value -split ',')) {
                $ModifiedValue = $MValue.Trim() -replace '^''|"|''|"$'
                "`"$ModifiedValue`""
            }
            $Value = $MultipleValues -join ','
        }
        elseif ($DateTime -eq $false -or $null -eq $DateTime) {
            $ModifiedValue = $Value.Trim() -replace '^''|"|''|"$'
            $Value = "`"$ModifiedValue`""
        }

        if ($DateTime -eq $true) {
            Write-Verbose -Message "DateTime: $Value"
            $EncodedValue1 = [uri]::EscapeDataString($Value.Split(',')[0])
            $EncodedValue2 = [uri]::EscapeDataString($Value.Split(',')[1])
            $null = $QueryString.Append(($OperatorFormatStructure[$Operator.Replace('-', '')] -replace 'Property', $Property -replace 'Value1', $EncodedValue1 -replace 'Value2', $EncodedValue2))
        }
        else {
            $EncodedValue = [uri]::EscapeDataString($Value)
            $null = $QueryString.Append(($OperatorFormatStructure[$Operator.Replace('-', '')] -replace 'Property', $Property -replace 'Value', $EncodedValue))
        }

        Write-Verbose "Property: $Property, Operator: $Operator, Value: $EncodedValue$EncodedValue1$EncodedValue2"
        if ($i -lt $LogicalOperatorsInOrder.Count) {
            $null = $QueryString.Append($OperatorFormatStructure[$($LogicalOperatorsInOrder[$i]).Replace('-', '')])
            Write-Verbose "Logical Operator: $($LogicalOperatorsInOrder[$i])"
        }
    }
    $QueryString.ToString()
}
#EndRegion '.\Private\ConvertTo-FilterQuery.ps1' 160
#Region '.\Private\ConvertTo-SendGridAddress.ps1' 0
function ConvertTo-SendGridAddress {
    [CmdletBinding()]
    param (
        [Parameter(
            ValueFromPipeline = $true,
            Position = 0
        )]
        [Alias("EmailAddress")]
        [object[]]$Address
    )
    process {
        foreach ($A in $Address) {
            try {
                $EmailAddress = [System.Net.Mail.MailAddress]$A
                if ($null -eq $EmailAddress.DisplayName -or $EmailAddress.DisplayName -eq [string]::Empty) {
                    @{
                        email = $EmailAddress.Address
                    }
                }
                else {
                    @{
                        email = $EmailAddress.Address
                        name  = $EmailAddress.DisplayName
                    }
                }
            }
            catch {
                Write-Error "Invalid email address: $A" -ErrorAction Stop
            }
        }
    }
}
#EndRegion '.\Private\ConvertTo-SendGridAddress.ps1' 33
#Region '.\Private\ConvertTo-TitleCase.ps1' 0
function ConvertTo-TitleCase {
    <#
    .SYNOPSIS
    The ConvertTo-TitleCase function converts a specified string to title case.
 
    .DESCRIPTION
    The ConvertTo-TitleCase function converts a specified string to title case using the Method in (Get-Culture).TextInfo
    All input strings will be converted to lowercase, because uppercase are considered to be acronyms.
 
    .EXAMPLE
    ConvertTo-TitleCase -InputObject 'roger johnsson'
    Roger Johnsson
 
    This example returns the string 'Roger Johnsson' which has capitalized the R and J chars.
 
    .EXAMPLE
    'roger johnsson', 'JOHN ROGERSSON' | ConvertTo-TitleCase
    Roger Johnsson
    John Rogersson
 
    This example returns the strings 'Roger Johnsson' and 'John Rogersson' which has capitalized the R and J chars.
 
    .LINK
        https://github.com/Omnicit/Omnicit/blob/master/docs/en-US/ConvertTo-TitleCase.md
    #>

    [Alias('ConvertTo-NameTitle')]
    [CmdletBinding(
        PositionalBinding,
        SupportsShouldProcess
    )]
    param (
        # Specifies one or more objects to be convert to title case strings.
        [Parameter(
            Mandatory,
            ValueFromPipeline,
            Position = 0
        )]
        [AllowEmptyString()]
        [string[]]$InputObject
    )
    begin {
        $TextInfo = (Get-Culture).TextInfo
    }
    process {
        foreach ($String in $InputObject) {
            if ($PSCmdlet.ShouldProcess($String)) {
                $TextInfo.ToTitleCase($String.ToLower())
            }
        }
    }
}
#EndRegion '.\Private\ConvertTo-TitleCase.ps1' 52
#Region '.\Private\Invoke-SendGrid.ps1' 0
<#
.SYNOPSIS
This function is used to interact with the SendGrid API.
 
.DESCRIPTION
Invoke-SendGrid is a custom function designed to interact with the SendGrid API. It requires an active SendGridSession, which should be established via the Connect-SendGrid cmdlet before calling this function.
 
.PARAMETER Method
The web request method to use (GET, POST, PUT, DELETE etc).
 
.PARAMETER Namespace
The endpoint of the SendGrid API to interact with.
 
.PARAMETER ContentBody
(Optional) A hashtable containing the request body to send with the request.
 
.EXAMPLE
Invoke-SendGrid -Method GET -Namespace "mail/send"
 
#>

function Invoke-SendGrid {
    [CmdletBinding(
        SupportsShouldProcess
    )]
    param (
        # The web request method.
        [Parameter(
            Mandatory,
            HelpMessage = 'The web request method.',
            Position = 0
        )]
        [ValidateNotNullOrEmpty()]
        [Microsoft.PowerShell.Commands.WebRequestMethod]$Method,

        # The endpoint to use.
        [Parameter(
            Mandatory,
            HelpMessage = 'The SendGrid endpoint to use.',
            Position = 1
        )]
        [ValidateNotNullOrEmpty()]
        [string]$Namespace,

        # The content body to send with the request.
        [Parameter(
            HelpMessage = 'The content body to send with the request.',
            Position = 2
        )]
        [ValidateNotNull()]
        [AllowEmptyCollection()]
        [hashtable]$ContentBody,

        # The username of the subuser to send the query on behalf of.
        [Parameter(
            HelpMessage = 'The username of the subuser to send the query on behalf of.',
            Position = 3
        )]
        [ValidateNotNullOrEmpty()]
        [string]$OnBehalfOf,

        # The calling cmdlet or function that invoked this function.
        [Parameter(
            HelpMessage = 'The calling cmdlet or function that invoked this function.',
            Position = 4
        )]
        [ValidateNotNullOrEmpty()]
        [string]$CallingCmdlet
    )
    begin {
        # Function to get unique properties of an object.
        function Get-UniqueProperties {
            param (
                [Parameter(
                    ValueFromPipeline
                )]
                [object[]]$InputObject
            )
            # Get the properties of each object in the input array.
            $Members = foreach ($Object in $InputObject) {
                $Object | Get-Member -MemberType NoteProperty
            }
            # Return the unique properties.
            if ($null -ne $Members) {
                ($Members | Sort-Object -Property Name -Unique).Name | ConvertTo-TitleCase
            }
        }
    }
    process {
        if ($PSCmdlet.ShouldProcess("$Method : $Namespace")) {
            Write-Verbose "Starting process with method: $Method and namespace: $Namespace"
            # Check if session is not a SendGridSession.
            if ($script:Session -isnot [SendGridSession]) {
                throw 'You must call the Connect-SendGrid cmdlet before calling any other cmdlets.'
            }
            try {
                # Invoke the query based on provided parameters.
                if ($PSBoundParameters.ContainsKey('ContentBody') -and $PSBoundParameters.ContainsKey('OnBehalfOf')) {
                    $Query = $script:Session.InvokeQuery($Method, $Namespace, $ContentBody, $OnBehalfOf)
                }
                elseif ($PSBoundParameters.ContainsKey('ContentBody')) {
                    $Query = $script:Session.InvokeQuery($Method, $Namespace, $ContentBody)
                }
                elseif ($PSBoundParameters.ContainsKey('OnBehalfOf')) {
                    $Query = $script:Session.InvokeQuery($Method, $Namespace, $OnBehalfOf)
                }
                else {
                    $Query = $script:Session.InvokeQuery($Method, $Namespace)
                }
            }
            catch {
                throw $_.Exception.Message
            }

            # Get unique properties.
            $Properties = Get-UniqueProperties -InputObject $Query
            
            # Handle PSObject array with a single or more than 'Result' property.
            if ($Query -is [System.Management.Automation.PSObject[]] -and $Properties.Count -eq 1) {
                switch ($Properties) {
                    'Result' {
                        $Query = $Query.result
                        break;
                    }
                    'Results' {
                        $Query = $Query.results
                        break;
                    }
                    'Suppressions' {
                        $Query = $Query.suppressions
                        break;
                    }
                    'Messages' {
                        $Query = $Query.messages
                        $PSTypeName = 'SendGridTools.Get.SGEmailActivity'
                        break;
                    }
                    Default {
                        break;
                    }
                }
                $Properties = Get-UniqueProperties -InputObject $Query
            }
            elseif ($Query -is [System.Management.Automation.PSObject[]] -and $Properties.Count -gt 1 -and ($Properties -eq 'Result' -or $Properties -eq 'Results')) {
                switch ($Properties | Where-Object { $_ -notmatch 'Metadata' }) {
                    'Result' {
                        $Query = $Query.result
                        break;
                    }
                    'Results' {
                        $Query = $Query.results
                        break;
                    }
                    Default {
                        break;
                    }
                }
                $Properties = Get-UniqueProperties -InputObject $Query
            }

            switch ($CallingCmdlet) {
                'Get-SGAuthenticatedDomain' {
                    $PSTypeName = 'SendGridTools.Get.SGAuthenticatedDomain'
                    break
                }
                'Get-SGAuthenticatedDomain -ShowDNS' {
                    # Need a format view that is friendly to the user. Pull request requested from one happy user.
                    break
                }
                'Get-SGBrandedDomainLink -ShowDNS' {
                    # Need a format view that is friendly to the user. Pull request requested from one happy user.
                    break
                }
                'Get-SGBrandedDomainLink' {
                    $PSTypeName = 'SendGridTools.Get.SGBrandedDomainLink'
                    break
                }
                'Get-SGCombinedDomain' {
                    $PSTypeName = 'SendGridTools.Get.SGCombinedDomain'
                    break
                }
                Default {
                    break
                }
            }

            # Process each object in the query.
            foreach ($Object in $Query) {
                # Create a new custom object.
                [PSCustomObject]$PSObject = [PSCustomObject]::new()
                if ($PSTypeName) {
                    $PSObject | Add-Member -TypeName $PSTypeName
                }

                # Process each property in the properties array.
                foreach ($Property in $Properties) {
                    # Check for inline properties.
                    if ($Object.$Property -is [System.Management.Automation.PSCustomObject]) {
                        $InlineProperties = Get-UniqueProperties -InputObject $Object.$Property

                        # Process each inline property.
                        foreach ($InlineProperty in $InlineProperties) {
                            $PSObject | Add-Member -MemberType NoteProperty -Name (('{0}{1}' -f ($Property -replace '[\s_-]+'), $($InlineProperty | ConvertTo-TitleCase) -replace '[\s_-]+')) -Value $Object.$Property.$InlineProperty
                        }
                    }

                    # Switch based on the property type.
                    switch ($Object.$Property) {
                        { $_ -is [int64] -and $Property -match 'valid|created|updated|lastat' } {
                            $PSObject | Add-Member -MemberType NoteProperty -Name (($Property | ConvertTo-TitleCase) -replace '[\s_-]+') -Value ([UnixTime]::FromUnixTime($_))
                            break
                        }
                        { $_ -is [string] -and $Property -match '^date$' } {
                            $PSObject | Add-Member -MemberType NoteProperty -Name (($Property | ConvertTo-TitleCase) -replace '[\s_-]+') -Value ([datetime]::Parse($_))
                            break
                        }
                        Default {
                            $PSObject | Add-Member -MemberType NoteProperty -Name (($Property | ConvertTo-TitleCase) -replace '[\s_-]+') -Value $Object.$Property -Force
                            break
                        }
                    }
                }
                if ($PSObject | Get-Member -Name 'Errors' -MemberType 'NoteProperty') {
                    throw $PSObject.Errors.Message
                }
                else {
                    if (0 -eq @($PSObject.PSObject.Properties).Count) {
                        Write-Verbose -Message ('Successfully invoked "{0}" on "{1}".' -f $CallingCmdlet, $Namespace) -Verbose
                    }
                    else {
                        $PSObject
                    }
                }
            }
            Write-Verbose -Message ('Successfully invoked "{0}" on "{1}".' -f $CallingCmdlet, $Namespace)
        }
    }
}
#EndRegion '.\Private\Invoke-SendGrid.ps1' 238
#Region '.\Private\Remove-EmptyHashtable.ps1' 0
function Remove-EmptyHashtable {
    [CmdletBinding()]
    param(
        [Parameter(
            Mandatory,
            ValueFromPipeline,
            ValueFromPipelineByPropertyName
        )]
        [alias('Splat', 'IDictionary')]
        [System.Collections.IDictionary[]]$Hashtable,
        [string[]] $ExcludeParameter,
        [switch] $Recursive,
        [int] $Rerun,
        [switch]$DoNotRemoveNull,
        [switch]$DoNotRemoveEmpty,
        [switch]$DoNotRemoveEmptyArray,
        [switch]$DoNotRemoveEmptyDictionary
    )
    foreach ($Hash in $Hashtable) {
        foreach ($Key in [object[]]$Hash.Keys) {
            if ($Key -notin $ExcludeParameter) {
                if ($Recursive) {
                    if ($Hash[$Key] -is [System.Collections.IDictionary]) {
                        if ($Hash[$Key].Count -eq 0) {
                            if (-not $DoNotRemoveEmptyDictionary) {
                                $Hash.Remove($Key)
                            }
                        }
                        else {
                            Remove-EmptyHashtable -Hashtable $Hash[$Key] -Recursive:$Recursive
                        }
                    }
                    else {
                        if (-not $DoNotRemoveNull -and $null -eq $Hash[$Key]) {
                            Write-Verbose -Message "Removing $Key from hashtable, because it is null."
                            $Hash.Remove($Key)
                        }
                        elseif (-not $DoNotRemoveEmpty -and $Hash[$Key] -is [string] -and $Hash[$Key] -eq '') {
                            Write-Verbose -Message "Removing $Key from hashtable, because it is empty."
                            $Hash.Remove($Key)
                        }
                        elseif (-not $DoNotRemoveEmptyArray -and $Hash[$Key] -is [System.Collections.IList] -and $Hash[$Key].Count -eq 0) {
                            Write-Verbose -Message "Removing $Key from hashtable, because it is an empty array."
                            $Hash.Remove($Key)
                        }
                    }
                }
                else {
                    if (-not $DoNotRemoveNull -and $null -eq $Hash[$Key]) {
                        Write-Verbose -Message "Removing $Key from hashtable, because it is null."
                        $Hash.Remove($Key)
                    }
                    elseif (-not $DoNotRemoveEmpty -and $Hash[$Key] -is [string] -and $Hash[$Key] -eq '') {
                        Write-Verbose -Message "Removing $Key from hashtable, because it is empty."
                        $Hash.Remove($Key)
                    }
                    elseif (-not $DoNotRemoveEmptyArray -and $Hash[$Key] -is [System.Collections.IList] -and $Hash[$Key].Count -eq 0) {
                        Write-Verbose -Message "Removing $Key from hashtable, because it is an empty array."
                        $Hash.Remove($Key)
                    }
                }
            }
        }
    }
    if ($Rerun) {
        for ($i = 0; $i -lt $Rerun; $i++) {
            Remove-EmptyHashtable -Hashtable $Hash -Recursive:$Recursive
        }
    }
}
#EndRegion '.\Private\Remove-EmptyHashtable.ps1' 71
#Region '.\Public\Add-SGEmailAddressToSuppressionGroup.ps1' 0
function Add-SGEmailAddressToSuppressionGroup {
    <#
    .SYNOPSIS
        Adds email addresses to a suppression group.
 
    .DESCRIPTION
        The Add-SGEmailAddressToSuppressionGroup function adds email addresses to a suppression group in SendGrid.
         
    .PARAMETER GroupId
        Specifies the ID of the suppression group.
 
    .PARAMETER EmailAddresses
        Specifies the email addresses to add to the suppression group.
 
    .PARAMETER OnBehalfOf
        Specifies a On Behalf Of header to allow you to make API calls from a parent account on behalf of the parent's sub users or customer accounts.
 
    .EXAMPLE
        PS C:\> Add-SGEmailAddressToSuppressionGroup -GroupId 123 -EmailAddresses 'test@example.com'
        This command adds the email address 'test@example.com' to the suppression group with the ID 123.
    #>

    [CmdletBinding(
        SupportsShouldProcess
    )]
    [Alias('Add-SGSuppression', 'Add-SGAddressToSuppression')]
    param (
        # Specifies the ID of the suppression group.
        [Parameter(
            Mandatory,
            ValueFromPipeline,
            ValueFromPipelineByPropertyName,
            Position = 0
        )]
        [Alias('Id')]
        [int]$UniqueId,

        # Specifies the email addresses to add to the suppression group.
        [Parameter(
            Mandatory,
            Position = 1
        )]
        [MailAddress[]]$EmailAddresses,

        # Specifies a On Behalf Of header to allow you to make API calls from a parent account on behalf of the parent's sub users or customer accounts.
        [Parameter()]
        [string]$OnBehalfOf
    )
    process {
        $InvokeSplat = @{
            Method        = 'Post'
            Namespace     = "asm/groups/$UniqueId/suppressions"
            ContentBody   = @{ recipient_emails = $EmailAddresses | ForEach-Object { $_.Address } }
            ErrorAction   = 'Stop'
            CallingCmdlet = $PSCmdlet.MyInvocation.MyCommand.Name
        }
        if ($PSBoundParameters.ContainsKey('OnBehalfOf')) {
            $InvokeSplat.OnBehalfOf = $OnBehalfOf
        }
        if ($PSCmdlet.ShouldProcess(('Add email addresses to suppression group with ID {0}.' -f $UniqueId))) {
            try {
                Invoke-SendGrid @InvokeSplat
            }
            catch {
                Write-Error ('Failed to add email addresses to suppression group. {0}' -f $_.Exception.Message) -ErrorAction Stop
            }
        }
    }
}
#EndRegion '.\Public\Add-SGEmailAddressToSuppressionGroup.ps1' 69
#Region '.\Public\Add-SGGlobalSuppression.ps1' 0
function Add-SGGlobalSuppression {
    <#
    .SYNOPSIS
        Adds a specific email address to the global suppressions list in SendGrid.
 
    .DESCRIPTION
        The Add-SGGlobalSuppression function adds a specific email address to the global suppressions list in SendGrid.
 
    .PARAMETER EmailAddress
        Specifies the email address to add to the global suppressions list.
 
    .PARAMETER OnBehalfOf
        Specifies an On Behalf Of header to allow you to make API calls from a parent account on behalf of the parent's sub users or customer accounts.
 
    .EXAMPLE
        PS C:\> Add-SGSGlobalSuppression -EmailAddress 'test@example.com'
        This command add the email address 'test@example.com' to the global suppressions list in SendGrid.
 
    .EXAMPLE
        PS C:\> Add-SGSGlobalSuppression -EmailAddress 'test@example.com' -OnBehalfOf 'Subuser'
        This command add the email address 'test@example.com' to the global suppressions list in SendGrid for the Subuser 'Subuser'.
    #>

    [CmdletBinding(
        DefaultParameterSetName = 'Default',
        SupportsShouldProcess
    )]
    param (
        # Specifies the email address to remove from the global suppressions list.
        [Parameter(
            Mandatory = $true,
            ValueFromPipeline,
            ValueFromPipelineByPropertyName,
            Position = 0
        )]
        [Alias('Email')]
        [MailAddress[]]$EmailAddress,

        # Specifies an On Behalf Of header to allow you to make API calls from a parent account on behalf of the parent's sub users or customer accounts.
        [Parameter()]
        [string]$OnBehalfOf
    )
    process {
        $InvokeSplat = @{
            Method        = 'Post'
            Namespace     = "suppression/unsubscribes"
            ErrorAction   = 'Stop'
            CallingCmdlet = $PSCmdlet.MyInvocation.MyCommand.Name
            
        }
        if ($PSBoundParameters.OnBehalfOf) {
            $InvokeSplat.Add('OnBehalfOf', $OnBehalfOf)
        }
        foreach ($Email in $EmailAddress) {
            $InvokeSplat['ContentBody'] = @{
                'emails' = @(@{email = $Email.Address})
            }
            if ($PSCmdlet.ShouldProcess(('Add email address {0} to the global suppressions list.' -f $Email.Address))) {
                try {
                    Invoke-SendGrid @InvokeSplat
                }
                catch {
                    Write-Error ('Failed to add email address "{0}" to the global suppressions list. {0}' -f $Email.Address, $_.Exception.Message) -ErrorAction Stop
                }
            }
        }
    }
}
#EndRegion '.\Public\Add-SGGlobalSuppression.ps1' 68
#Region '.\Public\Confirm-SGAuthenticatedDomain.ps1' 0
function Confirm-SGAuthenticatedDomain {
    <#
    .SYNOPSIS
        Validates the authenticated domains within the current SendGrid instance.
         
    .DESCRIPTION
        Confirm-SGAuthenticatedDomain is used to validate the authenticated domains within the current SendGrid instance.
        An authenticated domain allows you to remove the "via" or "sent on behalf of" message that your recipients see when they read your emails.
        Authenticating a domain allows you to replace sendgrid.net with your personal sending domain.
        You will be required to create a subdomain so that SendGrid can generate the DNS records which you must give to your host provider.
         
        This function should be executed after the external DNS records have been applied.
 
    .PARAMETER UniqueId
        Specifies the unique ID of the branded link to validate. This parameter is mandatory.
 
    .EXAMPLE
        PS C:\> Confirm-SGAuthenticatedDomain -UniqueId '1234567'
         
        This command validates the authenticated domain with the unique ID '1234567' in the current SendGrid instance.
 
    .EXAMPLE
        PS C:\> Get-SGAuthenticatedDomain | Confirm-SGAuthenticatedDomain
         
        This command validates all authenticated domains in the current SendGrid instance.
     
    .NOTES
        This function requires an active SendGrid instance to work properly. Make sure to check the validity of the UniqueId parameter.
    #>

    [CmdletBinding(
        SupportsShouldProcess
    )]
    param (
        # Specifies the unique ID of the branded link to validate. This parameter is mandatory.
        [Parameter(
            Mandatory,
            ValueFromPipeline,
            ValueFromPipelineByPropertyName,
            DontShow,
            ParameterSetName = 'InputObject'
        )]
        [Object[]]$InputObject,
        
        # Specifies the unique ID of the branded link to validate. This parameter is mandatory.
        [Parameter(
            Mandatory,
            Position = 0,
            ParameterSetName = 'UniqueId'
        )]
        [Alias('Id')]
        [string[]]$UniqueId,

        # Specifies a On Behalf Of header to allow you to make API calls from a parent account on behalf of the parent's sub users or customer accounts.
        [Parameter()]
        [string]$OnBehalfOf
    )    
    process {
        if ($PSCmdlet.ParameterSetName -eq 'InputObject') {
            $UniqueId = @()
            foreach ($Object in $InputObject) {
                switch ($Object) {
                    { $_ -is [string] } { $UniqueId += $_; break }
                    { $_ -is [int] } { $UniqueId += $_; break }
                    { $_ -is [System.Management.Automation.PSCustomObject] } { $UniqueId += $_.Id; break }
                    default { Write-Error ('Failed to convert InputObject to Id.') -ErrorAction Stop }
                }
            }            
        }
        foreach ($Id in $UniqueId) { 
            $InvokeSplat = @{
                Method        = 'Post'
                Namespace     = "whitelabel/domains/$Id/validate"
                ErrorAction   = 'Stop'
                CallingCmdlet = $PSCmdlet.MyInvocation.MyCommand.Name
            }
            $GetSplat = @{
                UniqueId    = $Id
                ErrorAction = 'Stop'
            }
            if ($PSBoundParameters.OnBehalfOf) {
                $InvokeSplat.Add('OnBehalfOf', $OnBehalfOf)
                $GetSplat.Add('OnBehalfOf', $OnBehalfOf)
            }
            $SGAuthenticatedDomain = Get-SGAuthenticatedDomain @GetSplat
            $SGAuthenticatedDomain

            if ($PSCmdlet.ShouldProcess(('{0}.{1}' -f $SGAuthenticatedDomain.Subdomain, $SGAuthenticatedDomain.Domain))) {

                if ($SGAuthenticatedDomain.Valid -eq $true) {
                    Write-Verbose -Message ('Authenticated Domain already validated!') -Verbose
                }
                else {
                    try {
                        Invoke-SendGrid @InvokeSplat
                    }
                    catch {
                        Write-Error ('Failed to validate SendGrid Authenticated Domain. {0}' -f $_.Exception.Message) -ErrorAction Stop
                    }
                }
            }
        }
    }
}
#EndRegion '.\Public\Confirm-SGAuthenticatedDomain.ps1' 104
#Region '.\Public\Confirm-SGBrandedDomainLink.ps1' 0
function Confirm-SGBrandedDomainLink {
    <#
    .SYNOPSIS
        Validates the branded domain links within the current SendGrid instance.
         
    .DESCRIPTION
        Confirm-SGBrandedDomainLink is used to validate the branded domain links within the current SendGrid instance.
        An authenticated domain allows you to remove the "via”" or "sent on behalf of" message that your recipients see when they read your emails.
        Authenticating a domain allows you to replace sendgrid.net with your personal sending domain.
        You will be required to create a subdomain so that SendGrid can generate the DNS records which you must give to your host provider.
 
        This function should be executed after the external DNS records have been applied.
 
    .PARAMETER UniqueId
        Specifies the unique ID of the branded link to validate. This parameter is mandatory.
 
    .EXAMPLE
        PS C:\> Confirm-SGBrandedDomainLink -UniqueId '1234567'
         
        This command validates the branded domain link with the unique ID '1234567' in the current SendGrid instance.
     
    .NOTES
        This function requires an active SendGrid instance to work properly. Make sure to check the validity of the UniqueId parameter.
    #>

    [CmdletBinding(
        SupportsShouldProcess
    )]
    param (
        # Specifies the unique ID of the branded link to validate. This parameter is mandatory.
        [Parameter(
            Mandatory,
            ValueFromPipeline,
            ValueFromPipelineByPropertyName,
            DontShow,
            ParameterSetName = 'InputObject'
        )]
        [Object[]]$InputObject,
        
        # Specifies the unique ID of the branded link to validate. This parameter is mandatory.
        [Parameter(
            Mandatory,
            Position = 0,
            ParameterSetName = 'UniqueId'
        )]
        [Alias('Id')]
        [string[]]$UniqueId,

        # Specifies a On Behalf Of header to allow you to make API calls from a parent account on behalf of the parent's Subusers or customer accounts.
        [Parameter()]
        [string]$OnBehalfOf
    )   
    process {
        if ($PSCmdlet.ParameterSetName -eq 'InputObject') {
            $UniqueId = @()
            foreach ($Object in $InputObject) {
                switch ($Object) {
                    { $_ -is [string] } { $UniqueId += $_; break }
                    { $_ -is [int] } { $UniqueId += $_; break }
                    { $_ -is [System.Management.Automation.PSCustomObject] } { $UniqueId += $_.Id; break }
                    default { Write-Error ('Failed to convert InputObject to Id.') -ErrorAction Stop }
                }
            }            
        }
        foreach ($Id in $UniqueId) {
            $InvokeSplat = @{
                Method        = 'Post'
                Namespace     = "whitelabel/links/$Id/validate"
                ErrorAction   = 'Stop'
                CallingCmdlet = $PSCmdlet.MyInvocation.MyCommand.Name
            }
            $GetSplat = @{
                UniqueId    = $Id
                ErrorAction = 'Stop'
            }
            if ($PSBoundParameters.OnBehalfOf) {
                $InvokeSplat.Add('OnBehalfOf', $OnBehalfOf)
                $GetSplat.Add('OnBehalfOf', $OnBehalfOf)
            }
            $SGBrandedDomainLink = Get-SGBrandedDomainLink @GetSplat
            $SGBrandedDomainLink

            if ($PSCmdlet.ShouldProcess(('{0}.{1}' -f $SGBrandedDomainLink.Subdomain, $SGBrandedDomainLink.Domain))) {

                if ($SGBrandedDomainLink.Valid -eq $true) {
                    Write-Verbose -Message ('Branded Link Domain already validated!') -Verbose
                }
                else {
                    try {
                        Invoke-SendGrid @InvokeSplat
                    }
                    catch {
                        Write-Error ('Failed to validate SendGrid Branded Domain Link. {0}' -f $_.Exception.Message) -ErrorAction Stop
                    }
                }
            }
        }
    }
}
#EndRegion '.\Public\Confirm-SGBrandedDomainLink.ps1' 99
#Region '.\Public\Connect-SendGrid.ps1' 0
function Connect-SendGrid {
    <#
    .SYNOPSIS
        Establishes a connection with a SendGrid instance.
         
    .DESCRIPTION
        Connect-SendGrid, or its alias Connect-SG, initiates a connection with a SendGrid instance using an API key as the credential.
        If a connection already exists, it ensures that the connection is active. If not, it creates a new connection.
 
    .PARAMETER Credential
        Specifies the API key to use when connecting to the SendGrid instance. The 'Username' field of the PSCredential object does not matter,
        and can be set to any string. The 'Password' field of the PSCredential object should be set to the SendGrid API key.
 
    .PARAMETER Force
        Indicates that this cmdlet forces a new connection, even if a connection already exists.
 
    .EXAMPLE
        PS C:\> Connect-SendGrid -Credential $myCred
 
        This command attempts to establish a connection to SendGrid using the API key stored in $myCred.
 
    .EXAMPLE
        PS C:\> Connect-SendGrid
 
        This command attempts to establish a connection to SendGrid. It will prompt for the API key since no credential was supplied.
 
    .EXAMPLE
        PS C:\> Connect-SendGrid -Force
 
        This command attempts to forcefully establish a new connection to SendGrid. It will prompt for the API key.
 
    .EXAMPLE
        PS C:\> Connect-SendGrid -Credential $myCred -Force
 
        This command attempts to forcefully establish a new connection to SendGrid using the API key stored in $myCred.
        Even if a connection already exists, it will create a new one.
 
    .NOTES
        A SendGrid API key is required to make a successful connection. Ensure your API key has adequate permissions for the tasks you intend to perform.
        The API key should be provided as the 'Password' field of the PSCredential object.
 
        The provided API key (credential) is stored in a script-scoped variable within the module. This means it's only accessible by functions
        within the same module and not accessible externally by other scripts or modules. This provides a degree of isolation and security.
 
        PowerShell does not store script or private variables in plain text in memory, but rather as secure strings, which means the actual API key
        is not easily retrievable through memory inspection tools. However, please note that this doesn't provide complete security. In environments
        where highly sensitive information is handled, it's recommended to use more secure methods of storing and using credentials, such as Azure Key Vault.
 
        The API key stored in the session will persist only as long as the PowerShell session remains active.
        Once the PowerShell session is closed, the variable storing the API key is discarded.
 
        In addition, the SendGridSession class has a built-in mechanism to limit session lifetime. It tracks the time when the session was last created
        or refreshed, and if the last successful connection attempt was more than 12 hours ago, the class automatically disconnects the session.
        This also removes the stored credential (API key) from memory. If you attempt to interact with the SendGrid API after the session has expired,
        you'll need to reconnect using your credentials. This is done to help ensure the security of your API key.
    #>

    [CmdletBinding(
        SupportsShouldProcess
    )]
    [Alias('Connect-SG')]
    param (
        # Username does not matter. Use 'apikey' if unsure when connecting to SendGrid using API.
        [Parameter(
            Position = 0
        )]
        [System.Management.Automation.PSCredential]
        [System.Management.Automation.Credential()]$Credential,

        [Parameter(
            Position = 1
        )]
        [switch]$Force
    )
    
    process {
        try {
            if ($PSCmdlet.ShouldProcess('SendGrid Session', 'Connect')) {
                if ($Force -or -not $script:Session -or -not ($script:Session -is [SendGridSession])) {
                    $script:Session = [SendGridSession]::new()
                    if ($Credential) {
                        $script:Session.Connect($Credential)
                    }
                    else {
                        $script:Session.Connect((Get-Credential -Message 'Enter your ApiKey' -UserName 'apikey' -Title 'Connect-SendGrid'))
                    }
                    Write-Verbose -Message 'Connection to SendGrid established.' -Verbose
                }
                else {
                    $script:Session.Connect()
                    Write-Verbose -Message 'Existing connection to SendGrid refreshed.' -Verbose
                }
            }
        }
        catch {
            if ($script:Session) {
                Write-Verbose -Message 'Encountered an error while connecting to SendGrid. Cleaning up...'
            }
            Remove-Variable -Name Session -Scope Script
            Write-Error -Message ('Unable to connect to SendGrid. Error detail: {0}' -f $_.Exception.Message) -ErrorAction Stop
        }
    }
}
#EndRegion '.\Public\Connect-SendGrid.ps1' 103
#Region '.\Public\Disable-SGSubuser.ps1' 0
function Disable-SGSubuser {
    <#
    .SYNOPSIS
        Disables a Subuser within the current SendGrid instance.
 
    .DESCRIPTION
        Disable-SGSubuser disables a Subuser within the current SendGrid instance.
        The Subuser is disabled with the provided username.
 
    .PARAMETER Username
        Specifies the ID of a specific Subuser to enable. This parameter is mandatory.
 
    .EXAMPLE
        PS C:\> Disable-SGSubuser -Username <username>
 
        This command disables a Subuser with the specified username within the current SendGrid instance.
     
 
    .NOTES
        To use this function, you must be connected to a SendGrid instance. Use the Connect-SendGrid function to establish a connection.
 
    #>

    [CmdletBinding(
        SupportsShouldProcess,
        ConfirmImpact = 'High'
    )]
    param (

        # Specifies the username for the Subuser to create.
        [Parameter(
            Mandatory,
            ValueFromPipelineByPropertyName,
            Position = 0
        )]
        [string]$Username
    )
    process {
        $InvokeSplat = @{
            Method        = 'Patch'
            Namespace     = "subusers/$Username"
            ErrorAction   = 'Stop'
            ContentBody   = @{
                disabled = $true
            }
            CallingCmdlet = $PSCmdlet.MyInvocation.MyCommand.Name
        } 

        if ($PSCmdlet.ShouldProcess($Username)) {
            try {
                Invoke-SendGrid @InvokeSplat
            }
            catch {
                Write-Error ('Failed to disable SendGrid Subuser. {0}' -f $_.Exception.Message) -ErrorAction Stop
            }
        }
    }
}
#EndRegion '.\Public\Disable-SGSubuser.ps1' 58
#Region '.\Public\Disconnect-SendGrid.ps1' 0
function Disconnect-SendGrid {
    <#
    .SYNOPSIS
        Disconnects from the current established SendGrid instance.
         
    .DESCRIPTION
        Disconnect-SendGrid, or its alias Disconnect-SG, disconnects the current session with a SendGrid instance.
        The function checks if a session exists and, if so, disconnects it.
 
    .EXAMPLE
        PS C:\> Disconnect-SendGrid
         
        This command attempts to disconnect an active connection to SendGrid.
 
    .NOTES
        To use this function, you must first be connected to a SendGrid instance. Use the Connect-SendGrid function to establish a connection.
    #>

    [CmdletBinding(
        SupportsShouldProcess
    )]
    [Alias('Disconnect-SG')]
    param ()
    
    process {
        if ($script:Session -is [SendGridSession]) {
            if ($PSCmdlet.ShouldProcess('SendGrid Session', 'Disconnect')) {
                try {
                    $script:Session.Disconnect()
                    Remove-Variable -Name Session -Scope Script
                }
                catch {
                    Write-Error -Message ('Unable to disconnect from SendGrid. {0}' -f { $_.Exception.Message })
                }
            }
        }
        else {
            Write-Warning -Message 'No active SendGrid session was found.'
        }
    }
}
#EndRegion '.\Public\Disconnect-SendGrid.ps1' 41
#Region '.\Public\Enable-SGSubuser.ps1' 0
function Enable-SGSubuser {
    <#
    .SYNOPSIS
        Enables a Subuser within the current SendGrid instance.
 
    .DESCRIPTION
        Enable-SGSubuser enables a Subuser within the current SendGrid instance.
        The Subuser is enabled with the provided username.
 
    .PARAMETER Username
        Specifies the ID of a specific Subuser to enable. This parameter is mandatory.
 
    .EXAMPLE
        PS C:\> Enable-SGSubuser -Username <username>
         
        This command enables a Subuser with the specified username within the current SendGrid instance.
 
    .NOTES
        To use this function, you must be connected to a SendGrid instance. Use the Connect-SendGrid function to establish a connection.
 
    #>

    [CmdletBinding(
        SupportsShouldProcess
    )]
    param (

        # Specifies the username for the Subuser to create.
        [Parameter(
            Mandatory,
            ValueFromPipelineByPropertyName,
            Position = 0
        )]
        [string]$Username
    )
    process {
        $InvokeSplat = @{
            Method        = 'Patch'
            Namespace     = "subusers/$Username"
            ErrorAction   = 'Stop'
            ContentBody   = @{
                disabled = $false
            }
            CallingCmdlet = $PSCmdlet.MyInvocation.MyCommand.Name
        } 

        if ($PSCmdlet.ShouldProcess($Username)) {
            try {
                Invoke-SendGrid @InvokeSplat
            }
            catch {
                Write-Error ('Failed to enable SendGrid Subuser. {0}' -f $_.Exception.Message) -ErrorAction Stop
            }
        }
    }
}
#EndRegion '.\Public\Enable-SGSubuser.ps1' 56
#Region '.\Public\Get-SGAddressWhitelistSetting.ps1' 0
function Get-SGAddressWhitelistSetting {
    <#
    .SYNOPSIS
        Retrieves the address whitelist mail settings on SendGrid.
    .DESCRIPTION
        Get-SGAddressWhitelistSetting retrieves the address whitelist mail settings on SendGrid.
    .EXAMPLE
        PS C:\> Get-SGAddressWhitelistSetting
        This command retrieves the address whitelist mail settings on SendGrid.
    .NOTES
        To use this function, you must be connected to a SendGrid instance. Use the Connect-SendGrid function to establish a connection.
    #>

    [CmdletBinding()]
    param (# Specifies an On Behalf Of header to allow you to make API calls from a parent account on behalf of the parent's Subusers or customer accounts.
        [Parameter()]
        [string]$OnBehalfOf
    )
    process {
        $InvokeSplat = @{
            Method        = 'Get'
            Namespace     = 'mail_settings/address_whitelist'
            ErrorAction   = 'Stop'
            CallingCmdlet = $PSCmdlet.MyInvocation.MyCommand.Name
        } 

        if ($PSBoundParameters.OnBehalfOf) {
            $InvokeSplat.Add('OnBehalfOf', $OnBehalfOf)
        }
        
        try {
            Invoke-SendGrid @InvokeSplat
        }
        catch {
            Write-Error ('Failed to retrieve SendGrid address whitelist settings. {0}' -f $_.Exception.Message) -ErrorAction Stop
        }
    }
}
#EndRegion '.\Public\Get-SGAddressWhitelistSetting.ps1' 38
#Region '.\Public\Get-SGAlert.ps1' 0
function Get-SGAlert {
    <#
    .SYNOPSIS
        Retrieves a specific alert or all alerts from SendGrid.
 
    .DESCRIPTION
        Get-SGAlert retrieves a specific alert or all alerts from SendGrid based on the provided parameters.
 
    .PARAMETER AlertId
        Specifies the ID of the alert to retrieve.
 
    .PARAMETER OnBehalfOf
        Specifies an On Behalf Of header to allow you to make API calls from a parent account on behalf of the parent's Subusers or customer accounts.
 
    .EXAMPLE
        PS C:\> Get-SGAlert -AlertId "123"
 
        This command retrieves the alert with the ID '123' from SendGrid.
 
    .EXAMPLE
        PS C:\> Get-SGAlert -OnBehalfOf 'Subuser'
 
        This command retrieves all alerts from SendGrid for the Subuser 'Subuser'.
    #>

    [CmdletBinding()]
    param (
        # Specifies the ID of the alert to retrieve.
        [Parameter(
            ValueFromPipeline,
            ValueFromPipelineByPropertyName,
            Position = 0
        )]
        [Alias('Id')]
        [string[]]$AlertId,

        # Specifies an On Behalf Of header to allow you to make API calls from a parent account on behalf of the parent's Subusers or customer accounts.
        [string]$OnBehalfOf
    )
    process {
        $InvokeSplat = @{
            Method        = 'Get'
            Namespace     = 'alerts'
            ErrorAction   = 'Stop'
            CallingCmdlet = $PSCmdlet.MyInvocation.MyCommand.Name
        }
        if ($PSBoundParameters.OnBehalfOf) {
            $InvokeSplat.Add('OnBehalfOf', $OnBehalfOf)
        }
        if ($PSBoundParameters.AlertId) {
            foreach ($Alert in $AlertId) {
                $InvokeSplat['Namespace'] = "alerts/$Alert"
                try {
                    Invoke-SendGrid @InvokeSplat
                }
                catch {
                    Write-Error ('Failed to retrieve SendGrid alert. {0}' -f $_.Exception.Message) -ErrorAction Stop
                }
            }
        }
        else {
            try {
                Invoke-SendGrid @InvokeSplat
            }
            catch {
                Write-Error ('Failed to retrieve SendGrid alert(s). {0}' -f $_.Exception.Message) -ErrorAction Stop
            }
        }
    }
}
#EndRegion '.\Public\Get-SGAlert.ps1' 70
#Region '.\Public\Get-SGApiKey.ps1' 0
function Get-SGApiKey {
    <#
    .SYNOPSIS
        Retrieves all or a specific API Key within the current SendGrid instance.
 
    .DESCRIPTION
        Get-SGApiKey retrieves all API Keys or a specific API Key based on its ID
        within the current SendGrid instance. If a specific API Key ID is provided,
        the cmdlet also returns the scopes added to the key.
 
    .PARAMETER ApiKeyId
        Specifies the ID of a specific API Key to retrieve. If this parameter is not provided, all API Keys are retrieved.
        When a specific API Key ID is provided, the associated scopes of the key are also retrieved.
 
    .PARAMETER OnBehalfOf
        Specifies a On Behalf Of header to allow you to make API calls from a parent account on behalf of the parent's Subusers or customer accounts.
 
    .EXAMPLE
        PS C:\> Get-SGApiKey
         
        This command retrieves all API Keys within the current SendGrid instance.
 
    .EXAMPLE
        PS C:\> Get-SGApiKey -ApiKeyId <apiKeyId>
         
        This command retrieves the API Key with the specified ID within the current SendGrid instance and returns
        the scopes added to the key.
     
    .EXAMPLE
        PS C:\> Get-SGApiKey -OnBehalfOf 'Subuser'
         
        This command retrieves all API Keys within the current SendGrid instance on behalf of the specified subuser.
    #>

    [CmdletBinding(
        SupportsShouldProcess
    )]
    param (

        # Specifies the ID of a specific API Key to retrieve. If this parameter is not provided, all API Keys are retrieved.
        [Parameter(
            ValueFromPipeline,
            ValueFromPipelineByPropertyName,
            Position = 0
        )]
        [string[]]$ApiKeyId,

        # Specifies a On Behalf Of header to allow you to make API calls from a parent account on behalf of the parent's Subusers or customer accounts.
        [Parameter()]
        [string]$OnBehalfOf
    )

    process {
        $InvokeSplat = @{
            Method        = 'Get'
            Namespace     = 'api_keys'
            ErrorAction   = 'Stop'
            CallingCmdlet = $PSCmdlet.MyInvocation.MyCommand.Name
        }
        if ($PSBoundParameters.OnBehalfOf) {
            $InvokeSplat.Add('OnBehalfOf', $OnBehalfOf)
        }
        if ($PSBoundParameters.ApiKeyId) {
            foreach ($Id in $ApiKeyID) {
                if ($PSCmdlet.ShouldProcess(('{0}' -f $Id))) {
                    $InvokeSplat['Namespace'] = "api_keys/$Id"
                    try {
                        Invoke-SendGrid @InvokeSplat
                    }
                    catch {
                        Write-Error ('Failed to retrieve SendGrid API Key. {0}' -f $_.Exception.Message) -ErrorAction Stop
                    }
                }
            }
        }
        else {
            if ($PSCmdlet.ShouldProcess(('{0}' -f 'All API Keys'))) {
                try {
                    Invoke-SendGrid @InvokeSplat
                }
                catch {
                    Write-Error ('Failed to retrieve SendGrid API Key. {0}' -f $_.Exception.Message) -ErrorAction Stop
                }
            }
        }
    }
}
#EndRegion '.\Public\Get-SGApiKey.ps1' 87
#Region '.\Public\Get-SGAuthenticatedDomain.ps1' 0
function Get-SGAuthenticatedDomain {
    <#
    .SYNOPSIS
        Retrieves all or specific Authenticated Domains within the current SendGrid instance.
         
    .DESCRIPTION
        Get-SGAuthenticatedDomain retrieves all Authenticated Domains or a specific Authenticated Domain based on its unique ID
        within the current SendGrid instance. An authenticated domain allows you to replace sendgrid.net with your personal sending domain,
        thereby removing the "via" or "sent on behalf of" message that recipients see when they read your emails.
 
    .PARAMETER UniqueId
        Specifies the UniqueId of a specific Authenticated Domain to retrieve. If this parameter is not provided, all Authenticated Domains are retrieved.
 
    .PARAMETER OnBehalfOf
        Specifies a On Behalf Of header to allow you to make API calls from a parent account on behalf of the parent's Subusers or customer accounts.
 
    .EXAMPLE
        PS C:\> Get-SGAuthenticatedDomain
         
        Domain : sending.example.com
        Subdomain : em4963
        User : Top Account
        Valid : True
        AutomaticSecurity : True
        Default : False
        ValidationAttempt : 2022-03-04 15:34:34
        DNS : @{MailCNAME=; DKIM1=; DKIM2=}
        IPAddresses : {}
        UniqueId : 13508031
        UserId : 8262273
 
        Domain : email.example.com
        Subdomain : em200
        User : Top Account
        Valid : True
        AutomaticSecurity : True
        Default : False
        ValidationAttempt : 2021-11-12 07:38:27
        DNS : @{MailCNAME=; DKIM1=; DKIM2=}
        IPAddresses : {}
        UniqueId : 12589712
        UserId : 8262273
        ...
 
        This command retrieves all Authenticated Domains within the current SendGrid instance.
 
    .EXAMPLE
        PS C:\> Get-SGAuthenticatedDomain -UniqueId 12589712
         
        Domain : email.example.com
        Subdomain : em200
        User : Top Account
        Valid : True
        AutomaticSecurity : True
        Default : False
        ValidationAttempt : 2021-11-12 07:38:27
        DNS : @{MailCNAME=; DKIM1=; DKIM2=}
        IPAddresses : {}
        UniqueId : 12589712
        UserId : 8262273
        Username : Top Account
 
        This command retrieves the Authenticated Domain with the UniqueId '12589712' within the current SendGrid instance.
 
        .EXAMPLE
        PS C:\> Get-SGAuthenticatedDomain -UniqueId 12589712 -OnBehalfOf 'Subuser'
 
        Domain : email.example.com
        Subdomain : em200
        User : Top Account
        Valid : True
        AutomaticSecurity : True
        Default : False
        ValidationAttempt : 2021-11-12 07:38:27
        DNS : @{MailCNAME=; DKIM1=; DKIM2=}
        IPAddresses : {}
        UniqueId : 12589712
        UserId : 8262273
        Username : Subuser
 
        This command retrieves the Authenticated Domain with the UniqueId '12589712' within for the Subuser 'Subuser' within the current SendGrid instance.
    #>

    [CmdletBinding(
        SupportsShouldProcess
    )]
    param (
        # Specifies the UniqueId of a specific Authenticated Domain to retrieve. If this parameter is not provided, all Authenticated Domains are retrieved.
        [Parameter(
            ValueFromPipeline,
            ValueFromPipelineByPropertyName,
            Position = 0
        )]
        [Alias('UniqueId')]
        [string[]]$Id,

        # Specifies if the DNS records should be shown.
        [Parameter(
            Position = 1
        )]
        [switch]$ShowDNS,

        # Specifies a On Behalf Of header to allow you to make API calls from a parent account on behalf of the parent's Subusers or customer accounts.
        [Parameter()]
        [string]$OnBehalfOf
    )
    DynamicParam {
        # Create a dictionary to hold the dynamic parameters
        $ParamDictionary = [System.Management.Automation.RuntimeDefinedParameterDictionary]::new()
        if ($null -eq $Id) {
            # Create the Equal parameter attribute
            $DomainNameParamAttribute = [System.Management.Automation.ParameterAttribute]::new()
            $DomainNameParamAttribute.ParameterSetName = 'DomainNameSet'

            # Add the parameter attributes to an attribute collection
            $DomainNameAttributeCollection = [System.Collections.ObjectModel.Collection[System.Attribute]]::new()
            $DomainNameAttributeCollection.Add($DomainNameParamAttribute)

            # Add ValidateSet to the parameter
            $script:SGDomains = Invoke-SGCommand -Namespace 'whitelabel/domains' # Can't reference if self Get-SGAuthenticatedDomain for reasons unknown to me.
            $DomainNameValidateSet = [System.Management.Automation.ValidateSetAttribute]::new([string[]]$script:SGDomains.Domain)
            $DomainNameAttributeCollection.Add($DomainNameValidateSet)

            # Add Alias to the parameter
            $DomainNameAliasAttribute = [System.Management.Automation.AliasAttribute]::new('Domain')
            $DomainNameAttributeCollection.Add($DomainNameAliasAttribute)

            # Create the actual parameter(s)
            $DomainNameParam = [System.Management.Automation.RuntimeDefinedParameter]::new('DomainName', [string[]], $DomainNameAttributeCollection)

            # Push the parameter(s) into a parameter dictionary
            $ParamDictionary.Add('DomainName', $DomainNameParam)
        }
        return $ParamDictionary
    }
    process {
        $InvokeSplat = @{
            Method        = 'Get'
            Namespace     = 'whitelabel/domains'
            ErrorAction   = 'Stop'
            CallingCmdlet = $PSCmdlet.MyInvocation.MyCommand.Name
        }
        # Get-SGAuthenticatedDomain -ShowDNS'
        if ($PSBoundParameters.ShowDNS) {
            $InvokeSplat['CallingCmdlet'] = "$($PSCmdlet.MyInvocation.MyCommand.Name) -ShowDNS"
        }
        if ($PSBoundParameters.OnBehalfOf) {
            $InvokeSplat.Add('OnBehalfOf', $OnBehalfOf)
        }
        if ($PSCmdlet.ParameterSetName -eq 'DomainNameSet') {
            $Id = ($script:SGDomains | Where-Object { $_.Domain -eq ($PSBoundParameters['DomainName']) }).Id
        }
        if ($null -ne $Id) {
            foreach ($UniqueId in $Id) {
                if ($PSCmdlet.ShouldProcess(('{0}' -f $UniqueId))) {
                    $InvokeSplat['Namespace'] = "whitelabel/domains/$UniqueId"
                    try {
                        Invoke-SendGrid @InvokeSplat
                    }
                    catch {
                        Write-Error ('Failed to retrieve SendGrid Authenticated Domain. {0}' -f $_.Exception.Message) -ErrorAction Stop
                    }
                }
            }
        }
        else {
            if ($PSCmdlet.ShouldProcess(('All Authenticated Domains'))) {
                try {
                    Invoke-SendGrid @InvokeSplat
                }
                catch {
                    Write-Error ('Failed to retrieve all SendGrid Authenticated Domain. {0}' -f $_.Exception.Message) -ErrorAction Stop
                }
            }
        }
    }   
}
#EndRegion '.\Public\Get-SGAuthenticatedDomain.ps1' 177
#Region '.\Public\Get-SGBlock.ps1' 0
function Get-SGBlock {
    <#
    .SYNOPSIS
        Retrieves a specific block from SendGrid.
 
    .DESCRIPTION
        Get-SGBlock retrieves a specific block based on the email address from SendGrid. Blocks occur when an email is rejected due to an issue with the message itself.
 
    .PARAMETER EmailAddress
        Specifies the email address of a specific block to retrieve.
 
    .PARAMETER OnBehalfOf
        Specifies an On Behalf Of header to allow you to make API calls from a parent account on behalf of the parent's Subusers or customer accounts.
 
    .EXAMPLE
        PS C:\> Get-SGBlock -EmailAddress block@example.com
 
        This command retrieves the block for the email address 'block@example.com' from SendGrid.
 
    .EXAMPLE
        PS C:\> Get-SGBlock -EmailAddress block@example.com -OnBehalfOf 'Subuser'
 
        This command retrieves the block for the email address 'block@example.com' from SendGrid for the Subuser 'Subuser'.
    #>

    [CmdletBinding()]
    param (
        # Specifies the specific email address to retrieve.
        [Parameter(
            ValueFromPipeline,
            ValueFromPipelineByPropertyName,
            Position = 0
        )]
        [MailAddress[]]$EmailAddress,

        # Refers to the start of the time range in Unix timestamp when an invalid email was created (inclusive).
        [Parameter(
            Position = 1
        )]
        [UnixTime]$StartTime,

        # Refers to the end of the time range in Unix timestamp when an invalid email was created (inclusive).
        [Parameter(
            Position = 2
        )]
        [UnixTime]$EndTime,

        # Sets the page size, i.e., the maximum number of items from the list to be returned for a single API request. If omitted, the default page size is used. The maximum page size for this endpoint is 500 items per page.
        [Parameter(
            Position = 3
        )]
        [int]$Limit,

        # The number of items in the list to skip over before starting to retrieve the items for the requested page. The default offset of 0 represents the beginning of the list, i.e., the start of the first page. To request the second page of the list, set the offset to the page size as determined by Limit. Use multiples of the page size as your offset to request further consecutive pages.
        [Parameter(
            Position = 4
        )]
        [int]$Offset,

        # Specifies an On Behalf Of header to allow you to make API calls from a parent account on behalf of the parent's Subusers or customer accounts.
        [Parameter()]
        [string]$OnBehalfOf
    )
    process {
        $InvokeSplat = @{
            Method        = 'Get'
            Namespace     = "suppression/blocks"
            ErrorAction   = 'Stop'
            CallingCmdlet = $PSCmdlet.MyInvocation.MyCommand.Name
        }
        if ($PSBoundParameters.OnBehalfOf) {
            $InvokeSplat.Add('OnBehalfOf', $OnBehalfOf)
        }
        #Generic List
        [System.Collections.Generic.List[string]]$QueryParameters = [System.Collections.Generic.List[string]]::new()

        if ($PSBoundParameters.StartTime) {
            $QueryParameters.Add("start_time=$($StartTime.ToUnixTime())")
        }
        if ($PSBoundParameters.EndTime) {
            $QueryParameters.Add("end_time=$($EndTime.ToUnixTime())")
        }
        if ($PSBoundParameters.Limit) {
            $QueryParameters.Add("limit=$limit")
        }
        else {
            $QueryParameters.Add("limit=100")
        }
        if ($PSBoundParameters.Offset) {
            $QueryParameters.Add("offset=$offset")
        }

        if ($QueryParameters.Count -gt 0 -or $PSBoundParameters.EmailAddress) {
            $InvokeSplat['Namespace'] += '?' + ($QueryParameters -join '&')
        }

        if ($PSBoundParameters.EmailAddress) {
            foreach ($Email in $EmailAddress) {
                $EmailInvokeSplat = $InvokeSplat.Clone()
                $EmailInvokeSplat['Namespace'] += "&email=$($Email.Address)"
                if ($EmailInvokeSplat['Namespace'] -match ('\?\&email=')) {
                    $EmailInvokeSplat['Namespace'] = $EmailInvokeSplat['Namespace'].Replace('?&email=', '?email=')
                }
                try {
                    Invoke-SendGrid @EmailInvokeSplat
                }
                catch {
                    Write-Error ('Failed to retrieve SendGrid block. {0}' -f $_.Exception.Message) -ErrorAction Stop
                }
            }
        }
        else {
            try {
                Invoke-SendGrid @InvokeSplat
            }
            catch {
                Write-Error ('Failed to retrieve all SendGrid blocks. {0}' -f $_.Exception.Message) -ErrorAction Stop
            }
        }
    }   
}
#EndRegion '.\Public\Get-SGBlock.ps1' 121
#Region '.\Public\Get-SGBounce.ps1' 0
function Get-SGBounce {
    <#
    .SYNOPSIS
        Retrieves all or specific bounces from SendGrid.
 
    .DESCRIPTION
        Get-SGBounce retrieves all bounces or a specific bounce based on its unique ID from SendGrid. Bounces occur when an email is rejected by the recipient's mail server.
 
    .PARAMETER UniqueId
        Specifies the UniqueId of a specific bounce to retrieve. If this parameter is not provided, all bounces are retrieved.
 
    .PARAMETER OnBehalfOf
        Specifies an On Behalf Of header to allow you to make API calls from a parent account on behalf of the parent's Subusers or customer accounts.
 
    .EXAMPLE
        PS C:\> Get-SGBounce
 
        Email : bounce1@example.com
        Status : 5.1.1
        Reason : Invalid Recipient
        Created : 2022-03-04 15:34:34
        Updated : 2022-03-04 15:34:34
        UniqueId : 13508031
        UserId : 8262273
 
        Email : bounce2@example.com
        Status : 5.1.1
        Reason : Invalid Recipient
        Created : 2021-11-12 07:38:27
        Updated : 2021-11-12 07:38:27
        UniqueId : 12589712
        UserId : 8262273
        ...
 
        This command retrieves all bounces from SendGrid.
 
    .EXAMPLE
        PS C:\> Get-SGBounce -EmailAddress bounce2@example.com
 
        Email : bounce2@example.com
        Status : 5.1.1
        Reason : Invalid Recipient
        Created : 2021-11-12 07:38:27
        Updated : 2021-11-12 07:38:27
        UniqueId : 12589712
        UserId : 8262273
 
        This command retrieves the bounce with the UniqueId '12589712' from SendGrid.
 
    .EXAMPLE
        PS C:\> Get-SGBounce -EmailAddress bounce2@example.com -OnBehalfOf 'Subuser'
 
        Email : bounce2@example.com
        Status : 5.1.1
        Reason : Invalid Recipient
        Created : 2021-11-12 07:38:27
        Updated : 2021-11-12 07:38:27
        UniqueId : 12589712
        UserId : 8262273
        Username : Subuser
 
        This command retrieves the bounce with the UniqueId '12589712' from SendGrid for the Subuser 'Subuser'.
    #>

    [CmdletBinding()]
    param (
        # Specifies the specific email address to retrieve. If this parameter is not provided, all bounces are retrieved.
        [Parameter(
            ValueFromPipeline,
            ValueFromPipelineByPropertyName,
            Position = 0
        )]
        [MailAddress[]]$EmailAddress,

        # Refers to the start of the time range in Unix timestamp when an invalid email was created (inclusive).
        [Parameter(
            Position = 1
        )]
        [UnixTime]$StartTime,

        # Refers to the end of the time range in Unix timestamp when an invalid email was created (inclusive).
        [Parameter(
            Position = 2
        )]
        [UnixTime]$EndTime,

        # Sets the page size, i.e., the maximum number of items from the list to be returned for a single API request. If omitted, the default page size is used. The maximum page size for this endpoint is 500 items per page.
        [Parameter(
            Position = 3
        )]
        [int]$Limit,

        # The number of items in the list to skip over before starting to retrieve the items for the requested page. The default offset of 0 represents the beginning of the list, i.e., the start of the first page. To request the second page of the list, set the offset to the page size as determined by Limit. Use multiples of the page size as your offset to request further consecutive pages.
        [Parameter(
            Position = 4
        )]
        [int]$Offset,

        # Specifies an On Behalf Of header to allow you to make API calls from a parent account on behalf of the parent's Subusers or customer accounts.
        [Parameter()]
        [string]$OnBehalfOf
    )
    process {
        $InvokeSplat = @{
            Method        = 'Get'
            Namespace     = 'suppression/bounces'
            ErrorAction   = 'Stop'
            CallingCmdlet = $PSCmdlet.MyInvocation.MyCommand.Name
        }
        if ($PSBoundParameters.OnBehalfOf) {
            $InvokeSplat.Add('OnBehalfOf', $OnBehalfOf)
        }
        #Generic List
        [System.Collections.Generic.List[string]]$QueryParameters = [System.Collections.Generic.List[string]]::new()

        if ($PSBoundParameters.StartTime) {
            $QueryParameters.Add("start_time=$($StartTime.ToUnixTime())")
        }
        if ($PSBoundParameters.EndTime) {
            $QueryParameters.Add("end_time=$($EndTime.ToUnixTime())")
        }
        if ($PSBoundParameters.Limit) {
            $QueryParameters.Add("limit=$limit")
        }
        else {
            $QueryParameters.Add("limit=100")
        }
        if ($PSBoundParameters.Offset) {
            $QueryParameters.Add("offset=$offset")
        }

        if ($QueryParameters.Count -gt 0 -or $PSBoundParameters.EmailAddress) {
            $InvokeSplat['Namespace'] += '?' + ($QueryParameters -join '&')
        }

        if ($PSBoundParameters.EmailAddress) {
            foreach ($Email in $EmailAddress) {
                $EmailInvokeSplat = $InvokeSplat.Clone()
                $EmailInvokeSplat['Namespace'] += "&email=$($Email.Address)"
                if ($EmailInvokeSplat['Namespace'] -match ('\?\&email=')) {
                    $EmailInvokeSplat['Namespace'] = $EmailInvokeSplat['Namespace'].Replace('?&email=', '?email=')
                }
                try {
                    Invoke-SendGrid @EmailInvokeSplat
                }
                catch {
                    Write-Error ('Failed to retrieve SendGrid bounce. {0}' -f $_.Exception.Message) -ErrorAction Stop
                }
            }
        }
        else {
            try {
                Invoke-SendGrid @InvokeSplat
            }
            catch {
                Write-Error ('Failed to retrieve all SendGrid bounces. {0}' -f $_.Exception.Message) -ErrorAction Stop
            }
        }
    }   
}
#EndRegion '.\Public\Get-SGBounce.ps1' 160
#Region '.\Public\Get-SGBounceByClassification.ps1' 0
function Get-SGBounceByClassification {
    <#
    .SYNOPSIS
        Retrieves bounce totals by classification from SendGrid.
 
    .DESCRIPTION
        Get-SGBounceByClassification retrieves the total number of bounces by classification in descending order for each day from SendGrid. Bounces can be classified as permanent or temporary failures to deliver the message.
 
    .PARAMETER StartDate
        Specifies the start date of the time range when a bounce was created (inclusive) in YYYY-MM-DD format.
 
    .PARAMETER EndDate
        Specifies the end date of the time range when a bounce was created (inclusive) in YYYY-MM-DD format.
 
    .PARAMETER OnBehalfOf
        Specifies an On Behalf Of header to allow you to make API calls from a parent account on behalf of the parent's Subusers or customer accounts.
 
 
    .EXAMPLE
        PS C:\> Get-SGBounceByClassification
 
        Classification : 5.1.1
        TotalBounces : 100
 
        Classification : 4.0.0
        TotalBounces : 50
 
        This command retrieves the bounce totals by classification for the time range from '2022-01-01' to '2022-01-31' from SendGrid.
 
    .EXAMPLE
        PS C:\> Get-SGBounceByClassification -StartDate '2022-01-01' -EndDate '2022-01-31' -OnBehalfOf 'Subuser'
 
        Classification : 5.1.1
        TotalBounces : 100
 
        Classification : 4.0.0
        TotalBounces : 50
        Username : Subuser
 
        This command retrieves the bounce totals by classification for the time range from '2022-01-01' to '2022-01-31' from SendGrid for the Subuser 'Subuser'.
    #>

    [CmdletBinding()]
    param (
        # Specifies the Classification of the bounce.
        [Parameter(
            Position = 0
        )]
        [ValidateSet('Content', 'Frequency or Volume Too High', 'Invalid Address', 'Mailbox Unavailable', 'Reputation', 'Technical Failure', 'Unclassified')]
        [string]$Classification,
        
        # Specifies the start date of the time range when a bounce was created (inclusive). Both datetime and unix timestamp formats are accepted.
        [Parameter(
            Position = 1
        )]
        [UnixTime]$StartDate,

        # Specifies the end date of the time time range when a bounce was created (inclusive). Both datetime and unix timestamp formats are accepted.
        [Parameter(
            Position = 2
        )]
        [UnixTime]$EndDate,

        # Specifies an On Behalf Of header to allow you to make API calls from a parent account on behalf of the parent's Subusers or customer accounts.
        [Parameter()]
        [string]$OnBehalfOf
    )
    process {
        $InvokeSplat = @{
            Method        = 'Get'
            Namespace     = 'suppression/bounces/classifications'
            ErrorAction   = 'Stop'
            CallingCmdlet = $PSCmdlet.MyInvocation.MyCommand.Name
        }
        if ($PSBoundParameters.Classification) {
            $InvokeSplat['Namespace'] = "suppression/bounces/classifications/$Classification"
        }
        if ($PSBoundParameters.OnBehalfOf) {
            $InvokeSplat.Add('OnBehalfOf', $OnBehalfOf)
        }

        #Generic List
        [System.Collections.Generic.List[string]]$QueryParameters = [System.Collections.Generic.List[string]]::new()

        if ($PSBoundParameters.StartDate) {
            $QueryParameters.Add("start_date=$($StartDate.ToSendGridTime())")
        }
        if ($PSBoundParameters.EndDate) {
            $QueryParameters.Add("end_date=$($EndDate.ToSendGridTime())")
        }
        if ($QueryParameters.Count -gt 0) {
            $InvokeSplat['Namespace'] += '?' + ($QueryParameters -join '&')
        }

        try {
            Invoke-SendGrid @InvokeSplat
        }
        catch {
            Write-Error ('Failed to retrieve SendGrid bounce classifications. {0}' -f $_.Exception.Message) -ErrorAction Stop
        }
    }
}
#EndRegion '.\Public\Get-SGBounceByClassification.ps1' 102
#Region '.\Public\Get-SGBouncePurgeSetting.ps1' 0
function Get-SGBouncePurgeSetting {
    <#
    .SYNOPSIS
        Retrieves the bounce purge mail settings on SendGrid.
    .DESCRIPTION
        Get-SGBouncePurgeSetting retrieves the bounce purge mail settings on SendGrid.
    .EXAMPLE
        PS C:\> Get-SGBouncePurgeSetting
        This command retrieves the bounce purge mail settings on SendGrid.
    .NOTES
        To use this function, you must be connected to a SendGrid instance. Use the Connect-SendGrid function to establish a connection.
    #>

    [CmdletBinding()]
    param (
        # Specifies an On Behalf Of header to allow you to make API calls from a parent account on behalf of the parent's Subusers or customer accounts.
        [Parameter()]
        [string]$OnBehalfOf
    )
    process {
        $InvokeSplat = @{
            Method        = 'Get'
            Namespace     = 'mail_settings/bounce_purge'
            ErrorAction   = 'Stop'
            CallingCmdlet = $PSCmdlet.MyInvocation.MyCommand.Name
        }

        if ($PSBoundParameters.OnBehalfOf) {
            $InvokeSplat.Add('OnBehalfOf', $OnBehalfOf)
        }
        
        try {
            Invoke-SendGrid @InvokeSplat
        }
        catch {
            Write-Error ('Failed to retrieve SendGrid bounce purge settings. {0}' -f $_.Exception.Message) -ErrorAction Stop
        }
    }
}
#EndRegion '.\Public\Get-SGBouncePurgeSetting.ps1' 39
#Region '.\Public\Get-SGBrandedDomainLink.ps1' 0
function Get-SGBrandedDomainLink {
    <#
    .SYNOPSIS
        Retrieves all or specific Branded Domain Links within the current SendGrid instance.
         
    .DESCRIPTION
        Get-SGBrandedDomainLink retrieves all Branded Domain Links or a specific Branded Domain Link based on its unique ID
        within the current SendGrid instance. Branded Domain Links allow all of the click-tracked links, opens, and images in your
        emails to be served from your domain rather than sendgrid.net, which aids in spam filter and recipient server assessments
        of email trustworthiness.
 
    .PARAMETER UniqueId
        Specifies the UniqueId of a specific Branded Domain Link to retrieve. If this parameter is not provided, all Branded Domain Links are retrieved.
 
    .EXAMPLE
        PS C:\> Get-SGBrandedDomainLink
         
        Domain : sending.example.com
        Subdomain : sg
        User : Top Account
        Valid : True
        Default : False
        ValidationAttempt : 2022-03-04 15:34:34
        DNS : @{DomainCNAME=; OwnerCNAME=}
        UniqueId : 13508031
        UserId : 8262273
 
        Domain : email.example.com
        Subdomain : url6142
        User : Top Account
        Valid : True
        Default : False
        ValidationAttempt : 2021-11-12 07:38:12
        DNS : @{DomainCNAME=; OwnerCNAME=}
        UniqueId : 12589712
        UserId : 8262273
        ...
 
        This command retrieves all Branded Domain Links within the current SendGrid instance.
 
    .EXAMPLE
        PS C:\> Get-SGBrandedDomainLink -UniqueId '12589712'
 
        Domain : email.example.com
        Subdomain : url6142
        User : Top Account
        Valid : True
        Default : False
        ValidationAttempt : 2021-11-12 07:38:12
        DNS : @{DomainCNAME=; OwnerCNAME=}
        UniqueId : 12589712
        UserId : 8262273
 
        This command retrieves the Branded Domain Link with the UniqueId '12589712' within the current SendGrid instance.
 
    .EXAMPLE
        PS C:\> Get-SGBrandedDomainLink -OnBehalfOf 'Subuser'
 
        Domain : email.example.com
        Subdomain : url6142
        User : Top Account
        Valid : True
        Default : False
        ValidationAttempt : 2021-11-12 07:38:12
        DNS : @{DomainCNAME=; OwnerCNAME=}
        UniqueId : 12589712
        UserId : 8262273
 
        This command retrieves all Branded Domain Links within the current SendGrid instance on behalf of the specified subuser.
 
    .NOTES
        To use this function, you must be connected to a SendGrid instance. Use the Connect-SendGrid function to establish a connection.
    #>

    [CmdletBinding(
        SupportsShouldProcess
    )]
    param (

        # Specifies a UniqueId to retrieve
        [Parameter(
            ValueFromPipeline,
            ValueFromPipelineByPropertyName,
            Position = 0
        )]
        [Alias('Id')]
        [string]$UniqueId,

        # Specifies if the DNS records should be shown.
        [Parameter()]
        [switch]$ShowDNS,

        # Specifies a On Behalf Of header to allow you to make API calls from a parent account on behalf of the parent's Subusers or customer accounts.
        [Parameter()]
        [string]$OnBehalfOf
    )
    DynamicParam {
        # Create a dictionary to hold the dynamic parameters
        $ParamDictionary = [System.Management.Automation.RuntimeDefinedParameterDictionary]::new()
        if ($null -eq $UniqueId) {
            # Create the Equal parameter attribute
            $DomainNameParamAttribute = [System.Management.Automation.ParameterAttribute]::new()
            $DomainNameParamAttribute.ParameterSetName = 'DomainNameSet'

            # Add the parameter attributes to an attribute collection
            $DomainNameAttributeCollection = [System.Collections.ObjectModel.Collection[System.Attribute]]::new()
            $DomainNameAttributeCollection.Add($DomainNameParamAttribute)

            # Add ValidateSet to the parameter
            $script:SGDomains = Invoke-SGCommand -Namespace 'whitelabel/links' # Can't reference self Get-SGAuthenticatedDomain.
            $DomainNameValidateSet = [System.Management.Automation.ValidateSetAttribute]::new([string[]]$script:SGDomains.Domain)
            $DomainNameAttributeCollection.Add($DomainNameValidateSet)

            # Add Alias to the parameter
            $DomainNameAliasAttribute = [System.Management.Automation.AliasAttribute]::new('Domain')
            $DomainNameAttributeCollection.Add($DomainNameAliasAttribute)

            # Create the actual parameter(s)
            $DomainNameParam = [System.Management.Automation.RuntimeDefinedParameter]::new('DomainName', [string[]], $DomainNameAttributeCollection)

            # Push the parameter(s) into a parameter dictionary
            $ParamDictionary.Add('DomainName', $DomainNameParam)
        }
        return $ParamDictionary
    }
    process {
        $InvokeSplat = @{
            Method        = 'Get'
            Namespace     = 'whitelabel/links'
            ErrorAction   = 'Stop'
            CallingCmdlet = $PSCmdlet.MyInvocation.MyCommand.Name
        }

        # Get-SGBrandedDomainLink -ShowDNS'
        if ($PSBoundParameters.ShowDNS) {
            $InvokeSplat['CallingCmdlet'] = "$($PSCmdlet.MyInvocation.MyCommand.Name) -ShowDNS"
        }

        if ($PSBoundParameters.OnBehalfOf) {
            $InvokeSplat.Add('OnBehalfOf', $OnBehalfOf)
        }
        if ($null -ne ($PSBoundParameters['DomainName'])) {
            $UniqueId = ($script:SGDomains | Where-Object { $_.Domain -eq ($PSBoundParameters['DomainName']) }).Id
        }
        if ($PSBoundParameters.UniqueId -or $PSBoundParameters.DomainName) {
            foreach ($Id in $UniqueId) {
                if ($PSCmdlet.ShouldProcess(('{0}' -f $Id))) {
                    $InvokeSplat['Namespace'] = "whitelabel/links/$Id"
                    try {
                        Invoke-SendGrid @InvokeSplat
                    }
                    catch {
                        Write-Error ('Failed to retrieve SendGrid SendGrid Branded Domain Link. {0}' -f $_.Exception.Message) -ErrorAction Stop
                    }
                }
            }
        }
        else {
            if ($PSCmdlet.ShouldProcess(('{0}' -f 'All Branded Domain Links'))) {
                try {
                    Invoke-SendGrid @InvokeSplat
                }
                catch {
                    Write-Error ('Failed to retrieve all SendGrid SendGrid Branded Domain Links. {0}' -f $_.Exception.Message) -ErrorAction Stop
                }
            }
        }
    }
}
#EndRegion '.\Public\Get-SGBrandedDomainLink.ps1' 169
#Region '.\Public\Get-SGDesign.ps1' 0
function Get-SGDesign {
    <#
    .SYNOPSIS
        WARNING NOT FULLY TESTED
        Retrieves a list of designs stored in the Twilio SendGrid Design Library.
 
    .DESCRIPTION
        Get-SGDesign retrieves a list of designs stored in the Twilio SendGrid Design Library.
        This function does not return the pre-built Twilio SendGrid designs.
 
    .PARAMETER PageSize
        Specifies the number of results to return. The default is 100.
 
    .PARAMETER PageToken
        Specifies the token corresponding to a specific page of results, as provided by metadata.
 
    .PARAMETER Summary
        Set to false to return all fields. The default is true.
 
    .EXAMPLE
        PS C:\> Get-SGDesign -PageSize 50 -PageToken 'token'
        This command retrieves a specific page of designs with a page size of 50.
    .EXAMPLE
        PS C:\> Get-SGDesign -PageSize 100 -Summary $false -OnBehalfOf 'Subuser'
        This command retrieves all fields of the first page of designs with a page size of 100 on behalf of the Subuser 'Subuser'.
    #>

    [CmdletBinding()]
    param (
        [Parameter(
            Position = 0
        )]
        [int]$PageSize = 100,
        [Parameter(
            Position = 1
        )]
        [string]$PageToken,
        [Parameter(
            Position = 2
        )]
        [switch]$Summary
    )
    process {
        $InvokeSplat = @{
            Method        = 'Get'
            Namespace     = 'designs'
            ErrorAction   = 'Stop'
            CallingCmdlet = $PSCmdlet.MyInvocation.MyCommand.Name
        }

        #Generic List
        [System.Collections.Generic.List[string]]$QueryParameters = [System.Collections.Generic.List[string]]::new()

        if ($PSBoundParameters.PageSize) {
            $QueryParameters.Add("page_size=$($PageSize))")
        }
        if ($PSBoundParameters.PageToken) {
            $QueryParameters.Add("page_token=$($PageToken)")
        }
        if ($PSBoundParameters.Summary) {
            $QueryParameters.Add("summary=$($Summary.IsPresent)")
        }

        if ($QueryParameters.Count) {
            $InvokeSplat['Namespace'] += '?' + ($QueryParameters -join '&')
        }
        try {
            Invoke-SendGrid @InvokeSplat
        }
        catch {
            Write-Error ('Failed to retrieve SendGrid Design. {0}' -f $_.Exception.Message) -ErrorAction Stop
        }
    }
}
#EndRegion '.\Public\Get-SGDesign.ps1' 74
#Region '.\Public\Get-SGEmailActivity.ps1' 0
function Get-SGEmailActivity {
    <#
    .SYNOPSIS
        Retrieves email activity from SendGrid based on the provided query.
    .DESCRIPTION
        Get-SGEmailActivity uses the SendGrid Email Activity API to filter and retrieve email activity.
        For example, you can retrieve all bounced messages or all messages with the same subject line.
    .PARAMETER Query
        Specifies the query to filter email activity. The query must be URL encoded and use the following format: query={query_type}="{query_content}".
    .PARAMETER Limit
        Sets the number of messages to be returned. This parameter must be greater than 0 and less than or equal to 1000. If omitted, the default is 10.
    .EXAMPLE
        PS C:\> Get-SGEmailActivity -Query "to_email%3D%22example%40example.com%22" -Limit 50
        This command retrieves the email activity for the email address 'example@example.com' with a limit of 50 messages.
    #>

    [CmdletBinding(
        DefaultParameterSetName = 'PropertySet'
    )]
    [Alias('Get-SGActivity')]
    param (
        [Parameter(
            Position = 0,
            Mandatory = $true,
            ParameterSetName = 'PropertySet'
        )]
        [Alias('Object')]
        [ValidateSet('ApiKeyId', 'ApiKeyName', 'AsmGroupId', 'AsmGroupName', 'Categories', 'Clicks', 'Events', 'FromEmail', 'LastEventTime', 'MarketingCampaignId', 'MarketingCampaignName', 'MessageId', 'OutboundIp', 'Status', 'Subject', 'Teammate', 'TemplateId', 'TemplateName', 'ToEmail')]
        [string]$Property,

        # Specifies the query to filter email activity. Use native PowerShell operators, the query will automatically be URL encoded.
        [Parameter(
            ParameterSetName = 'FilterSet',
            Position = 0,
            Mandatory
        )]
        [string]$Filter,

        # Specifies the a raw SendGrid query to filter email activity. The query will not be URL encoded. Therefor, you must provide a URL encoded query.
        [Parameter(
            ParameterSetName = 'SendGridFilterSet',
            Position = 0,
            Mandatory
        )]
        [string]$SendGridFilter,
        
        [Parameter(ParameterSetName = 'PropertySet')]
        [Parameter(ParameterSetName = 'FilterSet')]
        [Parameter(ParameterSetName = 'SendGridFilterSet')]
        [ValidateRange(1, 1000)]
        [int]$Limit = 10
    )
    DynamicParam {
        # Create a dictionary to hold the dynamic parameters
        $ParamDictionary = [System.Management.Automation.RuntimeDefinedParameterDictionary]::new()
        if ($null -eq $Filter -and  $null -eq $SendGridFilter) {
            if ($Property -notmatch 'LastEventTime|Events') {
                # Create the Equal parameter attribute
                $EqualParamAttribute = [System.Management.Automation.ParameterAttribute]::new()

                # Create the NotEqual parameter attribute
                $NotEqualParamAttribute = [System.Management.Automation.ParameterAttribute]::new()

                # Add the parameter attributes to an attribute collection
                $EqualAttributeCollection = [System.Collections.ObjectModel.Collection[System.Attribute]]::new()
                $EqualAttributeCollection.Add($EqualParamAttribute)
                $NotEqualAttributeCollection = [System.Collections.ObjectModel.Collection[System.Attribute]]::new()
                $NotEqualAttributeCollection.Add($NotEqualParamAttribute)

                # Add Alias to the parameter
                $EQAliasAttribute = [System.Management.Automation.AliasAttribute]::new('Equals')
                $NEAliasAttribute = [System.Management.Automation.AliasAttribute]::new('NotEquals')
                $EqualAttributeCollection.Add($EQAliasAttribute)
                $NotEqualAttributeCollection.Add($NEAliasAttribute)

                # Create the actual parameter(s)
                $EqualParam = [System.Management.Automation.RuntimeDefinedParameter]::new('EQ', [switch], $EqualAttributeCollection)
                $NotEqualParam = [System.Management.Automation.RuntimeDefinedParameter]::new('NE', [switch], $NotEqualAttributeCollection)

                # Push the parameter(s) into a parameter dictionary
                $ParamDictionary.Add('EQ', $EqualParam)
                $ParamDictionary.Add('NE', $NotEqualParam)
            }
            if ($Property -eq 'Clicks') {
                # Create the GreaterThan parameter attribute
                $GTParamAttribute = [System.Management.Automation.ParameterAttribute]::new()

                # Create the LessThan parameter attribute
                $LTParamAttribute = [System.Management.Automation.ParameterAttribute]::new()

                # Add the parameter attributes to an attribute collection
                $GTAttributeCollection = [System.Collections.ObjectModel.Collection[System.Attribute]]::new()
                $GTAttributeCollection.Add($GTParamAttribute)
                $LTAttributeCollection = [System.Collections.ObjectModel.Collection[System.Attribute]]::new()
                $LTAttributeCollection.Add($LTParamAttribute)

                # Add Alias to the parameter
                $GTAliasAttribute = [System.Management.Automation.AliasAttribute]::new('GreaterThan')
                $GTAttributeCollection.Add($GTAliasAttribute)
                $LTAliasAttribute = [System.Management.Automation.AliasAttribute]::new('LessThan')
                $LTAttributeCollection.Add($LTAliasAttribute)

                # Create the actual parameter(s)
                $GTParam = [System.Management.Automation.RuntimeDefinedParameter]::new('GT', [switch], $GTAttributeCollection)
                $LTParam = [System.Management.Automation.RuntimeDefinedParameter]::new('LT', [switch], $LTAttributeCollection)

                # Push the parameter(s) into a parameter dictionary
                $ParamDictionary.Add('GT', $GTParam)
                $ParamDictionary.Add('LT', $LTParam)
            }
            if ($Property -match 'TemplateId|TemplateName|OriginatingIp|OutboundIp|Events|MarketingCampaignName|MarketingCampaignId|Categories|AsmGroupId|AsmGroupName|Teammate') {
                # Create the Contains parameter attribute
                $ContainsParamAttribute = [System.Management.Automation.ParameterAttribute]::new()

                # Create the NotContains parameter attribute
                $NotContainsParamAttribute = [System.Management.Automation.ParameterAttribute]::new()

                # Add the parameter attributes to an attribute collection
                $ContainsAttributeCollection = [System.Collections.ObjectModel.Collection[System.Attribute]]::new()
                $ContainsAttributeCollection.Add($ContainsParamAttribute)
                $NotContainsAttributeCollection = [System.Collections.ObjectModel.Collection[System.Attribute]]::new()
                $NotContainsAttributeCollection.Add($NotContainsParamAttribute)

                # Create the actual Contains parameter
                $ContainsParam = [System.Management.Automation.RuntimeDefinedParameter]::new('Contains', [switch], $ContainsAttributeCollection)
                $NotContainsParam = [System.Management.Automation.RuntimeDefinedParameter]::new('NotContains', [switch], $NotContainsAttributeCollection)

                # Push the parameter(s) into a parameter dictionary
                $ParamDictionary.Add('Contains', $ContainsParam)
                $ParamDictionary.Add('NotContains', $NotContainsParam)
            }
            if ($Property -match 'Subject|TemplateId|MarketingCampaignName|MarketingCampaignId|ApiKeyId|Categories|OutboundIp|Clicks|AsmGroupId|Teammate|Events') {
                # Create the IsEmpty parameter attribute
                $IsEmptyParamAttribute = [System.Management.Automation.ParameterAttribute]::new()

                # Create the IsNotEmpty parameter attribute
                $IsNotEmptyParamAttribute = [System.Management.Automation.ParameterAttribute]::new()

                # Add the parameter attributes to an attribute collection
                $IsEmptyAttributeCollection = [System.Collections.ObjectModel.Collection[System.Attribute]]::new()
                $IsEmptyAttributeCollection.Add($IsEmptyParamAttribute)
                $IsNotEmptyAttributeCollection = [System.Collections.ObjectModel.Collection[System.Attribute]]::new()
                $IsNotEmptyAttributeCollection.Add($IsNotEmptyParamAttribute)

                # Create the actual Contains parameter
                $IsEmptyParam = [System.Management.Automation.RuntimeDefinedParameter]::new('IsEmpty', [switch], $IsEmptyAttributeCollection)
                $IsNotEmptyParam = [System.Management.Automation.RuntimeDefinedParameter]::new('IsNotEmpty', [switch], $IsNotEmptyAttributeCollection)

                # Push the parameter(s) into a parameter dictionary
                $ParamDictionary.Add('IsEmpty', $IsEmptyParam)
                $ParamDictionary.Add('IsNotEmpty', $IsNotEmptyParam)
            }
            if ($Property -match 'MessageId|FromEmail|Subject|ToEmail|OutboundIp|OriginatingIp') {
                # Create the Like parameter attribute
                $LikeParamAttribute = [System.Management.Automation.ParameterAttribute]::new()

                # Create the IsNotEmpty parameter attribute
                $NotLikeParamAttribute = [System.Management.Automation.ParameterAttribute]::new()
                # Add the parameter attributes to an attribute collection
                $LikeAttributeCollection = [System.Collections.ObjectModel.Collection[System.Attribute]]::new()
                $LikeAttributeCollection.Add($LikeParamAttribute)
                $NotLikeAttributeCollection = [System.Collections.ObjectModel.Collection[System.Attribute]]::new()
                $NotLikeAttributeCollection.Add($NotLikeParamAttribute)

                # Create the actual Contains parameter
                $LikeParam = [System.Management.Automation.RuntimeDefinedParameter]::new('Like', [switch], $LikeAttributeCollection)
                $NotLikeParam = [System.Management.Automation.RuntimeDefinedParameter]::new('NotLike', [switch], $NotLikeAttributeCollection)

                # Push the parameter(s) into a parameter dictionary
                $ParamDictionary.Add('Like', $LikeParam)
                $ParamDictionary.Add('NotLike', $NotLikeParam)
            }
            #region Value Properties
            if ($Property -match 'MessageId|FromEmail|Subject|ToEmail|OutboundIp|OriginatingIp') {
                # Create the Value parameter attribute
                $ValueParamAttribute = [System.Management.Automation.ParameterAttribute]::new()
                $ValueParamAttribute.Position = 2
                $ValueParamAttribute.ParameterSetName = $PSCmdlet.ParameterSetName

                # Add the parameter attributes to an attribute collection
                $ValueAttributeCollection = [System.Collections.ObjectModel.Collection[System.Attribute]]::new()
                $ValueAttributeCollection.Add($ValueParamAttribute)

                # Create the actual Value parameter
                $ValueParam = [System.Management.Automation.RuntimeDefinedParameter]::new('Value', [string[]], $ValueAttributeCollection)

                # Push the parameter(s) into a parameter dictionary
                $ParamDictionary.Add('Value', $ValueParam)
            }
            if ($Property -eq 'Clicks') {
                # Create the Value parameter attribute
                $ValueParamAttribute = [System.Management.Automation.ParameterAttribute]::new()
                $ValueParamAttribute.Position = 2
                $ValueParamAttribute.ParameterSetName = $PSCmdlet.ParameterSetName

                # Add the parameter attributes to an attribute collection
                $ValueAttributeCollection = [System.Collections.ObjectModel.Collection[System.Attribute]]::new()
                $ValueAttributeCollection.Add($ValueParamAttribute)

                # Create the actual Value parameter
                $ValueParam = [System.Management.Automation.RuntimeDefinedParameter]::new('Value', [Int32], $ValueAttributeCollection)

                # Push the parameter(s) into a parameter dictionary
                $ParamDictionary.Add('Value', $ValueParam)
            }
            if ($Property -eq 'Status') {
                # Create the Value parameter attribute
                $ValueParamAttribute = [System.Management.Automation.ParameterAttribute]::new()
                $ValueParamAttribute.Position = 2
                $ValueParamAttribute.ParameterSetName = $PSCmdlet.ParameterSetName

                # Add the parameter attributes to an attribute collection
                $ValueAttributeCollection = [System.Collections.ObjectModel.Collection[System.Attribute]]::new()
                $ValueAttributeCollection.Add($ValueParamAttribute)

                # Add ValidateSet to the parameter
                $StatusValidateSet = [System.Management.Automation.ValidateSetAttribute]::new('delivered', 'not_delivered', 'processing')
                $ValueAttributeCollection.Add($StatusValidateSet)

                # Create the actual Value parameter
                $ValueParam = [System.Management.Automation.RuntimeDefinedParameter]::new('Value', [string[]], $ValueAttributeCollection)

                # Push the parameter(s) into a parameter dictionary
                $ParamDictionary.Add('Value', $ValueParam)
            }
            if ($Property -eq 'Events') {
                # Create the Value parameter attribute
                $ValueParamAttribute = [System.Management.Automation.ParameterAttribute]::new()
                $ValueParamAttribute.Position = 2
                $ValueParamAttribute.ParameterSetName = $PSCmdlet.ParameterSetName

                # Add the parameter attributes to an attribute collection
                $ValueAttributeCollection = [System.Collections.ObjectModel.Collection[System.Attribute]]::new()
                $ValueAttributeCollection.Add($ValueParamAttribute)

                # Add ValidateSet to the parameter
                $StatusValidateSet = [System.Management.Automation.ValidateSetAttribute]::new('processed', 'deferred', 'delivered', 'bounce', 'open', 'click', 'dropped', 'spamreport', 'unsubscribe', 'group_unsubscribe', 'group_resubscribe')
                $ValueAttributeCollection.Add($StatusValidateSet)

                # Create the actual Value parameter
                $ValueParam = [System.Management.Automation.RuntimeDefinedParameter]::new('Value', [string[]], $ValueAttributeCollection)

                # Push the parameter(s) into a parameter dictionary
                $ParamDictionary.Add('Value', $ValueParam)
            }
            if ($Property -eq 'TemplateId') {
                # Create the Value parameter attribute
                $ValueParamAttribute = [System.Management.Automation.ParameterAttribute]::new()
                $ValueParamAttribute.Position = 2
                $ValueParamAttribute.ParameterSetName = $PSCmdlet.ParameterSetName

                # Add the parameter attributes to an attribute collection
                $ValueAttributeCollection = [System.Collections.ObjectModel.Collection[System.Attribute]]::new()
                $ValueAttributeCollection.Add($ValueParamAttribute)

                # Add ValidateSet to the parameter
                $script:Templates = Get-SGTemplate
                $StatusValidateSet = [System.Management.Automation.ValidateSetAttribute]::new($Templates.TemplateId)
                $ValueAttributeCollection.Add($StatusValidateSet)

                # Create the actual Value parameter
                $ValueParam = [System.Management.Automation.RuntimeDefinedParameter]::new('Value', [string[]], $ValueAttributeCollection)

                # Push the parameter(s) into a parameter dictionary
                $ParamDictionary.Add('Value', $ValueParam)
            }
            if ($Property -eq 'TemplateName') {
                # Create the Value parameter attribute
                $ValueParamAttribute = [System.Management.Automation.ParameterAttribute]::new()
                $ValueParamAttribute.Position = 2
                $ValueParamAttribute.ParameterSetName = $PSCmdlet.ParameterSetName

                # Add the parameter attributes to an attribute collection
                $ValueAttributeCollection = [System.Collections.ObjectModel.Collection[System.Attribute]]::new()
                $ValueAttributeCollection.Add($ValueParamAttribute)

                # Add ValidateSet to the parameter
                $script:Templates = Get-SGTemplate
                $StatusValidateSet = [System.Management.Automation.ValidateSetAttribute]::new([string[]]$Templates.TemplateName)
                $ValueAttributeCollection.Add($StatusValidateSet)

                # Create the actual Value parameter
                $ValueParam = [System.Management.Automation.RuntimeDefinedParameter]::new('Value', [string[]], $ValueAttributeCollection)

                # Push the parameter(s) into a parameter dictionary
                $ParamDictionary.Add('Value', $ValueParam)
            }
            if ($Property -eq 'MarketingCampaignId') {
                Write-Warning -Message 'The MarketingCampaignId property is not yet implemented'
                <#
            # Create the Value parameter attribute
            $ValueParamAttribute = [System.Management.Automation.ParameterAttribute]::new()
            $ValueParamAttribute.Position = 2
            $ValueParamAttribute.ParameterSetName = $PSCmdlet.ParameterSetName
 
            # Add the parameter attributes to an attribute collection
            $ValueAttributeCollection = [System.Collections.ObjectModel.Collection[System.Attribute]]::new()
            $ValueAttributeCollection.Add($ValueParamAttribute)
 
            # Add ValidateSet to the parameter
            $Campaigns = Get-SGCampaign
            $StatusValidateSet = [System.Management.Automation.ValidateSetAttribute]::new($Campaigns.CampaignId)
            $ValueAttributeCollection.Add($StatusValidateSet)
 
            # Create the actual Value parameter
            $ValueParam = [System.Management.Automation.RuntimeDefinedParameter]::new('Value', [string], $ValueAttributeCollection)
 
            # Push the parameter(s) into a parameter dictionary
            $ParamDictionary.Add('Value', $ValueParam)
            #>

            }

            if ($Property -eq 'MarketingCampaignName') {
                Write-Warning -Message 'The MarketingCampaignName property is not yet implemented'
                <#
            # Create the Value parameter attribute
            $ValueParamAttribute = [System.Management.Automation.ParameterAttribute]::new()
            $ValueParamAttribute.Position = 2
            $ValueParamAttribute.ParameterSetName = $PSCmdlet.ParameterSetName
 
            # Add the parameter attributes to an attribute collection
            $ValueAttributeCollection = [System.Collections.ObjectModel.Collection[System.Attribute]]::new()
            $ValueAttributeCollection.Add($ValueParamAttribute)
 
            # Add ValidateSet to the parameter
            $Campaigns = Get-SGCampaign
            $StatusValidateSet = [System.Management.Automation.ValidateSetAttribute]::new($Campaigns.CampaignName)
            $ValueAttributeCollection.Add($StatusValidateSet)
 
            # Create the actual Value parameter
            $ValueParam = [System.Management.Automation.RuntimeDefinedParameter]::new('Value', [string], $ValueAttributeCollection)
 
            # Push the parameter(s) into a parameter dictionary
            $ParamDictionary.Add('Value', $ValueParam)
            #>

            }
            if ($Property -eq 'ApiKeyId') {
                # Create the Value parameter attribute
                $ValueParamAttribute = [System.Management.Automation.ParameterAttribute]::new()
                $ValueParamAttribute.Position = 2
                $ValueParamAttribute.ParameterSetName = $PSCmdlet.ParameterSetName

                # Add the parameter attributes to an attribute collection
                $ValueAttributeCollection = [System.Collections.ObjectModel.Collection[System.Attribute]]::new()
                $ValueAttributeCollection.Add($ValueParamAttribute)

                # Add ValidateSet to the parameter
                $script:APIKeys = Get-SGApiKey
                $StatusValidateSet = [System.Management.Automation.ValidateSetAttribute]::new([string[]]$APIKeys.ApiKeyId)
                $ValueAttributeCollection.Add($StatusValidateSet)

                # Create the actual Value parameter
                $ValueParam = [System.Management.Automation.RuntimeDefinedParameter]::new('Value', [string[]], $ValueAttributeCollection)

                # Push the parameter(s) into a parameter dictionary
                $ParamDictionary.Add('Value', $ValueParam)
            }
            if ($Property -eq 'ApiKeyName') {
                # Create the Value parameter attribute
                $ValueParamAttribute = [System.Management.Automation.ParameterAttribute]::new()
                $ValueParamAttribute.Position = 2
                $ValueParamAttribute.ParameterSetName = $PSCmdlet.ParameterSetName

                # Add the parameter attributes to an attribute collection
                $ValueAttributeCollection = [System.Collections.ObjectModel.Collection[System.Attribute]]::new()
                $ValueAttributeCollection.Add($ValueParamAttribute)

                # Add ValidateSet to the parameter
                $script:APIKeys = Get-SGApiKey
                $StatusValidateSet = [System.Management.Automation.ValidateSetAttribute]::new([string[]]$APIKeys.Name)
                $ValueAttributeCollection.Add($StatusValidateSet)

                # Create the actual Value parameter
                $ValueParam = [System.Management.Automation.RuntimeDefinedParameter]::new('Value', [string[]], $ValueAttributeCollection)

                # Push the parameter(s) into a parameter dictionary
                $ParamDictionary.Add('Value', $ValueParam)
            }
            <# NOT YET IMPLEMENTED
        if ($Property -eq 'Categories') {
            # Create the Value parameter attribute
            $ValueParamAttribute = [System.Management.Automation.ParameterAttribute]::new()
            $ValueParamAttribute.Position = 2
            $ValueParamAttribute.ParameterSetName = $PSCmdlet.ParameterSetName
 
            # Add the parameter attributes to an attribute collection
            $ValueAttributeCollection = [System.Collections.ObjectModel.Collection[System.Attribute]]::new()
            $ValueAttributeCollection.Add($ValueParamAttribute)
 
            # Add ValidateSet to the parameter
            $script:Categories = Get-SGCategory
            $StatusValidateSet = [System.Management.Automation.ValidateSetAttribute]::new([string[]]$Categories.Category)
            $ValueAttributeCollection.Add($StatusValidateSet)
 
            # Create the actual Value parameter
            $ValueParam = [System.Management.Automation.RuntimeDefinedParameter]::new('Value', [string[]], $ValueAttributeCollection)
 
            # Push the parameter(s) into a parameter dictionary
            $ParamDictionary.Add('Value', $ValueParam)
        }#>

            if ($Property -eq 'AsmGroupId') {
                # Create the Value parameter attribute
                $ValueParamAttribute = [System.Management.Automation.ParameterAttribute]::new()
                $ValueParamAttribute.Position = 2
                $ValueParamAttribute.ParameterSetName = $PSCmdlet.ParameterSetName

                # Add the parameter attributes to an attribute collection
                $ValueAttributeCollection = [System.Collections.ObjectModel.Collection[System.Attribute]]::new()
                $ValueAttributeCollection.Add($ValueParamAttribute)

                # Add ValidateSet to the parameter
                $UnsubscribeGroups = Get-SGSuppressionGroup
                $StatusValidateSet = [System.Management.Automation.ValidateSetAttribute]::new([string[]]$UnsubscribeGroups.Id)
                $ValueAttributeCollection.Add($StatusValidateSet)

                # Create the actual Value parameter
                $ValueParam = [System.Management.Automation.RuntimeDefinedParameter]::new('Value', [string[]], $ValueAttributeCollection)

                # Push the parameter(s) into a parameter dictionary
                $ParamDictionary.Add('Value', $ValueParam)
            }
            if ($Property -eq 'AsmGroupName') {
                # Create the Value parameter attribute
                $ValueParamAttribute = [System.Management.Automation.ParameterAttribute]::new()
                $ValueParamAttribute.Position = 2
                $ValueParamAttribute.ParameterSetName = $PSCmdlet.ParameterSetName

                # Add the parameter attributes to an attribute collection
                $ValueAttributeCollection = [System.Collections.ObjectModel.Collection[System.Attribute]]::new()
                $ValueAttributeCollection.Add($ValueParamAttribute)

                # Add ValidateSet to the parameter
                $script:UnsubscribeGroups = Get-SGSuppressionGroup
                $StatusValidateSet = [System.Management.Automation.ValidateSetAttribute]::new([string[]]$UnsubscribeGroups.Name)
                $ValueAttributeCollection.Add($StatusValidateSet)

                # Create the actual Value parameter
                $ValueParam = [System.Management.Automation.RuntimeDefinedParameter]::new('Value', [string[]], $ValueAttributeCollection)

                # Push the parameter(s) into a parameter dictionary
                $ParamDictionary.Add('Value', $ValueParam)
            }
            if ($Property -eq 'Teammate') {
                # Create the Value parameter attribute
                $ValueParamAttribute = [System.Management.Automation.ParameterAttribute]::new()
                $ValueParamAttribute.Position = 2
                $ValueParamAttribute.ParameterSetName = $PSCmdlet.ParameterSetName

                # Add the parameter attributes to an attribute collection
                $ValueAttributeCollection = [System.Collections.ObjectModel.Collection[System.Attribute]]::new()
                $ValueAttributeCollection.Add($ValueParamAttribute)

                # Add ValidateSet to the parameter
                $script:Teammates = Get-SGTeammate
                $StatusValidateSet = [System.Management.Automation.ValidateSetAttribute]::new([string[]]$Teammates.Username)
                $ValueAttributeCollection.Add($StatusValidateSet)

                # Create the actual Value parameter
                $ValueParam = [System.Management.Automation.RuntimeDefinedParameter]::new('Value', [string[]], $ValueAttributeCollection)

                # Push the parameter(s) into a parameter dictionary
                $ParamDictionary.Add('Value', $ValueParam)
            }
            #endregion Value Properties
        }
        # Return the dictionary
        return $ParamDictionary
    }
    begin {
        if ($Property -eq 'ApiKeyName') {
            $Value = ($script:APIKeys.where({ $_.Name -eq "$($PSBoundParameters['Value'])" })).ApiKeyId
            $PSBoundParameters['Value'] = $Value
        }
        if ($Property -eq 'ASMGroupName') {
            $Value = ($script:UnsubscribeGroups.where({ $_.Name -eq "$($PSBoundParameters['Value'])" })).Id
            $PSBoundParameters['Value'] = $Value
        }
        $Properties = @{
            'MessageId'             = 'msg_id'
            'FromEmail'             = 'from_email'
            'Subject'               = 'subject'
            'ToEmail'               = 'to_email'
            'Status'                = 'status'
            'TemplateId'            = 'template_id'
            'MarketingCampaignName' = 'marketing_campaign_name'
            'MarketingCampaignId'   = 'marketing_campaign_id'
            'ApiKeyId'              = 'api_key_id'
            'ApiKeyName'            = 'api_key_id'
            'Events'                = 'events'
            'Categories'            = 'categories'
            'UniqueArgs'            = 'unique_args'
            'OutboundIp'            = 'outbound_ip'
            'LastEventTime'         = 'last_event_time'
            'Clicks'                = 'clicks'
            'AsmGroupId'            = 'asm_group_id'
            'AsmGroupName'          = 'asm_group_id'
            'Teammate'              = 'teammate'
        }
        $Operators = [ordered]@{
            'EQ'          = '='
            'NE'          = '!='
            'GT'          = '>'
            'LT'          = '<'
            'IN'          = 'IN'
            'NotIn'       = 'NOT IN'
            'Like'        = 'LIKE'
            'NotLike'     = 'NOT LIKE'
            'Contains'    = 'Contains'
            'NotContains' = 'Not Contains'
            'IsEmpty'     = 'IS NULL'
            'IsNotEmpty'  = 'IS NOT NULL'
        }
    }
    process {
        $InvokeSplat = @{
            Method        = 'Get'
            Namespace     = 'messages'
            ErrorAction   = 'Stop'
            CallingCmdlet = $PSCmdlet.MyInvocation.MyCommand.Name
        }
        if ($PSCmdlet.ParameterSetName -eq 'FilterSet') {
            $EncodedFilter = $Filter | ConvertTo-FilterQuery
        }
        elseif ($PSCmdlet.ParameterSetName -eq 'SendGridFilterSet') {
            $EncodedFilter = $SendGridFilter
        }
        else {
            if ($PSBoundParameters['Value'].Count -gt 1 -and $PSBoundParameters.ContainsKey('EQ')) {
                $UsedOperator = $Operators['IN']
                $ValueIsArray = $true
            }
            elseif ($PSBoundParameters['Value'].Count -gt 1 -and $PSBoundParameters.ContainsKey('NE')) {
                $UsedOperator = $Operators['NotIn']
                $ValueIsArray = $true
            }
            else {
                $ValueIsArray = $false
                foreach ($key in $Operators.Keys) {
                    if ($PSBoundParameters.ContainsKey($key)) {
                        $UsedOperator = $Operators[$key]
                        break
                    }
                }
            }

            [System.Text.StringBuilder]$FilterQuery = [System.Text.StringBuilder]::new()

            $null = $FilterQuery.Append('(')
            if ($PSBoundParameters.ContainsKey('EQ') -or $PSBoundParameters.ContainsKey('NE')) {
                $null = $FilterQuery.Append($Properties[$Property])
                $null = $FilterQuery.Append(' ')
                $null = $FilterQuery.Append([uri]::EscapeDataString($UsedOperator))
                $null = $FilterQuery.Append(' ')
                if ($ValueIsArray) {
                    $null = $FilterQuery.Append('(')
                    foreach ($Var in ($PSBoundParameters['Value'])) {
                        $null = $FilterQuery.Append([uri]::EscapeDataString("""$Var"""))
                        $null = $FilterQuery.Append(',')
                    }
                    $null = $FilterQuery.Remove($FilterQuery.Length - 1, 1) # Remove the last comma using the length of the string and the number of characters to remove
                    $null = $FilterQuery.Append(')')
                }
                else {
                    $null = $FilterQuery.Append([uri]::EscapeDataString("""$($PSBoundParameters['Value'])"""))                
                }
            }
            elseif ($PSBoundParameters.ContainsKey('GT') -or $PSBoundParameters.ContainsKey('LT')) {
                $null = $FilterQuery.Append($Properties[$Property])
                $null = $FilterQuery.Append(' ')
                $null = $FilterQuery.Append([uri]::EscapeDataString($UsedOperator))
                $null = $FilterQuery.Append(' ')
                $null = $FilterQuery.Append($PSBoundParameters['Value'])
            }
            elseif ($PSBoundParameters.ContainsKey('Like') -or $PSBoundParameters.ContainsKey('NotLike')) {
                $null = $FilterQuery.Append($Properties[$Property])
                $null = $FilterQuery.Append(' ')
                $null = $FilterQuery.Append([uri]::EscapeDataString($UsedOperator))
                $null = $FilterQuery.Append(' ')
                $null = $FilterQuery.Append([uri]::EscapeDataString("""%$($PSBoundParameters['Value'])%"""))
            }
            elseif ($PSBoundParameters.ContainsKey('Contains') -or $PSBoundParameters.ContainsKey('NotContains')) {
                $null = $FilterQuery.Append('(')
                foreach ($Var in ($PSBoundParameters['Value'])) {
                
                    $null = $FilterQuery.Append([uri]::EscapeDataString($UsedOperator))
                    $null = $FilterQuery.Append('(')
                    $null = $FilterQuery.Append($Properties[$Property])
                    $null = $FilterQuery.Append(',')
                    $null = $FilterQuery.Append([uri]::EscapeDataString("""$Var"""))
                    $null = $FilterQuery.Append(')')
                    $null = $FilterQuery.Append(' OR ')
                }
                $null = $FilterQuery.Remove($FilterQuery.Length - 4, 4) # Remove the last ' OR ' using the length of the string and the number of characters to remove
                $null = $FilterQuery.Append(')')
            }
            elseif ($PSBoundParameters.ContainsKey('IsEmpty') -or $PSBoundParameters.ContainsKey('IsNotEmpty')) {
                $null = $FilterQuery.Append($Properties[$Property])
                $null = $FilterQuery.Append(' ')
                $null = $FilterQuery.Append($UsedOperator)
            }
            else {
                $null = $FilterQuery.Append($Properties[$Property])
                $null = $FilterQuery.Append(' ')
                $null = $FilterQuery.Append([uri]::EscapeDataString($UsedOperator))
                $null = $FilterQuery.Append(' ')
                $null = $FilterQuery.Append([uri]::EscapeDataString("""$($PSBoundParameters['Value'])"""))
            }

            $null = $FilterQuery.Append(')')        
            Write-Verbose -Message ("Filter Query: $($FilterQuery.ToString())")
            $EncodedFilter = $FilterQuery.ToString()
        }
        #Generic List for Query Parameters
        [System.Collections.Generic.List[string]]$QueryParameters = [System.Collections.Generic.List[string]]::new()
        $QueryParameters.Add("limit=$Limit")
        $QueryParameters.Add("query=$EncodedFilter")
        if ($QueryParameters.Count -gt 0) {
            $InvokeSplat['Namespace'] += '?' + ($QueryParameters -join '&')
        }
        try {
            Invoke-SendGrid @InvokeSplat
        }
        catch {
            Write-Error ('Failed to retrieve SendGrid email activity. {0}' -f $_.Exception.Message) -ErrorAction Stop
        }
        #>
    }
}
#EndRegion '.\Public\Get-SGEmailActivity.ps1' 628
#Region '.\Public\Get-SGForwardBounceSetting.ps1' 0
function Get-SGForwardBounceSetting {
    <#
    .SYNOPSIS
        Retrieves the forward bounce mail settings on SendGrid.
    .DESCRIPTION
        Get-SGForwardBounceSetting retrieves the forward bounce mail settings on SendGrid.
    .EXAMPLE
        PS C:\> Get-SGForwardBounceSetting
        This command retrieves the forward bounce mail settings on SendGrid.
    .NOTES
        To use this function, you must be connected to a SendGrid instance. Use the Connect-SendGrid function to establish a connection.
    #>

    [CmdletBinding()]
    param (
        # Specifies an On Behalf Of header to allow you to make API calls from a parent account on behalf of the parent's Subusers or customer accounts.
        [Parameter()]
        [string]$OnBehalfOf
    )
    process {
        $InvokeSplat = @{
            Method        = 'Get'
            Namespace     = 'mail_settings/forward_bounce'
            ErrorAction   = 'Stop'
            CallingCmdlet = $PSCmdlet.MyInvocation.MyCommand.Name
        }

        if ($PSBoundParameters.OnBehalfOf) {
            $InvokeSplat.Add('OnBehalfOf', $OnBehalfOf)
        }
        
        try {
            Invoke-SendGrid @InvokeSplat
        }
        catch {
            Write-Error ('Failed to retrieve SendGrid forward bounce settings. {0}' -f $_.Exception.Message) -ErrorAction Stop
        }
    }
}
#EndRegion '.\Public\Get-SGForwardBounceSetting.ps1' 39
#Region '.\Public\Get-SGForwardSpamSetting.ps1' 0
function Get-SGForwardSpamSetting {
    <#
    .SYNOPSIS
        Retrieves the forward spam mail settings on SendGrid.
    .DESCRIPTION
        Get-SGForwardSpamSetting retrieves the forward spam mail settings on SendGrid.
    .EXAMPLE
        PS C:\> Get-SGForwardSpamSetting
        This command retrieves the forward spam mail settings on SendGrid.
    .NOTES
        To use this function, you must be connected to a SendGrid instance. Use the Connect-SendGrid function to establish a connection.
    #>

    [CmdletBinding()]
    param (
        # Specifies an On Behalf Of header to allow you to make API calls from a parent account on behalf of the parent's Subusers or customer accounts.
        [Parameter()]
        [string]$OnBehalfOf
    )
    process {
        $InvokeSplat = @{
            Method        = 'Get'
            Namespace     = 'mail_settings/forward_spam'
            ErrorAction   = 'Stop'
            CallingCmdlet = $PSCmdlet.MyInvocation.MyCommand.Name
        }

        if ($PSBoundParameters.OnBehalfOf) {
            $InvokeSplat.Add('OnBehalfOf', $OnBehalfOf)
        }
        
        try {
            Invoke-SendGrid @InvokeSplat
        }
        catch {
            Write-Error ('Failed to retrieve SendGrid forward spam settings. {0}' -f $_.Exception.Message) -ErrorAction Stop
        }
    }
}
#EndRegion '.\Public\Get-SGForwardSpamSetting.ps1' 39
#Region '.\Public\Get-SGGlobalSuppression.ps1' 0
function Get-SGGlobalSuppression {
    <#
    .SYNOPSIS
        Retrieves a paginated list of all email addresses that are globally suppressed.
 
    .DESCRIPTION
        Get-SGGlobalSuppression retrieves a paginated list of all email addresses that are globally suppressed. Global suppressions are the email addresses of recipients who have indicated that they would like to unsubscribe from all the email you send.
 
    .PARAMETER StartTime
        Refers to the start of the time range in Unix timestamp when an unsubscribe email was created (inclusive).
 
    .PARAMETER EndTime
        Refers to the end of the time range in Unix timestamp when an unsubscribe email was created (inclusive).
 
    .PARAMETER Limit
        Sets the page size, i.e., the maximum number of items from the list to be returned for a single API request. If omitted, the default page size is used. The maximum page size for this endpoint is 500 items per page.
 
    .PARAMETER Offset
        The number of items in the list to skip over before starting to retrieve the items for the requested page. The default offset of 0 represents the beginning of the list, i.e., the start of the first page. To request the second page of the list, set the offset to the page size as determined by Limit. Use multiples of the page size as your offset to request further consecutive pages.
 
    .PARAMETER OnBehalfOf
        Specifies an On Behalf Of header to allow you to make API calls from a parent account on behalf of the parent's Subusers or customer accounts.
 
    .EXAMPLE
        PS C:\> Get-SGGlobalSuppression
 
        Email : suppress1@example.com
        Created : 2022-03-04 15:34:34
        Updated : 2022-03-04 15:34:34
 
        Email : suppress2@example.com
        Created : 2021-11-12 07:38:27
        Updated : 2021-11-12 07:38:27
        ...
 
        This command retrieves a paginated list of all email addresses that are globally suppressed.
 
    .EXAMPLE
        PS C:\> Get-SGGlobalSuppression -StartTime 1646486400 -EndTime 1678022400 -Limit 100 -Offset 200
 
        Email : suppress3@example.com
        Created : 2022-01-01 00:00:00
        Updated : 2022-01-01 00:00:00
 
        Email : suppress4@example.com
        Created : 2022-02-01 00:00:00
        Updated : 2022-02-01 00:00:00
        ...
 
        This command retrieves a paginated list of globally suppressed email addresses created between the specified start and end times, with a limit of 100 items per page and an offset of 200.
 
    .EXAMPLE
        PS C:\> Get-SGGlobalSuppression -OnBehalfOf 'Subuser'
 
        Email : suppress5@example.com
        Created : 2022-03-01 00:00:00
        Updated : 2022-03-01 00:00:00
        Username : Subuser
 
        This command retrieves a paginated list of globally suppressed email addresses for the Subuser 'Subuser'.
    #>

    [CmdletBinding()]
    param (
        # Specifies the specific email address to retrieve. If this parameter is not provided, all suppressions are retrieved.
        [Parameter(
            ValueFromPipeline,
            ValueFromPipelineByPropertyName,
            Position = 0
        )]
        [MailAddress[]]$EmailAddress,

        # Refers to the start of the time range in Unix timestamp when an unsubscribe email was created (inclusive).
        [Parameter(
            Position = 1
        )]
        [UnixTime]$StartTime,

        # Refers to the end of the time range in Unix timestamp when an unsubscribe email was created (inclusive).
        [Parameter(
            Position = 2
        )]
        [UnixTime]$EndTime,

        # Sets the page size, i.e., the maximum number of items from the list to be returned for a single API request. If omitted, the default page size is used. The maximum page size for this endpoint is 500 items per page.
        [Parameter(
            Position = 3
        )]
        [int]$Limit,

        # The number of items in the list to skip over before starting to retrieve the items for the requested page. The default offset of 0 represents the beginning of the list, i.e., the start of the first page. To request the second page of the list, set the offset to the page size as determined by Limit. Use multiples of the page size as your offset to request further consecutive pages.
        [Parameter(
            Position = 4
        )]
        [int]$Offset,

        # Specifies an On Behalf Of header to allow you to make API calls from a parent account on behalf of the parent's Subusers or customer accounts.
        [Parameter()]
        [string]$OnBehalfOf
    )
    process {
        $InvokeSplat = @{
            Method        = 'Get'
            Namespace     = 'suppression/unsubscribes'
            ErrorAction   = 'Stop'
            CallingCmdlet = $PSCmdlet.MyInvocation.MyCommand.Name
        }
        if ($PSBoundParameters.OnBehalfOf) {
            $InvokeSplat.Add('OnBehalfOf', $OnBehalfOf)
        }
        # Generic List
        [System.Collections.Generic.List[string]]$QueryParameters = [System.Collections.Generic.List[string]]::new()

        if ($PSBoundParameters.StartTime) {
            $QueryParameters.Add("start_time=$($StartTime.ToUnixTime())")
        }
        if ($PSBoundParameters.EndTime) {
            $QueryParameters.Add("end_time=$($EndTime.ToUnixTime())")
        }
        if ($PSBoundParameters.Limit) {
            $QueryParameters.Add("limit=$limit")
        }
        if ($PSBoundParameters.Offset) {
            $QueryParameters.Add("offset=$offset")
        }

        if ($QueryParameters.Count -gt 0 -or $PSBoundParameters.EmailAddress) {
            $InvokeSplat['Namespace'] += '?' + ($QueryParameters -join '&')
        }

        if ($PSBoundParameters.EmailAddress) {
            foreach ($Email in $EmailAddress) {
                $EmailInvokeSplat = $InvokeSplat.Clone()
                $EmailInvokeSplat['Namespace'] += "&email=$($Email.Address)"
                if ($EmailInvokeSplat['Namespace'] -match ('\?\&email=')) {
                    $EmailInvokeSplat['Namespace'] = $EmailInvokeSplat['Namespace'].Replace('?&email=', '?email=')
                }
                try {
                    Invoke-SendGrid @EmailInvokeSplat
                }
                catch {
                    Write-Error ('Failed to retrieve SendGrid suppression report. {0}' -f $_.Exception.Message) -ErrorAction Stop
                }
            }
        }
        else {
            try {
                Invoke-SendGrid @InvokeSplat
            }
            catch {
                Write-Error ('Failed to retrieve all SendGrid suppression reports. {0}' -f $_.Exception.Message) -ErrorAction Stop
            }
        }
    }
}
#EndRegion '.\Public\Get-SGGlobalSuppression.ps1' 155
#Region '.\Public\Get-SGInvalidEmail.ps1' 0
function Get-SGInvalidEmail {
    <#
    .SYNOPSIS
        Retrieves all or specific invalid emails from SendGrid.
 
    .DESCRIPTION
        Get-SGInvalidEmail retrieves all invalid emails or a specific invalid email based on its email address from SendGrid. Invalid emails occur when you attempt to send email to an address that is formatted in a manner that does not meet internet email format standards or the email does not exist at the recipient’s mail server.
 
    .PARAMETER EmailAddress
        Specifies the email address of a specific invalid email to retrieve. If this parameter is not provided, all invalid emails are retrieved.
 
    .PARAMETER StartTime
        Refers to the start of the time range in Unix timestamp when an invalid email was created (inclusive).
 
    .PARAMETER EndTime
        Refers to the end of the time range in Unix timestamp when an invalid email was created (inclusive).
 
    .PARAMETER Limit
        Sets the page size, i.e., the maximum number of items from the list to be returned for a single API request. If omitted, the default page size is used. The maximum page size for this endpoint is 500 items per page.
 
    .PARAMETER Offset
        The number of items in the list to skip over before starting to retrieve the items for the requested page. The default offset of 0 represents the beginning of the list, i.e., the start of the first page. To request the second page of the list, set the offset to the page size as determined by Limit. Use multiples of the page size as your offset to request further consecutive pages.
 
    .PARAMETER OnBehalfOf
        Specifies an On Behalf Of header to allow you to make API calls from a parent account on behalf of the parent's Subusers or customer accounts.
 
    .EXAMPLE
        PS C:\> Get-SGInvalidEmail
 
        Email : invalid1@example.com
        Created : 2022-03-04 15:34:34
        Updated : 2022-03-04 15:34:34
 
        Email : invalid2@example.com
        Created : 2021-11-12 07:38:27
        Updated : 2021-11-12 07:38:27
        ...
 
        This command retrieves all invalid emails from SendGrid.
 
    .EXAMPLE
        PS C:\> Get-SGInvalidEmail -EmailAddress invalid2@example.com
 
        Email : invalid2@example.com
        Created : 2021-11-12 07:38:27
        Updated : 2021-11-12 07:38:27
 
        This command retrieves the invalid email with the email address 'invalid2@example.com' from SendGrid.
 
    .EXAMPLE
        PS C:\> Get-SGInvalidEmail -StartTime 1646486400 -EndTime 1678022400 -Limit 100 -Offset 200
 
        Email : invalid3@example.com
        Created : 2022-01-01 00:00:00
        Updated : 2022-01-01 00:00:00
 
        Email : invalid4@example.com
        Created : 2022-02-01 00:00:00
        Updated : 2022-02-01 00:00:00
        ...
 
        This command retrieves invalid emails from SendGrid created between the specified start and end times, with a limit of 100 items per page and an offset of 200.
 
    .EXAMPLE
        PS C:\> Get-SGInvalidEmail -EmailAddress invalid5@example.com -OnBehalfOf 'Subuser'
 
        Email : invalid5@example.com
        Created : 2022-03-01 00:00:00
        Updated : 2022-03-01 00:00:00
        Username : Subuser
 
        This command retrieves the invalid email with the email address 'invalid5@example.com' from SendGrid for the Subuser 'Subuser'.
    #>

    [CmdletBinding()]
    param (
        # Specifies the specific email address to retrieve. If this parameter is not provided, all invalid emails are retrieved.
        [Parameter(
            ValueFromPipeline,
            ValueFromPipelineByPropertyName,
            Position = 0
        )]
        [MailAddress[]]$EmailAddress,

        # Refers to the start of the time range in Unix timestamp when an invalid email was created (inclusive).
        [Parameter(
            Position = 1
        )]
        [UnixTime]$StartTime,

        # Refers to the end of the time range in Unix timestamp when an invalid email was created (inclusive).
        [Parameter(
            Position = 2
        )]
        [UnixTime]$EndTime,

        # Sets the page size, i.e., the maximum number of items from the list to be returned for a single API request. If omitted, the default page size is used. The maximum page size for this endpoint is 500 items per page.
        [Parameter(
            Position = 3
        )]
        [int]$Limit,

        # The number of items in the list to skip over before starting to retrieve the items for the requested page. The default offset of 0 represents the beginning of the list, i.e., the start of the first page. To request the second page of the list, set the offset to the page size as determined by Limit. Use multiples of the page size as your offset to request further consecutive pages.
        [Parameter(
            Position = 4
        )]
        [int]$Offset,

        # Specifies an On Behalf Of header to allow you to make API calls from a parent account on behalf of the parent's Subusers or customer accounts.
        [Parameter()]
        [string]$OnBehalfOf
    )
    process {
        $InvokeSplat = @{
            Method        = 'Get'
            Namespace     = 'suppression/invalid_emails'
            ErrorAction   = 'Stop'
            CallingCmdlet = $PSCmdlet.MyInvocation.MyCommand.Name
        }
        if ($PSBoundParameters.OnBehalfOf) {
            $InvokeSplat.Add('OnBehalfOf', $OnBehalfOf)
        }
        #Generic List
        [System.Collections.Generic.List[string]]$QueryParameters = [System.Collections.Generic.List[string]]::new()

        if ($PSBoundParameters.StartTime) {
            $QueryParameters.Add("start_time=$($StartTime.ToUnixTime())")
        }
        if ($PSBoundParameters.EndTime) {
            $QueryParameters.Add("end_time=$($EndTime.ToUnixTime())")
        }
        if ($PSBoundParameters.Limit) {
            $QueryParameters.Add("limit=$limit")
        }
        if ($PSBoundParameters.Offset) {
            $QueryParameters.Add("offset=$offset")
        }

        if ($QueryParameters.Count -gt 0 -or $PSBoundParameters.EmailAddress) {
            $InvokeSplat['Namespace'] += '?' + ($QueryParameters -join '&')
        }

        if ($PSBoundParameters.EmailAddress) {
            foreach ($Email in $EmailAddress) {
                $EmailInvokeSplat = $InvokeSplat.Clone()
                $EmailInvokeSplat['Namespace'] += "&email=$($Email.Address)"
                if ($EmailInvokeSplat['Namespace'] -match ('\?\&email=')) {
                    $EmailInvokeSplat['Namespace'] = $EmailInvokeSplat['Namespace'].Replace('?&email=', '?email=')
                }
                try {
                    Invoke-SendGrid @EmailInvokeSplat
                }
                catch {
                    Write-Error ('Failed to retrieve SendGrid invalid email. {0}' -f $_.Exception.Message) -ErrorAction Stop
                }
            }
        }
        else {
            try {
                Invoke-SendGrid @InvokeSplat
            }
            catch {
                Write-Error ('Failed to retrieve SendGrid invalid emails. {0}' -f $_.Exception.Message) -ErrorAction Stop
            }
        }
    }
}
#EndRegion '.\Public\Get-SGInvalidEmail.ps1' 167
#Region '.\Public\Get-SGIPAddress.ps1' 0
function Get-SGIPAddress {
    <#
    .SYNOPSIS
        Retrieves the IP addresses associated with the current SendGrid instance.
 
    .DESCRIPTION
        Get-SGIPAddress retrieves the IP addresses associated with the current SendGrid instance.
 
    .EXAMPLE
        PS C:\> Get-SGIPAddress
 
        This command retrieves the IP addresses associated with the current SendGrid instance.
 
    .NOTES
        To use this function, you must be connected to a SendGrid instance. Use the Connect-SendGrid function to establish a connection.
 
    #>

    [CmdletBinding()]
    param ()

    process {
        $InvokeSplat = @{
            Method        = 'Get'
            Namespace     = 'ips'
            ErrorAction   = 'Stop'
            CallingCmdlet = $PSCmdlet.MyInvocation.MyCommand.Name
        } 
        
        try {
            Invoke-SendGrid @InvokeSplat
        }
        catch {
            Write-Error ('Failed to retrieve SendGrid IPs. {0}' -f $_.Exception.Message) -ErrorAction Stop
        }
    }
}
#EndRegion '.\Public\Get-SGIPAddress.ps1' 37
#Region '.\Public\Get-SGMailSetting.ps1' 0
function Get-SGMailSetting {
    <#
    .SYNOPSIS
        Retrieves a paginated list of all mail settings on SendGrid.
 
    .DESCRIPTION
        Get-SGMailSetting retrieves a paginated list of all mail settings on SendGrid.
 
    .PARAMETER Limit
        Specifies the page size, i.e. maximum number of items from the list to be returned for a single API request.
 
    .PARAMETER Offset
        Specifies the number of items in the list to skip over before starting to retrieve the items for the requested page.
 
    .PARAMETER OnBehalfOf
        Specifies an On Behalf Of header to allow you to make API calls from a parent account on behalf of the parent's Subusers or customer accounts.
 
    .EXAMPLE
        PS C:\> Get-SGMailSetting -Limit 10 -Offset 0
 
        This command retrieves the first page of mail settings on SendGrid with a page size of 10.
 
    .EXAMPLE
        PS C:\> Get-SGMailSetting -Limit 10 -Offset 10 -OnBehalfOf 'Subuser'
 
        This command retrieves the second page of mail settings on SendGrid with a page size of 10 on behalf of the Subuser 'Subuser'.
    #>

    [CmdletBinding()]
    param (
        # Specifies the page size, i.e. maximum number of items from the list to be returned for a single API request.
        [Parameter()]
        [int]$Limit,

        # Specifies the number of items in the list to skip over before starting to retrieve the items for the requested page.
        [Parameter()]
        [int]$Offset,

        # Specifies an On Behalf Of header to allow you to make API calls from a parent account on behalf of the parent's Subusers or customer accounts.
        [Parameter()]
        [string]$OnBehalfOf
    )
    process {
        $InvokeSplat = @{
            Method        = 'Get'
            Namespace     = 'mail_settings'
            ErrorAction   = 'Stop'
            CallingCmdlet = $PSCmdlet.MyInvocation.MyCommand.Name
        }

        if ($PSBoundParameters.OnBehalfOf) {
            $InvokeSplat.Add('OnBehalfOf', $OnBehalfOf)
        }
        #Generic List
        [System.Collections.Generic.List[string]]$QueryParameters = [System.Collections.Generic.List[string]]::new()

        if ($PSBoundParameters.Limit) {
            $QueryParameters.Add("limit=$limit")
        }
        if ($PSBoundParameters.Offset) {
            $QueryParameters.Add("offset=$offset")
        }

        if ($QueryParameters.Count -gt 0) {
            $InvokeSplat['Namespace'] += '?' + ($QueryParameters -join '&')
        }
        
        try {
            Invoke-SendGrid @InvokeSplat
        }
        catch {
            Write-Error ('Failed to retrieve SendGrid mail settings. {0}' -f $_.Exception.Message) -ErrorAction Stop
        }
    }
}
#EndRegion '.\Public\Get-SGMailSetting.ps1' 75
#Region '.\Public\Get-SGPermissionScopes.ps1' 0
function Get-SGPermissionScopes {
    <#
    .SYNOPSIS
        Retrieves all permission scopes that the current SendGrid session (apikey) has permission to.
         
    .DESCRIPTION
        Get-SGPermissionScopes queries SendGrid for all permission scopes that the current session, identified by the API key, has access to.
        Permission scopes define the specific actions that are permitted in a session. This information can be useful for diagnosing
        authorization issues or for configuring new sessions with the appropriate permissions.
 
    .EXAMPLE
        PS C:\> Get-SGPermissionScopes
 
        This command retrieves all permission scopes that the current session (apikey) has permission to.
 
    .NOTES
        To use this function, you must be connected to a SendGrid instance. Use the Connect-SendGrid function to establish a connection.
    #>

    [CmdletBinding()]
    param ()
    process {
        $InvokeSplat = @{
            Method        = 'Get'
            Namespace     = 'scopes'
            ErrorAction   = 'Stop'
            CallingCmdlet = $PSCmdlet.MyInvocation.MyCommand.Name
        }
        try {
            Invoke-SendGrid @InvokeSplat
        }
        catch {
            Write-Error ('Failed to retrieve permission scopes in SendGrid. {0}' -f $_.Exception.Message) -ErrorAction Stop
        }
        
    }
}
#EndRegion '.\Public\Get-SGPermissionScopes.ps1' 37
#Region '.\Public\Get-SGSpamReport.ps1' 0
function Get-SGSpamReport {
    <#
    .SYNOPSIS
        Retrieves all or specific spam reports from SendGrid.
 
    .DESCRIPTION
        Get-SGSpamReport retrieves all spam reports or a specific spam report based on its email address from SendGrid. Spam reports occur when recipients mark emails as spam or junk.
 
    .PARAMETER EmailAddress
        Specifies the email address of a specific spam report to retrieve. If this parameter is not provided, all spam reports are retrieved.
 
    .PARAMETER StartTime
        Refers to the start of the time range in Unix timestamp when a spam report was created (inclusive).
 
    .PARAMETER EndTime
        Refers to the end of the time range in Unix timestamp when a spam report was created (inclusive).
 
    .PARAMETER Limit
        Sets the page size, i.e., the maximum number of items from the list to be returned for a single API request. If omitted, the default page size is used. The maximum page size for this endpoint is 500 items per page.
 
    .PARAMETER Offset
        The number of items in the list to skip over before starting to retrieve the items for the requested page. The default offset of 0 represents the beginning of the list, i.e., the start of the first page. To request the second page of the list, set the offset to the page size as determined by Limit. Use multiples of the page size as your offset to request further consecutive pages.
 
    .PARAMETER OnBehalfOf
        Specifies an On Behalf Of header to allow you to make API calls from a parent account on behalf of the parent's Subusers or customer accounts.
 
    .EXAMPLE
        PS C:\> Get-SGSpamReport
 
        Email : spam1@example.com
        Created : 2022-03-04 15:34:34
        Updated : 2022-03-04 15:34:34
 
        Email : spam2@example.com
        Created : 2021-11-12 07:38:27
        Updated : 2021-11-12 07:38:27
        ...
 
        This command retrieves all spam reports from SendGrid.
 
    .EXAMPLE
        PS C:\> Get-SGSpamReport -EmailAddress spam2@example.com
 
        Email : spam2@example.com
        Created : 2021-11-12 07:38:27
        Updated : 2021-11-12 07:38:27
 
        This command retrieves the spam report with the email address 'spam2@example.com' from SendGrid.
 
    .EXAMPLE
        PS C:\> Get-SGSpamReport -StartTime 1646486400 -EndTime 1678022400 -Limit 100 -Offset 200
 
        Email : spam3@example.com
        Created : 2022-01-01 00:00:00
        Updated : 2022-01-01 00:00:00
 
        Email : spam4@example.com
        Created : 2022-02-01 00:00:00
        Updated : 2022-02-01 00:00:00
        ...
 
        This command retrieves spam reports from SendGrid created between the specified start and end times, with a limit of 100 items per page and an offset of 200.
 
    .EXAMPLE
        PS C:\> Get-SGSpamReport -EmailAddress spam5@example.com -OnBehalfOf 'Subuser'
 
        Email : spam5@example.com
        Created : 2022-03-01 00:00:00
        Updated : 2022-03-01 00:00:00
        Username : Subuser
 
        This command retrieves the spam report with the email address 'spam5@example.com' from SendGrid for the Subuser 'Subuser'.
    #>

    [CmdletBinding()]
    param (
        # Specifies the specific email address to retrieve. If this parameter is not provided, all spam reports are retrieved.
        [Parameter(
            ValueFromPipeline,
            ValueFromPipelineByPropertyName,
            Position = 0
        )]
        [MailAddress[]]$EmailAddress,

        # Refers to the start of the time range in Unix timestamp when a spam report was created (inclusive).
        [Parameter(
            Position = 1
        )]
        [UnixTime]$StartTime,

        # Refers to the end of the time range in Unix timestamp when a spam report was created (inclusive).
        [Parameter(
            Position = 2
        )]
        [UnixTime]$EndTime,

        # Sets the page size, i.e., the maximum number of items from the list to be returned for a single API request. If omitted, the default page size is used. The maximum page size for this endpoint is 500 items per page.
        [Parameter(
            Position = 3
        )]
        [int]$Limit,

        # The number of items in the list to skip over before starting to retrieve the items for the requested page. The default offset of 0 represents the beginning of the list, i.e., the start of the first page. To request the second page of the list, set the offset to the page size as determined by Limit. Use multiples of the page size as your offset to request further consecutive pages.
        [Parameter(
            Position = 4
        )]
        [int]$Offset,

        # Specifies an On Behalf Of header to allow you to make API calls from a parent account on behalf of the parent's Subusers or customer accounts.
        [Parameter()]
        [string]$OnBehalfOf
    )
    process {
        $InvokeSplat = @{
            Method        = 'Get'
            Namespace     = 'suppression/spam_reports'
            ErrorAction   = 'Stop'
            CallingCmdlet = $PSCmdlet.MyInvocation.MyCommand.Name
        }
        if ($PSBoundParameters.OnBehalfOf) {
            $InvokeSplat.Add('OnBehalfOf', $OnBehalfOf)
        }
        #Generic List
        [System.Collections.Generic.List[string]]$QueryParameters = [System.Collections.Generic.List[string]]::new()

        if ($PSBoundParameters.StartTime) {
            $QueryParameters.Add("start_time=$($StartTime.ToUnixTime())")
        }
        if ($PSBoundParameters.EndTime) {
            $QueryParameters.Add("end_time=$($EndTime.ToUnixTime())")
        }
        if ($PSBoundParameters.Limit) {
            $QueryParameters.Add("limit=$limit")
        }
        if ($PSBoundParameters.Offset) {
            $QueryParameters.Add("offset=$offset")
        }

        if ($QueryParameters.Count -gt 0 -or $PSBoundParameters.EmailAddress) {
            $InvokeSplat['Namespace'] += '?' + ($QueryParameters -join '&')
        }

        if ($PSBoundParameters.EmailAddress) {
            foreach ($Email in $EmailAddress) {
                $EmailInvokeSplat = $InvokeSplat.Clone()
                $EmailInvokeSplat['Namespace'] += "&email=$($Email.Address)"
                if ($EmailInvokeSplat['Namespace'] -match ('\?\&email=')) {
                    $EmailInvokeSplat['Namespace'] = $EmailInvokeSplat['Namespace'].Replace('?&email=', '?email=')
                }
                try {
                    Invoke-SendGrid @EmailInvokeSplat
                }
                catch {
                    Write-Error ('Failed to retrieve SendGrid spam report. {0}' -f $_.Exception.Message) -ErrorAction Stop
                }
            }
        }
        else {
            try {
                Invoke-SendGrid @InvokeSplat
            }
            catch {
                Write-Error ('Failed to retrieve SendGrid spam reports. {0}' -f $_.Exception.Message) -ErrorAction Stop
            }
        }
    }
}
#EndRegion '.\Public\Get-SGSpamReport.ps1' 167
#Region '.\Public\Get-SGSubuser.ps1' 0
function Get-SGSubuser {
    <#
    .SYNOPSIS
        Retrieves all or a specific Subuser within the current SendGrid instance.
 
    .DESCRIPTION
        Get-SGSubuser retrieves all Subusers or a specific Subuser based on its username
        within the current SendGrid instance. Due to limitations in the SendGrid API, when retrieve ing all users it wont display disabled users.
 
    .PARAMETER Username
        Specifies the ID of a specific Subuser to retrieve. If this parameter is not provided, all Subusers are retrieved.
 
    .PARAMETER Limit
        The number of results you would like to get in each request.
        Default: none
 
    .PARAMETER Offset
        The number of Subusers to skip.
        Default: none
 
    .EXAMPLE
        PS C:\> Get-SGSubuser
         
        This command retrieves all users within the current SendGrid instance.
 
    .EXAMPLE
        PS C:\> Get-SGSubuser -Username <username>
         
        This command retrieves the user with the specified username within the current SendGrid instance.
     
    .EXAMPLE
        PS C:\> Get-SGSubuser -Limit 2
         
        This command retrieves the first two Subusers within the current SendGrid instance.
    #>

    [CmdletBinding(
        SupportsShouldProcess
    )]
    param (

        # Specifies the ID of a specific Subuser to retrieve. If this parameter is not provided, all Subusers are retrieved.
        [Parameter(
            ValueFromPipeline,
            ValueFromPipelineByPropertyName,
            Position = 0
        )]
        [Alias('Id')]
        [string]$Username,

        # Specifies the page size, i.e. maximum number of items from the list to be returned for a single API request.
        [Parameter()]
        [int]$Limit,

        # Specifies the number of items in the list to skip over before starting to retrieve the items for the requested page.
        [Parameter()]
        [int]$Offset
    )

    process {
        $InvokeSplat = @{
            Method        = 'Get'
            Namespace     = 'subusers'
            ErrorAction   = 'Stop'
            CallingCmdlet = $PSCmdlet.MyInvocation.MyCommand.Name
        } 
        
        #Generic List
        [System.Collections.Generic.List[string]]$QueryParameters = [System.Collections.Generic.List[string]]::new()

        if ($PSBoundParameters.Username) {
            $InvokeSplat['Namespace'] += "/$username"
        }
        if ($PSBoundParameters.Limit) {
            $QueryParameters.Add("limit=$limit")
        }
        if ($PSBoundParameters.Offset) {
            $QueryParameters.Add("offset=$offset")
        }

        if ($QueryParameters.Count -gt 0) {
            $InvokeSplat['Namespace'] += '?' + ($QueryParameters -join '&')
        }

        if ($PSCmdlet.ShouldProcess(('{0}' -f 'Subusers'))) {
            try {
                Invoke-SendGrid @InvokeSplat
            }
            catch {
                Write-Error ('Failed to retrieve SendGrid Subuser. {0}' -f $_.Exception.Message) -ErrorAction Stop
            }
        }
    }
}
#EndRegion '.\Public\Get-SGSubuser.ps1' 94
#Region '.\Public\Get-SGSuppression.ps1' 0
function Get-SGSuppression {
    <#
    .SYNOPSIS
        Retrieves all suppressions or suppressions for a specific email address.
 
    .DESCRIPTION
        The Get-SGSuppression function retrieves all suppressions or suppressions for a specific email address from SendGrid.
         
    .PARAMETER EmailAddress
        Specifies the email address to search suppression groups for.
 
    .PARAMETER OnBehalfOf
        Specifies a On Behalf Of header to allow you to make API calls from a parent account on behalf of the parent's Subusers or customer accounts.
 
    .EXAMPLE
        PS C:\> Get-SGSuppression
        This command retrieves all suppressions.
 
    .EXAMPLE
        PS C:\> Get-SGSuppression -EmailAddress 'test@example.com'
        This command retrieves all suppressions for the email address 'test@example.com'.
    #>

    [CmdletBinding()]
    param (
        # Specifies the email address to search suppression groups for.
        [Parameter(
            Position = 0
        )]
        [MailAddress]$EmailAddress,

        # Specifies a On Behalf Of header to allow you to make API calls from a parent account on behalf of the parent's Subusers or customer accounts.
        [Parameter()]
        [string]$OnBehalfOf
    )
    process {
        $InvokeSplat = @{
            Method        = 'Get'
            Namespace     = 'asm/suppressions'
            ErrorAction   = 'Stop'
            CallingCmdlet = $PSCmdlet.MyInvocation.MyCommand.Name
        }

        if ($PSBoundParameters.ContainsKey('EmailAddress')) {
            $InvokeSplat.Namespace += '/{0}' -f $EmailAddress.Address
        }

        if ($PSBoundParameters.ContainsKey('OnBehalfOf')) {
            $InvokeSplat.OnBehalfOf = $OnBehalfOf
        }

        try {
            Invoke-SendGrid @InvokeSplat
        }
        catch {
            Write-Error ('Failed to retrieve suppressions. {0}' -f $_.Exception.Message) -ErrorAction Stop
        }
    }
}
#EndRegion '.\Public\Get-SGSuppression.ps1' 59
#Region '.\Public\Get-SGSuppressionGroup.ps1' 0
function Get-SGSuppressionGroup {
    <#
    .SYNOPSIS
        Retrieves suppression groups.
 
    .DESCRIPTION
        The Get-SGSuppressionGroup function retrieves all suppression groups or a specific suppression group in SendGrid.
         
    .PARAMETER GroupId
        Specifies the ID of the suppression group.
 
    .EXAMPLE
        PS C:\> Get-SGSuppressionGroup
        This command retrieves all suppression groups.
 
    .EXAMPLE
        PS C:\> Get-SGSuppressionGroup -GroupId 123
        This command retrieves the suppression group with the ID 123.
    #>

    [CmdletBinding()]
    param (
        # Specifies the ID of the suppression group.
        [Parameter(
            ValueFromPipeline,
            ValueFromPipelineByPropertyName,
            Position = 0
        )]
        [Alias('Id')]
        [int]$GroupId,

        # Specifies a On Behalf Of header to allow you to make API calls from a parent account on behalf of the parent's Subusers or customer accounts.
        [Parameter()]
        [string]$OnBehalfOf
    )
    process {
        $InvokeSplat = @{
            Method        = 'Get'
            Namespace     = 'asm/groups'
            ErrorAction   = 'Stop'
            CallingCmdlet = $PSCmdlet.MyInvocation.MyCommand.Name
        }
        if ($PSBoundParameters.ContainsKey('OnBehalfOf')) {
            $InvokeSplat.OnBehalfOf = $OnBehalfOf
        }
        if ($PSBoundParameters.ContainsKey('GroupId')) {
            $InvokeSplat.Namespace += "/$GroupId"
        }
        try {
            Invoke-SendGrid @InvokeSplat
        }
        catch {
            Write-Error ('Failed to retrieve suppression group(s). {0}' -f $_.Exception.Message) -ErrorAction Stop
        }
    }
}
#EndRegion '.\Public\Get-SGSuppressionGroup.ps1' 56
#Region '.\Public\Get-SGTeammate.ps1' 0
function Get-SGTeammate {
    <#
    .SYNOPSIS
        Retrieves all or a specific Teammate from SendGrid.
 
    .DESCRIPTION
        Get-SGTeammate retrieves all or a specific Teammate from SendGrid. You can specify the specific username to retrieve.
 
    .PARAMETER Username
        Specifies the specific username to retrieve.
 
    .PARAMETER OnBehalfOf
        Specifies an On Behalf Of header to allow you to make API calls from a parent account on behalf of the parent's Subusers or customer accounts.
 
    .EXAMPLE
        PS C:\> Get-SGTeammate
 
        This command retrieves all teammates from SendGrid.
 
    .EXAMPLE
        PS C:\> Get-SGTeammate -Username name@example.com
 
        This command retrieves the specific teammate with the username'name@example.com' from SendGrid.
    #>

    [CmdletBinding()]
    param (
        # Specifies the specific username to retrieve.
        [Parameter(
            ValueFromPipeline,
            ValueFromPipelineByPropertyName,
            Position = 0
        )]
        [string[]]$Username,

        # Specifies an On Behalf Of header to allow you to make API calls from a parent account on behalf of the parent's Subusers or customer accounts.
        [Parameter()]
        [string]$OnBehalfOf
    )
    process {
        $InvokeSplat = @{
            Method        = 'Get'
            Namespace     = "teammates"
            ErrorAction   = 'Stop'
            CallingCmdlet = $PSCmdlet.MyInvocation.MyCommand.Name
        }
        if ($PSBoundParameters.OnBehalfOf) {
            $InvokeSplat.Add('OnBehalfOf', $OnBehalfOf)
        }

        if ($PSBoundParameters.Username) {
            foreach ($User in $Username) {
                $UserInvokeSplat = $InvokeSplat.Clone()
                $UserInvokeSplat['Namespace'] = "teammates/$User"
                try {
                    Invoke-SendGrid @EmailInvokeSplat
                }
                catch {
                    Write-Error ('Failed to retrieve SendGrid teammate. {0}' -f $_.Exception.Message) -ErrorAction Stop
                }
            }
        }
        else {
            try {
                Invoke-SendGrid @InvokeSplat
            }
            catch {
                Write-Error ('Failed to retrieve all SendGrid teammates. {0}' -f $_.Exception.Message) -ErrorAction Stop
            }
        }
    }   
}
#EndRegion '.\Public\Get-SGTeammate.ps1' 72
#Region '.\Public\Invoke-SGCommand.ps1' 0
function Invoke-SGCommand {
    <#
    .SYNOPSIS
        A wrapper for the Invoke-SendGrid function.
 
    .DESCRIPTION
        Invoke-SGCommand is a wrapper for the Invoke-SendGrid function. It allows you to make API calls to SendGrid.
 
    .PARAMETER WebMethod
        Specifies the HTTP method to use for the API call. The default value is 'Get'.
 
    .PARAMETER Namespace
        Specifies the URL path for the API call.
 
    .PARAMETER ContentBody
        Specifies the content body for the API call. It should be a hashtable.
 
    .EXAMPLE
        PS C:\> Invoke-SGCommand -WebMethod 'Get' -Namespace 'v3/mail_settings' -ContentBody @{ 'limit' = 10; 'offset' = 0 }
 
        This command makes a 'Get' API call to SendGrid with the URL path 'v3/mail_settings' and the content body '{ 'limit' = 10; 'offset' = 0 }'.
    #>

    [CmdletBinding(
        SupportsShouldProcess
    )]
    param (
        # Specifies the URL path for the API call.
        [Parameter(
            Mandatory,
            Position = 0
        )]
        [Alias('UrlPath', 'Path')]
        [string]$Namespace,

        # Specifies the HTTP method to use for the API call. The default value is 'Get'.
        [Parameter(
            Position = 1
        )]
        [ValidateSet('Get', 'Post', 'Put', 'Delete', 'Patch')]
        [string]$WebMethod = 'Get',

        # Specifies the content body for the API call. It should be a hashtable.
        [Parameter(
            Position = 2
        )]
        [HashTable]$ContentBody,

        # Specifies if the SGCommand takes Query parameters like limit or offset. Should contain the query parameter followed by = and the value. Example: limit=10
        [Parameter(
            Position = 3
        )]
        [System.Collections.Generic.List[string]]$QueryParameters = [System.Collections.Generic.List[string]]::new(),

        # Specifies an On Behalf Of header to allow you to make API calls from a parent account on behalf of the parent's Subusers or customer accounts.
        [Parameter()]
        [string]$OnBehalfOf
    )
    process {

        # Replace the character(s) '/', '/v3/', and 'v3/' with an empty string if it begins with them.
        $ReplacedNamespace = $Namespace -replace '^/|/v3/|v3/|https:\/\/api\.sendgrid\.com/v3/|https://api.sendgrid.com' -replace '^/'
        $InvokeSplat = @{
            Method        = $WebMethod
            Namespace     = $ReplacedNamespace
            ErrorAction   = 'Stop'
            CallingCmdlet = $PSCmdlet.MyInvocation.MyCommand.Name
        }
        if ($PSBoundParameters.ContentBody) {
            $InvokeSplat.Add('ContentBody', $ContentBody)
        }
        if ($PSBoundParameters.OnBehalfOf) {
            $InvokeSplat.Add('OnBehalfOf', $OnBehalfOf)
        }

        if ($QueryParameters.Count -gt 0) {
            $InvokeSplat['Namespace'] += '?' + ($QueryParameters -join '&')
        }

        if ($PSCmdlet.ShouldProcess($InvokeSplat['Namespace'], 'Invoke SendGrid API call')) {
            try {
                Invoke-SendGrid @InvokeSplat
            }
            catch {
                Write-Error ('Failed to make SendGrid API call. {0}' -f $_.Exception.Message) -ErrorAction Stop
            }
        }
    }
}
#EndRegion '.\Public\Invoke-SGCommand.ps1' 89
#Region '.\Public\New-SGAlert.ps1' 0
function New-SGAlert {
    <#
    .SYNOPSIS
        Creates a new alert on SendGrid.
 
    .DESCRIPTION
        New-SGAlert creates a new alert on SendGrid based on the provided parameters.
 
    .PARAMETER Type
        Specifies the type of alert to create. Can be either 'usage_limit' or 'stats_notification'.
 
    .PARAMETER EmailTo
        Specifies the email address the alert will be sent to.
 
    .PARAMETER Frequency
        Specifies how frequently the alert will be sent. Required for 'stats_notification'.
 
    .PARAMETER Percentage
        Specifies the usage threshold at which the alert will be sent. Required for 'usage_alert'.
 
    .PARAMETER OnBehalfOf
        Specifies an On Behalf Of header to allow you to make API calls from a parent account on behalf of the parent's Subusers or customer accounts.
 
    .EXAMPLE
        PS C:\> New-SGAlert -Type 'usage_limit' -EmailTo 'test@example.com' -Percentage 90
 
        This command creates a new 'usage_limit' alert on SendGrid that will be sent to 'test@example.com' when the usage threshold reaches 90%.
 
    .EXAMPLE
        PS C:\> New-SGAlert -Type 'stats_notification' -EmailTo 'test@example.com' -Frequency 'daily' -OnBehalfOf 'Subuser'
 
        This command creates a new 'stats_notification' alert on SendGrid that will be sent to 'test@example.com' daily on behalf of the Subuser 'Subuser'.
    #>

    [CmdletBinding(
        SupportsShouldProcess
    )]
    param (
        # Specifies the type of alert to Email Credit Usage.
        [Parameter(
            Mandatory,
            ParameterSetName = 'Usage',
            Position = 0
        )]
        [switch]$EmailCreditUsage,

        # Specifies the type of alert to Email Statistics Summary.
        [Parameter(
            Mandatory,
            ParameterSetName = 'Statistics',
            Position = 0
        )]
        [switch]$EmailStatisticsSummary,

        # Specifies the email address the alert will be sent to.
        [Parameter(
            Mandatory,
            ParameterSetName = 'Statistics',
            Position = 1
        )]
        [Parameter(
            Mandatory,
            ParameterSetName = 'Usage',
            Position = 1
        )]
        [MailAddress]$EmailTo,

        # Specifies how frequently the alert will be sent. Required for 'stats_notification'.
        [Parameter(
            Mandatory,
            ParameterSetName = 'Statistics',
            Position = 2
        )]
        [ValidateSet('Daily', 'Weekly', 'Monthly')]
        [string]$Frequency,

        # Specifies the usage threshold at which the alert will be sent. Required for 'usage_alert'.
        [Parameter(
            Mandatory,
            ParameterSetName = 'Usage',
            Position = 2
        )]
        [ValidateRange(1, 100)]
        [int]$Percentage,

        # Specifies an On Behalf Of header to allow you to make API calls from a parent account on behalf of the parent's Subusers or customer accounts.
        [Parameter(ParameterSetName = 'Statistics')]
        [Parameter(ParameterSetName = 'Usage')]
        [string]$OnBehalfOf
    )
    process {
        $InvokeSplat = @{
            Method        = 'Post'
            Namespace     = 'alerts'
            ErrorAction   = 'Stop'
            CallingCmdlet = $PSCmdlet.MyInvocation.MyCommand.Name
        }

        $ContentBody = @{
            'email_to' = $EmailTo.Address
        }
        if ($PSCmdlet.ParameterSetName -eq 'Usage') {
            $ContentBody.Add('type', 'usage_limit')
            $ContentBody.Add('Percentage', $Percentage)
        }
        else {
            $ContentBody.Add('type', 'stats_notification')
            $ContentBody.Add('frequency', $Frequency.ToLower())
        }

        $InvokeSplat.Add('ContentBody', $ContentBody)

        if ($PSBoundParameters.OnBehalfOf) {
            $InvokeSplat.Add('OnBehalfOf', $OnBehalfOf)
        }
        if ($PSCmdlet.ShouldProcess($EmailTo.Address)) {
            try {
                Invoke-SendGrid @InvokeSplat
            }
            catch {
                Write-Error ('Failed to create SendGrid alert. {0}' -f $_.Exception.Message) -ErrorAction Stop
            }
        }
    }
}
#EndRegion '.\Public\New-SGAlert.ps1' 125
#Region '.\Public\New-SGApiKey.ps1' 0
function New-SGApiKey {
    <#
    .SYNOPSIS
        Creates a new API Key for the current SendGrid instance.
 
    .DESCRIPTION
        New-SGApiKey creates a new API key for the SendGrid instance. The API key can be given full access, restricted access, or billing access.
        The created API key can then be used to authenticate access to SendGrid services.
 
    .PARAMETER Name
        Specifies the name to describe this API Key.
 
    .PARAMETER Scopes
        Specifies the individual permissions that you are giving to this API Key.
 
    .PARAMETER FullAccessKey
        Specifies to create a full access API Key. This will nullify the Scopes parameter.
 
    .EXAMPLE
        PS C:\> New-SGApiKey -Name 'MyAPIKey' -Scopes @('mail.send', 'alerts.create', 'alerts.read')
 
        Creates a new API key with the name 'MyAPIKey' and assigns 'mail.send', 'alerts.create', 'alerts.read' scopes to the key.
 
    .EXAMPLE
        PS C:\> New-SGApiKey -Name 'MyFullAccessKey' -FullAccessKey
 
        Creates a new full access API key with the name 'MyFullAccessKey'. This will prompt for confirmation.
 
    .NOTES
        To use this function, you must be connected to a SendGrid instance. Use the Connect-SendGrid function to establish a connection.
        There is a limit of 100 API Keys on your account. Omitting the Scopes field from your request will create a key with "Full Access" permissions by default.
    #>

    [CmdletBinding(
        SupportsShouldProcess,
        DefaultParameterSetName = 'Scopes')]
    param (
        [Parameter(
            ParameterSetName = 'Scopes',
            Mandatory,
            Position = 0
        )]
        [Parameter(
            ParameterSetName = 'FullAccess',
            Mandatory,
            Position = 0
        )]
        [string]$Name,

        [Parameter(
            ParameterSetName = 'Scopes',
            Mandatory,
            Position = 1
        )]
        [ValidateSet([SendGridScopes])]
        [string[]]$Scopes,

        [Parameter(
            ParameterSetName = 'FullAccess',
            Mandatory,
            Position = 1
        )]
        [switch]$FullAccessKey,

        # Specifies a On Behalf Of header to allow you to make API calls from a parent account on behalf of the parent's Subusers or customer accounts.
        [Parameter()]
        [string]$OnBehalfOf
    )
    begin {
        [hashtable]$ContentBody = @{
            name = $Name
        }
        if ($PSCmdlet.ParameterSetName -eq 'Scopes') {
            $ContentBody.Add('scopes', $Scopes)
        }
    }
    process {
        $InvokeSplat = @{
            Method        = 'Post'
            Namespace     = 'api_keys'
            ErrorAction   = 'Stop'
            CallingCmdlet = $PSCmdlet.MyInvocation.MyCommand.Name
        }
        if ($PSBoundParameters.OnBehalfOf) {
            $InvokeSplat.Add('OnBehalfOf', $OnBehalfOf)
        }
        $InvokeSplat.Add('ContentBody', $ContentBody)
        if ($PSCmdlet.ParameterSetName -eq 'FullAccess') {
            if ($PSCmdlet.ShouldContinue("You are about to create an API key ($Name) with Full Access. Do you want to continue?", $MyInvocation.MyCommand.Name)) {
                try {
                    Invoke-SendGrid @InvokeSplat
                }
                catch {
                    Write-Error ('Failed to create a FullAccess SendGrid API key. {0}' -f $_.Exception.Message) -ErrorAction Stop
                }
            }
        }
        else {
            if ($PSCmdlet.ShouldProcess($Name)) {
                try {
                    Invoke-SendGrid @InvokeSplat
                }
                catch {
                    Write-Error ('Failed to create SendGrid API key. {0}' -f $_.Exception.Message) -ErrorAction Stop
                }
            }
        }
    }
}
#EndRegion '.\Public\New-SGApiKey.ps1' 109
#Region '.\Public\New-SGAuthenticatedDomain.ps1' 0
function New-SGAuthenticatedDomain {
    <#
    .SYNOPSIS
        Adds a new Authenticated Domain to the current SendGrid instance.
 
    .DESCRIPTION
        New-SGAuthenticatedDomain allows you to add a new Authenticated Domain to the current SendGrid instance. An authenticated domain allows
        you to remove the "via" or "sent on behalf of" message that your recipients see when they read your emails. Authenticating a domain allows
        you to replace sendgrid.net with your personal sending domain. You will be required to create a subdomain so that SendGrid can generate
        the DNS records which you must give to your host provider.
 
        This function uses a dynamic parameter, `CustomSPF`, which is available only when `DisableAutomaticSecurity` switch is set. The "CustomSPF"
        parameter allows to specify whether to use a custom SPF or allow SendGrid to manage your SPF. This option is only available to authenticated
        domains set up for manual security.
 
    .PARAMETER Domain
        Specifies a domain. It's recommended to provide a full domain including a subdomain, for instance email.example.com.
 
    .PARAMETER SendGridSubdomain
        Specifies an optional subdomain to be used. Use when you don't want SendGrid to automatically generate a subdomain like em1234.
 
    .PARAMETER SubUser
        Specifies a subuser to be used, this is optional.
     
    .PARAMETER DisableAutomaticSecurity
        Specify whether to not allow SendGrid to manage your SPF records, DKIM keys, and DKIM key rotation. Default is that SendGrid manages
        those records.
 
    .PARAMETER CustomDkimSelector
        Add a custom DKIM selector. Accepts three letters or numbers.
 
    .PARAMETER Force
        Specifies if the current domain (parameter Domain) should be created despite it contains a subdomain (email.example.com).
 
    .PARAMETER CustomSPF
        This is a dynamic parameter and only becomes available when the 'DisableAutomaticSecurity' switch is set.
        Specifies whether to use a custom SPF or allow SendGrid to manage your SPF. This option is only available to authenticated domains set up for manual security.
 
    .PARAMETER OnBehalfOf
        Specifies a On Behalf Of header to allow you to make API calls from a parent account on behalf of the parent's Subusers or customer accounts.
 
    .PARAMETER Default
        Specifies if the domain should be the default one for the SendGrid instance.
 
    .EXAMPLE
        PS C:\> New-SGAuthenticatedDomain -Domain 'example.com' -Subdomain 'email'
 
        Adds a new authenticated domain 'example.com' with the subdomain 'email' using the specified API key.
 
    .EXAMPLE
        PS C:\> New-SGAuthenticatedDomain -Domain 'example.com' -Subdomain 'email' -DisableAutomaticSecurity -CustomDkimSelector 'exm'
 
        Adds a new authenticated domain 'example.com' with the subdomain 'email', disables automatic security, and uses a custom DKIM selector 'exm' with the specified API key.
 
    .EXAMPLE
        PS C:\> New-SGAuthenticatedDomain -Domain 'sub.example.com' -Subdomain 'email' -Force
 
        Adds a new authenticated domain 'email.sub.example.com' with the subdomain 'email' and forces the creation despite the domain containing a subdomain.
 
    .EXAMPLE
        PS C:\> New-SGAuthenticatedDomain -Domain 'example.com' -Subdomain 'email' -DisableAutomaticSecurity -CustomSPF
 
        Adds a new authenticated domain 'example.com' with the subdomain 'email', disables automatic security, and uses a custom SPF record with the specified API key.
 
    .NOTES
        To use this function, you must be connected to a SendGrid instance. Use the Connect-SendGrid function to establish a connection.
    #>

    [CmdletBinding(
        SupportsShouldProcess
    )]
    param (

        # Specifies a domain. It's recommended to provide a full domain including a subdomain, for instance email.example.com.
        [Parameter(
            Mandatory,
            Position = 0
        )]
        [ValidatePattern('^([a-zA-Z0-9]([-a-zA-Z0-9]{0,61}[a-zA-Z0-9])?\.)?([a-zA-Z0-9]{1,2}([-a-zA-Z0-9]{0,252}[a-zA-Z0-9])?)\.([a-zA-Z]{2,63})$')]
        [string]$Domain,

        # Specifies an optional subdomain to be used. Use when you don't want SendGrid to automatically generate a subdomain like em1234.
        [Parameter(
            Position = 1
        )]
        [string]$SendGridSubdomain,

        # The username associated with this domain. This is optional.
        [Parameter(
            Position = 2
        )]
        [Alias('SubUser')]
        [string]$Username,

        # Specify whether to not allow SendGrid to manage your SPF records, DKIM keys, and DKIM key rotation. Default is that SendGrid manages those records.
        [Parameter(
            Position = 3
        )]
        [switch]$DisableAutomaticSecurity,

        # Add a custom DKIM selector. Accepts three letters or numbers.
        [Parameter(
            Position = 4
        )]
        [ValidatePattern('^[a-zA-Z\d]{3}$')]
        $CustomDkimSelector,

        # Specifies if the domain should be the default one for the SendGrid instance.
        [Parameter()]
        [switch]$Default,

        # Specifies a On Behalf Of header to allow you to make API calls from a parent account on behalf of the parent's Subusers or customer accounts.
        [Parameter()]
        [string]$OnBehalfOf
    )
    DynamicParam {
        $ParamDictionary = [System.Management.Automation.RuntimeDefinedParameterDictionary]::new()
        $IPAddressParamAttribute = [System.Management.Automation.ParameterAttribute]::new()
        $IPAddressParamAttribute.Position = 2
        $IPAddressParamAttribute.ParameterSetName = $PSCmdlet.ParameterSetName

        # Add the parameter attributes to an attribute collection
        $IPAddressAttributeCollection = [System.Collections.ObjectModel.Collection[System.Attribute]]::new()
        $IPAddressAttributeCollection.Add($IPAddressParamAttribute)

        # Add ValidateSet to the parameter
        $script:IPAddresses = Get-SGIPAddress
        $StatusValidateSet = [System.Management.Automation.ValidateSetAttribute]::new([string[]]$IPAddresses.Ip)
        $IPAddressAttributeCollection.Add($StatusValidateSet)

        # Create the actual IPAddress parameter
        $IPAddressParam = [System.Management.Automation.RuntimeDefinedParameter]::new('IPAddress', [string[]], $IPAddressAttributeCollection)

        # Push the parameter(s) into a parameter dictionary
        $ParamDictionary.Add('IPAddress', $IPAddressParam)
        
        if ($DisableAutomaticSecurity) {
            # Specify whether to use a custom SPF or allow SendGrid to manage your SPF. This option is only available to authenticated domains set up for manual security.
            $CustomSPFParamAttribute = [System.Management.Automation.ParameterAttribute]::new()
            $CustomSPFParamAttribute.Position = 5

            # Add the parameter attributes to an attribute collection
            $AttributeCollection = [System.Collections.ObjectModel.Collection[System.Attribute]]::new()
            $AttributeCollection.Add($CustomSPFParamAttribute)

            # Create the actual CustomSPF parameter
            $CustomSPFParam = [System.Management.Automation.RuntimeDefinedParameter]::new('CustomSPF', [switch], $AttributeCollection)

            # Push the parameter(s) into a parameter dictionary
            $ParamDictionary.Add('CustomSPF', $CustomSPFParam)
        }

        # Return the dictionary
        return $ParamDictionary
    }
    begin {
        [hashtable]$ContentBody = [hashtable]::new()

        $ContentBody.Add('domain', $Domain)

        if ($PSBoundParameters.ContainsKey('SendGridSubdomain')) {
            Write-Verbose -Message ("SendGrid will not generate a custom subdomain. Domain to be used: $Domain") -Verbose
            $ContentBody.Add('subdomain', $Subdomain)
            $ProcessMessage = "$Subdomain.$Domain"
            
        }
        else {
            Write-Verbose -Message ("SendGrid will automatically generate a custom subdomain for you. Example:em1234.$Domain") -Verbose
            $ProcessMessage = $Domain
        }

        if ($PSBoundParameters.ContainsKey('CustomDkimSelector')) {
            $ContentBody.Add('custom_dkim_selector', $CustomDkimSelector)
        }
        if ($PSBoundParameters.ContainsKey('SubUser')) {
            $ContentBody.Add('username', $SubUser)
        }
        if ($PSBoundParameters.ContainsKey('DisableAutomaticSecurity')) {
            $ContentBody.Add('automatic_security', $false)
        }
        else {
            $ContentBody.Add('automatic_security', $true)
        }
        if ($PSBoundParameters.ContainsKey('CustomSPF')) {
            $ContentBody.Add('custom_spf', $true)
        }
        if ($PSBoundParameters.ContainsKey('Username')) {
            $ContentBody.Add('username', $Username)
        }
        if ($PSBoundParameters.ContainsKey('IPAddress')) {
            $ContentBody.Add('ips', @($IPAddress))
        }
        $InvokeSplat = @{
            Method        = 'Post'
            Namespace     = 'whitelabel/domains'
            ErrorAction   = 'Stop'
            CallingCmdlet = $PSCmdlet.MyInvocation.MyCommand.Name
        }
        if ($PSBoundParameters.OnBehalfOf) {
            $InvokeSplat.Add('OnBehalfOf', $OnBehalfOf)
        }
    }    
    process {
        if ($PSCmdlet.ShouldProcess($ProcessMessage)) {
            if ($PSBoundParameters.ContainsKey('Default') -and $PSCmdlet.ShouldContinue($Domain,'Setting this domain as the default domain will remove the current default domain. Do you want to continue?')) {
                $ContentBody.Add('default', $true)
            }
            try {
                $InvokeSplat.Add('ContentBody', $ContentBody)
                Invoke-SendGrid @InvokeSplat
            }
            catch {
                Write-Error ('Failed to add SendGrid Authenticated Domain. {0}' -f $_.Exception.Message) -ErrorAction Stop
            }
        }
    }
}
#EndRegion '.\Public\New-SGAuthenticatedDomain.ps1' 217
#Region '.\Public\New-SGBrandedDomainLink.ps1' 0
function New-SGBrandedDomainLink {
    <#
    .SYNOPSIS
        Adds a new Branded Domain Link within the current SendGrid instance.
 
    .DESCRIPTION
        New-SGBrandedDomainLink adds a new Branded Domain Link within the current SendGrid instance. Email link branding (formerly "Link Whitelabel")
        allows all of the click-tracked links, opens, and images in your emails to be served from your domain rather than sendgrid.net. Spam filters
        and recipient servers look at the links within emails to determine whether the email looks trustworthy. They use the reputation of the root
        domain to determine whether the links can be trusted.
 
    .PARAMETER Domain
        Specifies a domain. Do not provide a full domain including a subdomain here, for instance email.example.com.
 
    .PARAMETER SendGridSubdomain
        Specifies an optional subdomain to be used. Use when you don't want SendGrid to automatically generate a subdomain like url1234.
 
    .PARAMETER Force
        Specifies if the current domain (parameter Domain) should be created despite it contains a subdomain (email.example.com).
 
    .EXAMPLE
        PS C:\> New-SGBrandedDomainLink -Domain 'example.com' -Subdomain 'link'
 
        Adds a new branded domain link 'sub.example.com' with the subdomain 'link' using the specified API key.
 
    .EXAMPLE
        PS C:\> New-SGBrandedDomainLink -Domain 'sub.example.com' -Force
 
        Adds a new branded domain link 'url123.sub.example.com' and forces the creation despite the domain containing a subdomain.
 
    .NOTES
        To use this function, you must be connected to a SendGrid instance. Use the Connect-SendGrid function to establish a connection.
    #>

    [CmdletBinding(SupportsShouldProcess)]
    param (

        # Specifies a domain. Do not provide a full domain including a subdomain here, for instance email.example.com.
        [Parameter(
            Mandatory,
            Position = 0
        )]
        [ValidatePattern('^([a-zA-Z0-9]([-a-zA-Z0-9]{0,61}[a-zA-Z0-9])?\.)?([a-zA-Z0-9]{1,2}([-a-zA-Z0-9]{0,252}[a-zA-Z0-9])?)\.([a-zA-Z]{2,63})$')]
        [string]$Domain,

        # Specifies an optional subdomain to be used. Use when you don't want SendGrid to automatically generate a subdomain like url1234.
        [Parameter(
            Position = 1
        )]
        [string]$SendGridSubDomain,

        # Specifies if the domain should be the default one for the SendGrid instance.
        [Parameter()]
        [switch]$Default,

        # Specifies a On Behalf Of header to allow you to make API calls from a parent account on behalf of the parent's Subusers or customer accounts.
        [Parameter()]
        [string]$OnBehalfOf
    )
    
    begin {
        [hashtable]$ContentBody = [hashtable]::new()

        $ContentBody.Add('domain', $Domain)
        if ($PSBoundParameters.ContainsKey('SendGridSubdomain')) {
            Write-Verbose -Message ("SendGrid will not generate a custom subdomain. Domain to be used: $Domain") -Verbose
            $ContentBody.Add('subdomain', $Subdomain)
            $ProcessMessage = "$Subdomain.$Domain"
            
        }
        else {
            Write-Verbose -Message ("SendGrid will automatically generate a custom branded subdomain for you. Example:url1234.$Domain") -Verbose
            $ProcessMessage = $Domain
        }
        $InvokeSplat = @{
            Method        = 'Post'
            Namespace     = 'whitelabel/links'
            ErrorAction   = 'Stop'
            CallingCmdlet = $PSCmdlet.MyInvocation.MyCommand.Name
        }
        if ($PSBoundParameters.OnBehalfOf) {
            $InvokeSplat.Add('OnBehalfOf', $OnBehalfOf)
        }
    }    
    process { 
        if ($PSCmdlet.ShouldProcess($ProcessMessage)) {
            if ($PSBoundParameters.ContainsKey('Default') -and $PSCmdlet.ShouldContinue($Domain, 'Setting this domain as the default domain will remove the current default domain. Do you want to continue?')) {
                $ContentBody.Add('default', $true)
            }
            try {
                $InvokeSplat.Add('ContentBody', $ContentBody)
                Invoke-SendGrid @InvokeSplat
            }
            catch {
                Write-Error ('Failed to create SendGrid Branded Domain Link. {0}' -f $_.Exception.Message) -ErrorAction Stop
            }
        }
    }
}
#EndRegion '.\Public\New-SGBrandedDomainLink.ps1' 99
#Region '.\Public\New-SGCombinedDomain.ps1' 0
function New-SGCombinedDomain {
    <#
    .SYNOPSIS
        Adds a new Authenticated Domain and a new Branded Domain Link within the current SendGrid instance.
 
    .DESCRIPTION
        New-SGCombinedDomain adds both an authenticated domain and a branded domain link within the current SendGrid instance.
        This allows for the setup of domain authentication and email link branding in a single step, enhancing the trustworthiness
        and deliverability of your emails.
 
    .PARAMETER Domain
        Specifies the domain for both the authenticated domain and the branded domain link.
        For the authenticated domain, do not provide a full domain including a subdomain here, for instance, email.example.com.
 
    .PARAMETER Subdomain
        Specifies a subdomain to be used for both the authenticated domain and the branded domain link.
        In most cases, it's "email" for authenticated domains and "link" for branded domain links.
 
    .PARAMETER DisableAutomaticSecurity
        Specifies if automatic security features (like DKIM and SPF records) should be disabled for the authenticated domain.
 
    .PARAMETER CustomDkimSelector
        Specifies a custom DKIM selector to be used for the authenticated domain.
 
    .PARAMETER CustomSPF
        Indicates whether a custom SPF record should be used for the authenticated domain.
    .PARAMETER Force
        Specifies if the current domain should be created despite it contains a subdomain (email.example.com) for the branded domain link.
    .EXAMPLE
        PS C:\> New-SGCombinedDomain -Domain 'example.com' -Subdomain 'email' -DisableAutomaticSecurity -CustomDkimSelector 'exm'
        Adds a new authenticated domain 'example.com' with the subdomain 'email', disables automatic security, and uses a custom DKIM selector 'exm'.
        Also adds a new branded domain link with the same domain and subdomain.
    .EXAMPLE
        PS C:\> New-SGCombinedDomain -Domain 'example.com' -Subdomain 'link' -Force
        Adds a new authenticated domain 'example.com' with the subdomain 'link' and forces the creation despite the domain containing a subdomain.
        Also adds a new branded domain link with the same domain and subdomain.
    .NOTES
        To use this function, you must be connected to a SendGrid instance. Use the Connect-SendGrid function to establish a connection.
    #>

    [CmdletBinding(
        SupportsShouldProcess
    )]
    param (
        [Parameter(
            Mandatory,
            Position = 0
        )]
        [string]$Domain,

        # Specifies an optional subdomain to be used. Use when you don't want SendGrid to automatically generate a subdomain like url1234 and em1234.
        [Parameter(
            Position = 1
        )]
        [string]$SendGridSubDomain,

        # Specify whether to not allow SendGrid to manage your SPF records, DKIM keys, and DKIM key rotation. Default is that SendGrid manages those records.
        [Parameter(
            Position = 2
        )]
        [switch]$DisableAutomaticSecurity,

        # Add a custom DKIM selector. Accepts three letters or numbers.
        [Parameter(
            Position = 3
        )]
        [ValidatePattern('^[a-zA-Z\d]{1,3}$')]
        [string]$CustomDkimSelector,

        # Specifies whether to use a custom SPF or allow SendGrid to manage your SPF. This option is only available to authenticated domains set up for manual security (DisableAutomaticSecurity).
        [switch]$CustomSPF,

        # Specifies a On Behalf Of header to allow you to make API calls from a parent account on behalf of the parent's Subusers or customer accounts.
        [Parameter()]
        [string]$OnBehalfOf
    )

    process {
        [hashtable]$AuthDomainSplat = @{
            Domain = $Domain
            SendGridSubDomain = $Subdomain
            DisableAutomaticSecurity = $DisableAutomaticSecurity.IsPresent
            CustomDkimSelector = $CustomDkimSelector
            CustomSPF = $CustomSPF.IsPresent
            OnBehalfOf = $OnBehalfOf
            ErrorAction = 'Stop'
        }
        [hashtable]$BrandedDomainSplat = @{
            Domain = $Domain
            SendGridSubDomain = $Subdomain
            ErrorAction = 'Stop'
        }
        # Remove empty Hashtables
        Remove-EmptyHashtable -Hashtable $AuthDomainSplat
        Remove-EmptyHashtable -Hashtable $BrandedDomainSplat
        if ($AuthDomainSplat['CustomSPF'] -eq $false -and -not $DisableAutomaticSecurity.IsPresent) {
            $AuthDomainSplat.Remove('CustomSPF')
            $AuthDomainSplat.Remove('DisableAutomaticSecurity')
        }
        if ($CustomSPF.IsPresent -and $DisableAutomaticSecurity.IsPresent -eq $false) {
            throw 'The CustomSPF parameter can only be used with the DisableAutomaticSecurity parameter.'
        }
        if ($PSCmdlet.ShouldProcess($Domain)) {
            # Add the new authenticated domain
            New-SGAuthenticatedDomain @AuthDomainSplat
            
            # Add the new branded domain link
            New-SGBrandedDomainLink @BrandedDomainSplat
        }
    }
}
#EndRegion '.\Public\New-SGCombinedDomain.ps1' 111
#Region '.\Public\New-SGSubuser.ps1' 0
function New-SGSubuser {
    <#
    .SYNOPSIS
        Creates a new Subuser within the current SendGrid instance.
 
    .DESCRIPTION
        New-SGSubuser creates a new Subuser within the current SendGrid instance.
        The Subuser is created with the provided username and email address to contact this subuser.
 
    .PARAMETER Username
        Specifies the ID of a specific Subuser to retrieve. If this parameter is not provided, all Subusers are retrieved.
 
    .PARAMETER Email
        Specifies the email address to contact this subuser.
    .PARAMETER Password
        Specifies the password for the Subuser to create.
 
    .PARAMETER Ips
        Specifies the IP addresses that you would like to allow this Subuser to access.
 
    .EXAMPLE
        PS C:\> New-SGSubuser -Username <username> -Email <email> -Password <securestring> -Ips <ipaddress>
         
        This command creates a new Subuser with the specified username, email address, password, and IP address within the current SendGrid instance.
 
    .NOTES
        To use this function, you must be connected to a SendGrid instance. Use the Connect-SendGrid function to establish a connection.
 
    #>

    [CmdletBinding(
        SupportsShouldProcess
    )]
    param (

        # Specifies the username for the Subuser to create.
        [Parameter(
            Mandatory,
            ValueFromPipelineByPropertyName,
            Position = 0
        )]
        [string]$Username,

        # Specifies the email address to contact this subuser.
        [Parameter(
            Mandatory,
            ValueFromPipelineByPropertyName,
            Position = 1
        )]
        [MailAddress]$Email,

        # Specifies the password for the Subuser to create.
        [Parameter(
            Mandatory,
            ValueFromPipelineByPropertyName,
            Position = 2
        )]
        [SecureString]$Password,

        # Specifies the IP addresses that you would like to allow this Subuser to access.
        [Parameter(
            Mandatory,
            ValueFromPipelineByPropertyName,
            Position = 3
        )]
        [IPAddress[]]$Ips

    )

    begin {
        [hashtable]$ContentBody = [ordered]@{
            username = $Username
            email    = $Email.Address
            password = (ConvertFrom-SecureString -SecureString $Password -AsPlainText)
            ips      = @($IPs.IPAddressToString)
        }
    }
    process {
        $InvokeSplat = @{
            Method        = 'Post'
            Namespace     = 'subusers'
            ErrorAction   = 'Stop'
            CallingCmdlet = $PSCmdlet.MyInvocation.MyCommand.Name
        } 

        $InvokeSplat.Add('ContentBody', $ContentBody)
        if ($PSCmdlet.ShouldProcess($Username)) {
            try {
                $InvokeSplat
                Invoke-SendGrid @InvokeSplat
            }
            catch {
                Write-Error ('Failed to create SendGrid Subuser. {0}' -f $_.Exception.Message) -ErrorAction Stop
            }
        }
    }
}
#EndRegion '.\Public\New-SGSubuser.ps1' 97
#Region '.\Public\New-SGSuppressionGroup.ps1' 0
function New-SGSuppressionGroup {
    <#
    .SYNOPSIS
        Creates a new suppression group.
 
    .DESCRIPTION
        The New-SGSuppressionGroup function creates a new suppression group in SendGrid.
         
    .PARAMETER Name
        Specifies the name of the suppression group.
 
    .PARAMETER Description
        Specifies the description of the suppression group.
 
    .PARAMETER IsDefault
        Specifies whether the suppression group is the default group.
 
    .EXAMPLE
        PS C:\> New-SGSuppressionGroup -Name 'My Group' -Description 'This is my group.' -IsDefault $false
        This command creates a new suppression group named 'My Group' with the specified description and is not set as the default group.
    #>

    [CmdletBinding(
        SupportsShouldProcess
    )]
    param (
        # Specifies the name of the suppression group.
        [Parameter(
            Mandatory,
            ValueFromPipeline,
            ValueFromPipelineByPropertyName,
            Position = 0
        )]
        [string]$Name,

        # Specifies the description of the suppression group.
        [Parameter(
            Mandatory,
            Position = 1
        )]
        [string]$Description,

        # Specifies whether the suppression group is the default group.
        [Parameter()]
        [switch]$IsDefault, 

        # Specifies a On Behalf Of header to allow you to make API calls from a parent account on behalf of the parent's Subusers or customer accounts.
        [Parameter()]
        [string]$OnBehalfOf
    )
    process {
        $InvokeSplat = @{
            Method        = 'Post'
            Namespace     = "asm/groups"
            ErrorAction   = 'Stop'
            CallingCmdlet = $PSCmdlet.MyInvocation.MyCommand.Name
        }

        $InvokeSplat['ContentBody'] = @{
            'name'                              = $Name
            'description'                       = $Description
            'is_default'                        = $IsDefault.IsPresent
        }
        if ($PSBoundParameters.OnBehalfOf) {
            $InvokeSplat.Add('OnBehalfOf', $OnBehalfOf)
        }
        if ($PSCmdlet.ShouldProcess(('Create a new suppression group named {0}.' -f $Name))) {
            try {
                Invoke-SendGrid @InvokeSplat
            }
            catch {
                Write-Error ('Failed to create a new suppression group. {0}' -f $_.Exception.Message) -ErrorAction Stop
            }
        }
    }
}
#EndRegion '.\Public\New-SGSuppressionGroup.ps1' 76
#Region '.\Public\Remove-SGAlert.ps1' 0
function Remove-SGAlert {
    <#
    .SYNOPSIS
        Deletes an existing alert on SendGrid.
 
    .DESCRIPTION
        Remove-SGAlert deletes an existing alert on SendGrid based on the provided alert ID.
 
    .PARAMETER AlertId
        Specifies the ID of the alert to delete.
 
    .PARAMETER OnBehalfOf
        Specifies an On Behalf Of header to allow you to make API calls from a parent account on behalf of the parent's Subusers or customer accounts.
 
    .EXAMPLE
        PS C:\> Remove-SGAlert -AlertId 123
 
        This command deletes the alert with the ID 123 on SendGrid.
 
    .EXAMPLE
        PS C:\> Remove-SGAlert -AlertId 123 -OnBehalfOf 'Subuser'
 
        This command deletes the alert with the ID 123 on SendGrid on behalf of the Subuser 'Subuser'.
    #>

    [CmdletBinding(
        SupportsShouldProcess,
        ConfirmImpact = 'High'
    )]
    param (
        # Specifies the UniqueId of the alert to delete.
        [Parameter(
            Mandatory,
            ValueFromPipeline,
            ValueFromPipelineByPropertyName,
            DontShow,
            ParameterSetName = 'InputObject'
        )]
        [Object[]]$InputObject,
        
        # Specifies the UniqueId of the alert to delete.
        [Parameter(
            Mandatory,
            Position = 0,
            ParameterSetName = 'UniqueId'
        )]
        [Alias('Id')]
        [int]$UniqueId,

        # Specifies an On Behalf Of header to allow you to make API calls from a parent account on behalf of the parent's Subusers or customer accounts.
        [Parameter()]
        [string]$OnBehalfOf
    )
    process {
        if ($PSCmdlet.ParameterSetName -eq 'InputObject') {
            $UniqueId = @()
            foreach ($Object in $InputObject) {
                switch ($Object) {
                    { $_ -is [string] } { $UniqueId += $_; break }
                    { $_ -is [int] } { $UniqueId += $_; break }
                    { $_ -is [System.Management.Automation.PSCustomObject] } { $UniqueId += $_.Id; break }
                    default { Write-Error ('Failed to convert InputObject to Id.') -ErrorAction Stop }
                }
            }            
        }
        foreach ($Id in $UniqueId) {
            if ($PSCmdlet.ShouldProcess($Id)) {
                $InvokeSplat = @{
                    Method        = 'Delete'
                    Namespace     = "alerts/$Id"
                    ErrorAction   = 'Stop'
                    CallingCmdlet = $PSCmdlet.MyInvocation.MyCommand.Name
                }
                if ($PSBoundParameters.OnBehalfOf) {
                    $InvokeSplat.Add('OnBehalfOf', $OnBehalfOf)
                }
                try {
                    Invoke-SendGrid @InvokeSplat
                }
                catch {
                    Write-Error ('Failed to delete SendGrid alert. {0}' -f $_.Exception.Message) -ErrorAction Stop
                }
            }
        }
    }
}
#EndRegion '.\Public\Remove-SGAlert.ps1' 86
#Region '.\Public\Remove-SGApiKey.ps1' 0
function Remove-SGApiKey {
    <#
    .SYNOPSIS
        Deletes a given API key.
 
    .DESCRIPTION
        Remove-SGApiKey deletes the API key with the given ID.
 
    .PARAMETER ApiKeyID
        Specifies the ID of the API Key to be deleted.
 
    .EXAMPLE
        PS C:\> Remove-SGApiKey -ApiKeyId 'R2l2W3kZSQukQv4lCkG3zW'
 
        This command deletes the API Key with the specified ID within the current SendGrid instance.
    #>

    [CmdletBinding(
        SupportsShouldProcess,
        ConfirmImpact = 'High'
    )]
    param (
        # Specifies the UniqueId of the API Key to be updated.
        [Parameter(
            Mandatory,
            ValueFromPipeline,
            ValueFromPipelineByPropertyName,
            DontShow,
            ParameterSetName = 'InputObject'
        )]
        [Object[]]$InputObject,
        
        # Specifies the UniqueId of the API Key to be updated.
        [Parameter(
            Mandatory,
            Position = 0,
            ParameterSetName = 'UniqueId'
        )]
        [Alias('Id')]
        [string[]]$UniqueId,
        
        # Specifies a On Behalf Of header to allow you to make API calls from a parent account on behalf of the parent's Subusers or customer accounts.
        [Parameter()]
        [string]$OnBehalfOf
    )
    
    process {
        if ($PSCmdlet.ParameterSetName -eq 'InputObject') {
            $UniqueId = @()
            foreach ($Object in $InputObject) {
                switch ($Object) {
                    { $_ -is [string] } { $UniqueId += $_; break }
                    { $_ -is [int] } { $UniqueId += $_; break }
                    { $_ -is [System.Management.Automation.PSCustomObject] } { $UniqueId += $_.Id; break }
                    default { Write-Error ('Failed to convert InputObject to Id.') -ErrorAction Stop }
                }
            }            
        }
        foreach ($Id in $UniqueId) {
            $InvokeSplat = @{
                Method        = 'Delete'
                Namespace     = "api_keys/$Id"
                ErrorAction   = 'Stop'
                CallingCmdlet = $PSCmdlet.MyInvocation.MyCommand.Name
            }
            $GetSplat = @{
                ApiKeyID    = $Id
                ErrorAction = 'Stop'
            }

            if ($PSBoundParameters.OnBehalfOf) {
                $InvokeSplat.Add('OnBehalfOf', $OnBehalfOf)
                $GetSplat.Add('OnBehalfOf', $OnBehalfOf)
            }
            $SGApiKey = Get-SGApiKey @GetSplat
            if ($PSCmdlet.ShouldProcess('ApiKey: {0}' -f $SGApiKey.Name)) {
                try {
                    Invoke-SendGrid @InvokeSplat
                }
                catch {
                    Write-Error ('Failed to delete SendGrid API Key. {0}' -f $_.Exception.Message) -ErrorAction Stop
                }
            }
        }
    }
}
#EndRegion '.\Public\Remove-SGApiKey.ps1' 86
#Region '.\Public\Remove-SGAuthenticatedDomain.ps1' 0
function Remove-SGAuthenticatedDomain {
    <#
    .SYNOPSIS
        Removes an Authenticated Domain within the current Sendgrid instance.
 
    .DESCRIPTION
        Remove-SGAuthenticatedDomain removes an authenticated domain from the current SendGrid instance. An authenticated domain allows you
        to remove the "via" or "sent on behalf of" message that your recipients see when they read your emails. Authenticating a domain allows
        you to replace sendgrid.net with your personal sending domain. You must provide the unique identifier of the domain to be removed.
        Please note that you might need to remove the DNS records manually after removing the domain.
 
    .PARAMETER UniqueId
        Specifies the unique identifier for the authenticated domain to remove.
 
    .EXAMPLE
        PS C:\> Remove-SGAuthenticatedDomain -UniqueId '1234567'
 
        Removes the authenticated domain with the unique identifier '1234567'.
 
    .EXAMPLE
        PS C:\> Get-SGAuthenticatedDomain | Where-Object { $_.Domain -eq 'example.com' } | Remove-SGAuthenticatedDomain
 
        Removes the authenticated domain 'example.com' using its unique identifier obtained from the Get-SGAuthenticatedDomain cmdlet.
 
    .NOTES
        To use this function, you must be connected to a SendGrid instance. Use the Connect-SendGrid function to establish a connection.
    #>

    [CmdletBinding(
        SupportsShouldProcess,
        ConfirmImpact = 'High')]
    param (
        # Specifies the UniqueId for the authenticated domain to remove.
        [Parameter(
            Mandatory,
            ValueFromPipeline,
            ValueFromPipelineByPropertyName,
            DontShow,
            ParameterSetName = 'InputObject'
        )]
        [Object[]]$InputObject,
        
        # Specifies the UniqueId for the authenticated domain to remove.
        [Parameter(
            Mandatory,
            Position = 0,
            ParameterSetName = 'UniqueId'
        )]
        [Alias('Id')]
        [string[]]$UniqueId,

        # Specifies a On Behalf Of header to allow you to make API calls from a parent account on behalf of the parent's Subusers or customer accounts.
        [Parameter()]
        [string]$OnBehalfOf
    )
    process {
        if ($PSCmdlet.ParameterSetName -eq 'InputObject') {
            $UniqueId = @()
            foreach ($Object in $InputObject) {
                switch ($Object) {
                    { $_ -is [string] } { $UniqueId += $_; break }
                    { $_ -is [int] } { $UniqueId += $_; break }
                    { $_ -is [System.Management.Automation.PSCustomObject] } { $UniqueId += $_.Id; break }
                    default { Write-Error ('Failed to convert InputObject to Id.') -ErrorAction Stop }
                }
            }            
        }
        foreach ($Id in $UniqueId) { 
            $InvokeSplat = @{
                Method        = 'Delete'
                Namespace     = "whitelabel/domains/$Id"
                ErrorAction   = 'Stop'
                CallingCmdlet = $PSCmdlet.MyInvocation.MyCommand.Name
            }
            $GetSplat = @{
                UniqueId    = $Id
                ErrorAction = 'Stop'
            }
            if ($PSBoundParameters.OnBehalfOf) {
                $InvokeSplat.Add('OnBehalfOf', $OnBehalfOf)
                $GetSplat.Add('OnBehalfOf', $OnBehalfOf)
            }
            $SGAuthenticatedDomain = Get-SGAuthenticatedDomain @GetSplat -ShowDNS
            
            Write-Verbose -Message ("Don't forget to remove DNS records.") -Verbose
            $SGAuthenticatedDomain

            if ($PSCmdlet.ShouldProcess(('{0}.{1}({2})' -f $SGAuthenticatedDomain.Subdomain, $SGAuthenticatedDomain.Domain,$Id))) {
                try {
                    Invoke-SendGrid @InvokeSplat
                }
                catch {
                    Write-Error ('Failed to remove SendGrid Authenticated Domain. {0}' -f $_.Exception.Message) -ErrorAction Stop
                }
            }
        }
    }
}
#EndRegion '.\Public\Remove-SGAuthenticatedDomain.ps1' 98
#Region '.\Public\Remove-SGBlock.ps1' 0
function Remove-SGBlock {
    <#
    .SYNOPSIS
        Removes a specific block from SendGrid.
 
    .DESCRIPTION
        Remove-SGBlock removes a specific block from SendGrid based on its email address.
 
    .PARAMETER EmailAddress
        Specifies the email address of the block to remove.
 
    .PARAMETER OnBehalfOf
        Specifies an On Behalf Of header to allow you to make API calls from a parent account on behalf of the parent's Subusers or customer accounts.
 
    .EXAMPLE
        PS C:\> Remove-SGBlock -EmailAddress "block1@example.com"
 
        This command removes the block with the email address 'block1@example.com' from SendGrid.
 
    .EXAMPLE
        PS C:\> Remove-SGBlock -EmailAddress "block2@example.com" -OnBehalfOf 'Subuser'
 
        This command removes the block with the email address 'block2@example.com' from SendGrid for the Subuser 'Subuser'.
    #>

    [CmdletBinding(
        DefaultParameterSetName = 'Default',
        SupportsShouldProcess,
        ConfirmImpact = 'High'
    )]
    param (
        # Specifies the email address of the block to remove.
        [Parameter(
            Mandatory,
            ValueFromPipeline,
            ValueFromPipelineByPropertyName,
            DontShow,
            ParameterSetName = 'InputObject'
        )]
        [Object[]]$InputObject,
        
        # Specifies the email address of the block to remove.
        [Parameter(
            Mandatory,
            ParameterSetName = 'Default',
            Position = 0
        )]
        [Alias('Email')]
        [MailAddress[]]$EmailAddress,

        # Specifies whether to delete all emails on the bounces list.
        [Parameter(
            ParameterSetName = 'DeleteAll',
            Mandatory,
            Position = 0
        )]
        [switch]$DeleteAll,

        # Specifies an On Behalf Of header to allow you to make API calls from a parent account on behalf of the parent's Subusers or customer accounts.
        [Parameter(ParameterSetName = 'Default')]
        [Parameter(ParameterSetName = 'DeleteAll')]
        [Parameter(ParameterSetName = 'InputObject')]
        [string]$OnBehalfOf
    )
    process {
        if ($PSCmdlet.ParameterSetName -eq 'InputObject') {
            $EmailAddress = @()
            foreach ($Object in $InputObject) {
                switch ($Object) {
                    { $_ -is [string] } { $EmailAddress += $_; break }
                    { $_ -is [System.Management.Automation.PSCustomObject] } { $EmailAddress += $_.Email; break }
                    default { Write-Error ('Failed to convert InputObject to Id.') -ErrorAction Stop }
                }
            }            
        }
        if ($PSCmdlet.ParameterSetName -eq 'DeleteAll') {
            $InvokeSplat = @{
                Method        = 'Delete'
                Namespace     = 'suppression/blocks'
                ErrorAction   = 'Stop'
                CallingCmdlet = $PSCmdlet.MyInvocation.MyCommand.Name
            }
            if ($PSBoundParameters.OnBehalfOf) {
                $InvokeSplat.Add('OnBehalfOf', $OnBehalfOf)
            }
            if ($PSCmdlet.ShouldProcess('Remove all bounces from SendGrid')) {
                try {
                    Invoke-SendGrid @InvokeSplat
                }
                catch {
                    Write-Error ('Failed to remove all SendGrid bounces. {0}' -f $_.Exception.Message) -ErrorAction Stop
                }
            }
        }
        else {
            foreach ($Id in $EmailAddress) {
                $InvokeSplat = @{
                    Method        = 'Delete'
                    Namespace     = "suppression/blocks/$($Id.Address)"
                    ErrorAction   = 'Stop'
                    CallingCmdlet = $PSCmdlet.MyInvocation.MyCommand.Name
                }
                if ($PSBoundParameters.OnBehalfOf) {
                    $InvokeSplat.Add('OnBehalfOf', $OnBehalfOf)
                }
                if ($PSCmdlet.ShouldProcess(('Remove bounce with email address {0}' -f $Id.Address))) {
                    try {
                        Invoke-SendGrid @InvokeSplat
                    }
                    catch {
                        Write-Error ('Failed to remove SendGrid bounce "{0}". {0}' -f $Id.Address, $_.Exception.Message) -ErrorAction Stop
                    }
                }
            }
        }
    }
}
#EndRegion '.\Public\Remove-SGBlock.ps1' 117
#Region '.\Public\Remove-SGBounce.ps1' 0
function Remove-SGBounce {
    <#
    .SYNOPSIS
        Removes a specific bounce from SendGrid.
 
    .DESCRIPTION
        Remove-SGBounce removes a specific bounce from SendGrid based on its email address.
 
    .PARAMETER EmailAddress
        Specifies the email address of the bounce to remove.
 
    .PARAMETER OnBehalfOf
        Specifies an On Behalf Of header to allow you to make API calls from a parent account on behalf of the parent's Subusers or customer accounts.
 
    .PARAMETER DeleteAll
        Specifies whether to delete all emails on the bounces list.
 
    .EXAMPLE
        PS C:\> Remove-SGBounce -EmailAddress "bounce1@example.com"
 
        This command removes the bounce with the email address 'bounce1@example.com' from SendGrid.
 
    .EXAMPLE
        PS C:\> Remove-SGBounce -EmailAddress "bounce2@example.com" -OnBehalfOf 'Subuser'
 
        This command removes the bounce with the email address 'bounce2@example.com' from SendGrid for the Subuser 'Subuser'.
 
    .EXAMPLE
        PS C:\> Remove-SGBounce -DeleteAll $true
 
        This command deletes all emails on the bounces list from SendGrid.
    #>

    [CmdletBinding(
        DefaultParameterSetName = 'Default',
        SupportsShouldProcess,
        ConfirmImpact = 'High'
    )]
    param (
        # Specifies the email address of the bounce to remove.
        [Parameter(
            Mandatory,
            ValueFromPipeline,
            ValueFromPipelineByPropertyName,
            DontShow,
            ParameterSetName = 'InputObject'
        )]
        [Object[]]$InputObject,
        
        # Specifies the email address of the bounce to remove.
        [Parameter(
            Mandatory,
            ParameterSetName = 'Default',
            Position = 0
        )]
        [Alias('Email')]
        [MailAddress[]]$EmailAddress,

        # Specifies whether to delete all emails on the bounces list.
        [Parameter(ParameterSetName = 'DeleteAll')]
        [switch]$DeleteAll,

        # Specifies an On Behalf Of header to allow you to make API calls from a parent account on behalf of the parent's Subusers or customer accounts.
        [Parameter(ParameterSetName = 'Default')]
        [Parameter(ParameterSetName = 'DeleteAll')]
        [Parameter(ParameterSetName = 'InputObject')]
        [string]$OnBehalfOf
    )
    process {
        if ($PSCmdlet.ParameterSetName -eq 'InputObject') {
            $EmailAddress = @()
            foreach ($Object in $InputObject) {
                switch ($Object) {
                    { $_ -is [string] } { $EmailAddress += $_; break }
                    { $_ -is [System.Management.Automation.PSCustomObject] } { $EmailAddress += $_.Email; break }
                    default { Write-Error ('Failed to convert InputObject to Id.') -ErrorAction Stop }
                }
            }            
        }
        if ($PSCmdlet.ParameterSetName -eq 'DeleteAll') {
            $InvokeSplat = @{
                Method        = 'Delete'
                Namespace     = 'suppression/bounces'
                ErrorAction   = 'Stop'
                CallingCmdlet = $PSCmdlet.MyInvocation.MyCommand.Name
            }
            if ($PSBoundParameters.OnBehalfOf) {
                $InvokeSplat.Add('OnBehalfOf', $OnBehalfOf)
            }
            if ($PSCmdlet.ShouldProcess('Remove all bounces from SendGrid')) {
                try {
                    Invoke-SendGrid @InvokeSplat
                }
                catch {
                    Write-Error ('Failed to remove all SendGrid bounces. {0}' -f $_.Exception.Message) -ErrorAction Stop
                }
            }
        }
        foreach ($Id in $EmailAddress) {
            $InvokeSplat = @{
                Method        = 'Delete'
                Namespace     = "suppression/bounces/$($Id.Address)"
                ErrorAction   = 'Stop'
                CallingCmdlet = $PSCmdlet.MyInvocation.MyCommand.Name
            }
            if ($PSBoundParameters.OnBehalfOf) {
                $InvokeSplat.Add('OnBehalfOf', $OnBehalfOf)
            }
            if ($PSCmdlet.ShouldProcess(('Remove bounce with email address {0}' -f $Id.Address))) {
                try {
                    Invoke-SendGrid @InvokeSplat
                }
                catch {
                    Write-Error ('Failed to remove SendGrid bounce "{0}". {0}' -f $Id.Address, $_.Exception.Message) -ErrorAction Stop
                }
            }
        }
    }
}
#EndRegion '.\Public\Remove-SGBounce.ps1' 119
#Region '.\Public\Remove-SGBrandedDomainLink.ps1' 0
function Remove-SGBrandedDomainLink {
    <#
    .SYNOPSIS
        Removes a Branded Domain Link from the current SendGrid instance.
 
    .DESCRIPTION
        Remove-SGBrandedDomainLink removes a branded domain link from the current SendGrid instance. Branded Domain Links allows all of the click-tracked links,
        opens, and images in your emails to be served from your domain rather than sendgrid.net. It improves the trustworthiness of your emails. You must provide
        the unique identifier of the branded link to be removed. Please note that you might need to remove the DNS records manually after removing the branded link.
 
    .PARAMETER UniqueId
        Specifies the unique identifier for the branded link to remove.
 
    .EXAMPLE
        PS C:\> Remove-SGBrandedDomainLink -UniqueId '1234567'
 
        Removes the branded domain link with the unique identifier '1234567'.
 
    .EXAMPLE
        PS C:\> Get-SGBrandedDomainLink | Where-Object { $_.Domain -eq 'example.com' } | Remove-SGBrandedDomainLink
 
        Removes the branded domain link 'example.com' using its unique identifier obtained from the Get-SGBrandedDomainLink cmdlet.
 
    .NOTES
        To use this function, you must be connected to a SendGrid instance. Use the Connect-SendGrid function to establish a connection.
    #>

    [CmdletBinding(
        SupportsShouldProcess,
        ConfirmImpact = 'High')]
    param (
        # Specifies a the UniqueId for the branded link to remove.
        [Parameter(
            Mandatory,
            ValueFromPipeline,
            ValueFromPipelineByPropertyName,
            DontShow,
            ParameterSetName = 'InputObject'
        )]
        [Object[]]$InputObject,
        
        # Specifies a the UniqueId for the branded link to remove.
        [Parameter(
            Mandatory,
            Position = 0,
            ParameterSetName = 'UniqueId'
        )]
        [Alias('Id')]
        [string[]]$UniqueId,

        # Specifies a On Behalf Of header to allow you to make API calls from a parent account on behalf of the parent's Subusers or customer accounts.
        [Parameter()]
        [string]$OnBehalfOf
    )
    process {
        if ($PSCmdlet.ParameterSetName -eq 'InputObject') {
            $UniqueId = @()
            foreach ($Object in $InputObject) {
                switch ($Object) {
                    { $_ -is [string] } { $UniqueId += $_; break }
                    { $_ -is [int] } { $UniqueId += $_; break }
                    { $_ -is [System.Management.Automation.PSCustomObject] } { $UniqueId += $_.Id; break }
                    default { Write-Error ('Failed to convert InputObject to Id.') -ErrorAction Stop }
                }
            }            
        }
        foreach ($Id in $UniqueId) { 
            $InvokeSplat = @{
                Method        = 'Delete'
                Namespace     = "whitelabel/links/$Id"
                ErrorAction   = 'Stop'
                CallingCmdlet = $PSCmdlet.MyInvocation.MyCommand.Name
            }
            $GetSplat = @{
                UniqueId    = $Id
                ErrorAction = 'Stop'
            }
            if ($PSBoundParameters.OnBehalfOf) {
                $InvokeSplat.Add('OnBehalfOf', $OnBehalfOf)
                $GetSplat.Add('OnBehalfOf', $OnBehalfOf)
            }
            $SGBrandedDomainLink = Get-SGBrandedDomainLink @GetSplat -ShowDNS
            Write-Verbose -Message ("Don't forget to remove DNS records.") -Verbose
            $SGBrandedDomainLink

            if ($PSCmdlet.ShouldProcess(('{0}.{1}' -f $SGBrandedDomainLink.Subdomain, $SGBrandedDomainLink.Domain))) {
                try {
                    Invoke-SendGrid @InvokeSplat
                }
                catch {
                    Write-Error ('Failed to remove SendGrid Branded Domain Link. {0}' -f $_.Exception.Message) -ErrorAction Stop
                }
            }
        }
    }
}
#EndRegion '.\Public\Remove-SGBrandedDomainLink.ps1' 96
#Region '.\Public\Remove-SGGlobalSuppression.ps1' 0
function Remove-SGGlobalSuppression {
    <#
    .SYNOPSIS
        Removes a specific email address from the global suppressions list in SendGrid.
 
    .DESCRIPTION
        Remove-SGSGlobalSuppression removes a specific email address from the global suppressions list in SendGrid.
 
    .PARAMETER EmailAddress
        Specifies the email address to remove from the global suppressions list.
 
    .PARAMETER OnBehalfOf
        Specifies an On Behalf Of header to allow you to make API calls from a parent account on behalf of the parent's Subusers or customer accounts.
 
    .EXAMPLE
        PS C:\> Remove-SGSGlobalSuppression -EmailAddress 'test@example.com'
        This command removes the email address 'test@example.com' from the global suppressions list in SendGrid.
 
    .EXAMPLE
        PS C:\> Remove-SGSGlobalSuppression -EmailAddress 'test@example.com' -OnBehalfOf 'Subuser'
        This command removes the email address 'test@example.com' from the global suppressions list in SendGrid for the Subuser 'Subuser'.
    #>

    [CmdletBinding(
        SupportsShouldProcess,
        ConfirmImpact = 'High',
        DefaultParameterSetName = 'Default'
    )]
    param (
        # Specifies the email address to remove from the global suppressions list.
        [Parameter(
            Mandatory,
            ValueFromPipeline,
            ValueFromPipelineByPropertyName,
            DontShow,
            ParameterSetName = 'InputObject'
        )]
        [Object[]]$InputObject,
        
        # Specifies the email address to remove from the global suppressions list.
        [Parameter(
            Mandatory,
            ParameterSetName = 'Default',
            Position = 0
        )]
        [Alias('Email')]
        [MailAddress[]]$EmailAddress,

        # Specifies an On Behalf Of header to allow you to make API calls from a parent account on behalf of the parent's Subusers or customer accounts.
        [Parameter(ParameterSetName = 'Default')]
        [Parameter(ParameterSetName = 'InputObject')]
        [string]$OnBehalfOf
    )
    process {
        if ($PSCmdlet.ParameterSetName -eq 'InputObject') {
            $UniqueId = @()
            foreach ($Object in $InputObject) {
                switch ($Object) {
                    { $_ -is [string] } { $UniqueId += $_; break }
                    { $_ -is [int] } { $UniqueId += $_; break }
                    { $_ -is [System.Management.Automation.PSCustomObject] } { $UniqueId += $_.Id; break }
                    default { Write-Error ('Failed to convert InputObject to Id.') -ErrorAction Stop }
                }
            }            
        }
        foreach ($Id in $EmailAddress) {
            $InvokeSplat = @{
                Method        = 'Delete'
                Namespace     = "suppression/unsubscribes/$Id"
                ErrorAction   = 'Stop'
                CallingCmdlet = $PSCmdlet.MyInvocation.MyCommand.Name
            }
            if ($PSBoundParameters.OnBehalfOf) {
                $InvokeSplat.Add('OnBehalfOf', $OnBehalfOf)
            }
            if ($PSCmdlet.ShouldProcess(('Remove email address {0} from global suppressions list.' -f $Id))) {
                try {
                    Invoke-SendGrid @InvokeSplat
                }
                catch {
                    Write-Error ('Failed to remove email address "{0}" from global suppressions list. {0}' -f $Id, $_.Exception.Message) -ErrorAction Stop
                }
            }
        }
    }
}
#EndRegion '.\Public\Remove-SGGlobalSuppression.ps1' 86
#Region '.\Public\Remove-SGInvalidEmail.ps1' 0
function Remove-SGInvalidEmail {
    <#
    .SYNOPSIS
        Removes a specific invalid email from SendGrid.
 
    .DESCRIPTION
        Remove-SGInvalidEmail removes a specific invalid email from SendGrid based on its email address.
 
    .PARAMETER EmailAddress
        Specifies the email address of the invalid email to remove.
 
    .PARAMETER OnBehalfOf
        Specifies an On Behalf Of header to allow you to make API calls from a parent account on behalf of the parent's Subusers or customer accounts.
 
    .EXAMPLE
        PS C:\> Remove-SGInvalidEmail -EmailAddress invalid1@example.com
 
        This command removes the invalid email with the email address 'invalid1@example.com' from SendGrid.
 
    .EXAMPLE
        PS C:\> Remove-SGInvalidEmail -EmailAddress invalid2@example.com -OnBehalfOf 'Subuser'
 
        This command removes the invalid email with the email address 'invalid2@example.com' from SendGrid for the Subuser 'Subuser'.
    #>

    [CmdletBinding(
        DefaultParameterSetName = 'Default',
        SupportsShouldProcess,
        ConfirmImpact = 'High'
    )]
    param (
        # Specifies the invalid email address to remove.
        [Parameter(
            Mandatory,
            ValueFromPipeline,
            ValueFromPipelineByPropertyName,
            DontShow,
            ParameterSetName = 'InputObject'
        )]
        [Object[]]$InputObject,
        
        # Specifies the invalid email address to remove.
        [Parameter(
            Mandatory,
            ParameterSetName = 'Default',
            Position = 0
        )]
        [Alias('Email')]
        [MailAddress[]]$EmailAddress,

        # Specifies whether to delete all emails on the invalid email address list.
        [Parameter(ParameterSetName = 'DeleteAll')]
        [switch]$DeleteAll,

        # Specifies an On Behalf Of header to allow you to make API calls from a parent account on behalf of the parent's Subusers or customer accounts.
        [Parameter(ParameterSetName = 'Default')]
        [Parameter(ParameterSetName = 'DeleteAll')]
        [Parameter(ParameterSetName = 'InputObject')]
        [string]$OnBehalfOf
    )
    process {
        if ($PSCmdlet.ParameterSetName -eq 'InputObject') {
            $EmailAddress = @()
            foreach ($Object in $InputObject) {
                switch ($Object) {
                    { $_ -is [string] } { $EmailAddress += $_; break }
                    { $_ -is [System.Management.Automation.PSCustomObject] } { $EmailAddress += $_.Email; break }
                    default { Write-Error ('Failed to convert InputObject to Id.') -ErrorAction Stop }
                }
            }            
        }
        if ($PSCmdlet.ParameterSetName -eq 'DeleteAll') {
            $InvokeSplat = @{
                Method        = 'Delete'
                Namespace     = 'suppression/invalid_emails'
                ErrorAction   = 'Stop'
                CallingCmdlet = $PSCmdlet.MyInvocation.MyCommand.Name
            }
            if ($PSBoundParameters.OnBehalfOf) {
                $InvokeSplat.Add('OnBehalfOf', $OnBehalfOf)
            }
            if ($PSCmdlet.ShouldProcess('Remove all invalid email addresses from SendGrid')) {
                try {
                    Invoke-SendGrid @InvokeSplat
                }
                catch {
                    Write-Error ('Failed to remove all SendGrid invalid email address. {0}' -f $_.Exception.Message) -ErrorAction Stop
                }
            }
        }
        else {
            foreach ($Id in $EmailAddress) {
                $InvokeSplat = @{
                    Method        = 'Delete'
                    Namespace     = "suppression/invalid_emails/$($Id.Address)"
                    ErrorAction   = 'Stop'
                    CallingCmdlet = $PSCmdlet.MyInvocation.MyCommand.Name
                }
                if ($PSBoundParameters.OnBehalfOf) {
                    $InvokeSplat.Add('OnBehalfOf', $OnBehalfOf)
                }
                if ($PSCmdlet.ShouldProcess(('Remove invalid email address {0}' -f $Id.Address))) {
                    try {
                        Invoke-SendGrid @InvokeSplat
                    }
                    catch {
                        Write-Error ('Failed to remove SendGrid invalid email address "{0}". {0}' -f $Id.Address, $_.Exception.Message) -ErrorAction Stop
                    }
                }
            }
        }
    }
}
#EndRegion '.\Public\Remove-SGInvalidEmail.ps1' 113
#Region '.\Public\Remove-SGSpamReport.ps1' 0
function Remove-SGSpamReport {
    <#
    .SYNOPSIS
        Removes a specific spam report from SendGrid.
 
    .DESCRIPTION
        Remove-SGSpamReport removes a specific spam report from SendGrid based on its ID.
 
    .PARAMETER ReportId
        Specifies the ID of the spam report to remove.
 
    .PARAMETER OnBehalfOf
        Specifies an On Behalf Of header to allow you to make API calls from a parent account on behalf of the parent's Subusers or customer accounts.
 
    .EXAMPLE
        PS C:\> Remove-SGSpamReport -EmailAddress spam1@example.com
        This command removes the spam report with the email address spam1@example.com from SendGrid.
 
    .EXAMPLE
        PS C:\> Remove-SGSpamReport -EmailAddress spam2@example.com -OnBehalfOf 'Subuser'
        This command removes the spam report with the email address spam2@example.com from SendGrid for the Subuser 'Subuser'.
    #>

    [CmdletBinding(
        DefaultParameterSetName = 'Default',
        SupportsShouldProcess,
        ConfirmImpact = 'High'
    )]
    param (
        # Specifies the invalid email address to remove.
        [Parameter(
            Mandatory,
            ValueFromPipeline,
            ValueFromPipelineByPropertyName,
            DontShow,
            ParameterSetName = 'InputObject'
        )]
        [Object[]]$InputObject,

        # Specifies the invalid email address to remove.
        [Parameter(
            Mandatory,
            ParameterSetName = 'Default',
            Position = 0
        )]
        [Alias('Email')]
        [MailAddress[]]$EmailAddress,

        # Specifies whether to delete all emails on the invalid email address list.
        [Parameter(ParameterSetName = 'DeleteAll')]
        [switch]$DeleteAll,

        # Specifies an On Behalf Of header to allow you to make API calls from a parent account on behalf of the parent's Subusers or customer accounts.
        [Parameter(ParameterSetName = 'Default')]
        [Parameter(ParameterSetName = 'DeleteAll')]
        [Parameter(ParameterSetName = 'InputObject')]
        [string]$OnBehalfOf
    )
    process {
        if ($PSCmdlet.ParameterSetName -eq 'InputObject') {
            $EmailAddress = @()
            foreach ($Object in $InputObject) {
                switch ($Object) {
                    { $_ -is [string] } { $EmailAddress += $_; break }
                    { $_ -is [System.Management.Automation.PSCustomObject] } { $EmailAddress += $_.Email; break }
                    default { Write-Error ('Failed to convert InputObject to Id.') -ErrorAction Stop }
                }
            }            
        }
        if ($PSCmdlet.ParameterSetName -eq 'DeleteAll') {
            $InvokeSplat = @{
                Method        = 'Delete'
                Namespace     = 'suppression/spam_reports'
                ErrorAction   = 'Stop'
                CallingCmdlet = $PSCmdlet.MyInvocation.MyCommand.Name
            }
            if ($PSBoundParameters.OnBehalfOf) {
                $InvokeSplat.Add('OnBehalfOf', $OnBehalfOf)
            }
            if ($PSCmdlet.ShouldProcess('Remove all email addresses from SendGrid spam reports.')) {
                try {
                    Invoke-SendGrid @InvokeSplat
                }
                catch {
                    Write-Error ('Failed to remove all email addresses from SendGrid spam reports. {0}' -f $_.Exception.Message) -ErrorAction Stop
                }
            }
        }
        else {
            foreach ($Id in $EmailAddress) {
                $InvokeSplat = @{
                    Method        = 'Delete'
                    Namespace     = "suppression/spam_reports/$($Id.Address)"
                    ErrorAction   = 'Stop'
                    CallingCmdlet = $PSCmdlet.MyInvocation.MyCommand.Name
                }
                if ($PSBoundParameters.OnBehalfOf) {
                    $InvokeSplat.Add('OnBehalfOf', $OnBehalfOf)
                }
                if ($PSCmdlet.ShouldProcess(('Remove email address {0} from spam report.' -f $Id.Address))) {
                    try {
                        Invoke-SendGrid @InvokeSplat
                    }
                    catch {
                        Write-Error ('Failed to remove email address "{0}" from SendGrid spam report. {0}' -f $Id.Address, $_.Exception.Message) -ErrorAction Stop
                    }
                }
            }
        }
    }
}
#EndRegion '.\Public\Remove-SGSpamReport.ps1' 111
#Region '.\Public\Remove-SGSubuser.ps1' 0
function Remove-SGSubuser {
    <#
    .SYNOPSIS
        Removes a specific Subuser within the current SendGrid instance.
 
    .DESCRIPTION
        Remove-SGSubuser removes a specific Subuser based on its username within the current SendGrid instance.
 
    .PARAMETER Username
        Specifies the ID of the Subuser to remove.
 
    .EXAMPLE
        PS C:\> Remove-SGSubuser -Username <username>
         
        This command removes the Subuser with the specified username within the current SendGrid instance.
    #>

    [CmdletBinding(
        SupportsShouldProcess,
        ConfirmImpact = 'High'
    )]
    param (
        # Specifies the ID of the Subuser to remove.
        [Parameter(
            Mandatory = $true,
            ValueFromPipeline,
            ValueFromPipelineByPropertyName,
            Position = 0
        )]
        [string]$Username
    )

    process {
        $InvokeSplat = @{
            Method        = 'Delete'
            Namespace     = "subusers/$Username"
            ErrorAction   = 'Stop'
            CallingCmdlet = $PSCmdlet.MyInvocation.MyCommand.Name
        }

        if ($PSCmdlet.ShouldProcess(('{0}' -f 'Subuser'))) {
            try {
                Invoke-SendGrid @InvokeSplat
            }
            catch {
                Write-Error ('Failed to remove SendGrid Subuser. {0}' -f $_.Exception.Message) -ErrorAction Stop
            }
        }
    }
}
#EndRegion '.\Public\Remove-SGSubuser.ps1' 50
#Region '.\Public\Remove-SGSuppressionGroup.ps1' 0
function Remove-SGSuppressionGroup {
    <#
    .SYNOPSIS
        Deletes a suppression group.
 
    .DESCRIPTION
        The Remove-SGSuppressionGroup function deletes a suppression group in SendGrid.
         
    .PARAMETER GroupId
        Specifies the ID of the suppression group.
 
    .PARAMETER OnBehalfOf
        Specifies a On Behalf Of header to allow you to make API calls from a parent account on behalf of the parent's Subusers or customer accounts.
 
    .EXAMPLE
        PS C:\> Remove-SGSuppressionGroup -GroupId 123
        This command deletes the suppression group with the ID 123.
    #>

    [CmdletBinding(
        SupportsShouldProcess,
        ConfirmImpact = 'High'
    )]
    param (
        # Specifies the ID of the suppression group.
        [Parameter(
            Mandatory,
            ValueFromPipeline,
            ValueFromPipelineByPropertyName,
            DontShow,
            ParameterSetName = 'InputObject'
        )]
        [Object[]]$InputObject,
        
        # Specifies the ID of the suppression group.
        [Parameter(
            Mandatory,
            Position = 0,
            ParameterSetName = 'UniqueId'
        )]
        [Alias('Id')]
        [int]$UniqueId,

        # Specifies a On Behalf Of header to allow you to make API calls from a parent account on behalf of the parent's Subusers or customer accounts.
        [Parameter()]
        [string]$OnBehalfOf
    )
    process {
        if ($PSCmdlet.ParameterSetName -eq 'InputObject') {
            $UniqueId = @()
            foreach ($Object in $InputObject) {
                switch ($Object) {
                    { $_ -is [string] } { $UniqueId += $_; break }
                    { $_ -is [int] } { $UniqueId += $_; break }
                    { $_ -is [System.Management.Automation.PSCustomObject] } { $UniqueId += $_.Id; break }
                    default { Write-Error ('Failed to convert InputObject to Id.') -ErrorAction Stop }
                }
            }            
        }
        $InvokeSplat = @{
            Method        = 'Delete'
            Namespace     = "asm/groups/$UniqueId"
            ErrorAction   = 'Stop'
            CallingCmdlet = $PSCmdlet.MyInvocation.MyCommand.Name
        }
        if ($PSBoundParameters.ContainsKey('OnBehalfOf')) {
            $InvokeSplat.OnBehalfOf = $OnBehalfOf
        }
        if ($PSCmdlet.ShouldProcess(('Delete suppression group with ID {0}.' -f $UniqueId))) {
            try {
                Invoke-SendGrid @InvokeSplat
            }
            catch {
                Write-Error ('Failed to delete suppression group. {0}' -f $_.Exception.Message) -ErrorAction Stop
            }
        }
    }
}
#EndRegion '.\Public\Remove-SGSuppressionGroup.ps1' 78
#Region '.\Public\Send-SGMailMessage.ps1' 0
function Send-SGMailMessage {
    <#
    .SYNOPSIS
        Sends an email via the SendGrid API.
 
    .DESCRIPTION
        The Send-SGMailMessage function sends an email using the SendGrid API. It allows you to specify the sender, recipient, subject, and body of the email, as well as any attachments.
 
    .PARAMETER From
        Specifies the sender's email address.
 
    .PARAMETER To
        One or an array of recipients who will receive your email.
        Each object in this array must contain the recipient's email address.
        Each object in the array may optionally contain the recipient's name. 'Name<Name@example.com>'
        'Name name@example.com'
        'Firstname Lastname firstname.lastname@example.com'
        'Firstname Lastname <firstname.lastname@example.com>'
        'Firstname.Lastname firstname.lastname@example.com'
        '"Firstname Lastname" firstname.lastname@example.com'
        '"Firstname Lastname" <firstname.lastname@example.com>'
 
    .PARAMETER Subject
        Specifies the email subject.
 
    .PARAMETER Body
        Specifies the email body.
 
    .PARAMETER CC
        Specifies the CC email address. CC addresses are not visible to the recipients of the email.
        One or an array of CC who will receive your email.
        Each object in this array must contain the recipient's email address.
        Each object in the array may optionally contain the recipient's name.
        'Name<Name@example.com>'
        'Name name@example.com'
        'Firstname Lastname firstname.lastname@example.com'
        'Firstname Lastname <firstname.lastname@example.com>'
        'Firstname.Lastname firstname.lastname@example.com'
        '"Firstname Lastname" firstname.lastname@example.com'
        '"Firstname Lastname" <firstname.lastname@example.com>'
 
    .PARAMETER BCC
        Specifies the BCC email address. BCC addresses are not visible to the recipients of the email.
        One or an array of BCC who will receive your email.
        Each object in this array must contain the recipient's email address.
        Each object in the array may optionally contain the recipient's name.
        'Name<Name@example.com>'
        'Name name@example.com'
        'Firstname Lastname firstname.lastname@example.com'
        'Firstname Lastname <firstname.lastname@example.com>'
        'Firstname.Lastname firstname.lastname@example.com'
        '"Firstname Lastname" firstname.lastname@example.com'
        '"Firstname Lastname" <firstname.lastname@example.com>'
 
    .PARAMETER BodyAsHtml
        Specifies if the email body is formatted as HTML. Default is False, i.e. plain text.
 
    .PARAMETER Attachment
        Specifies the attachment(s) to be included in the email.
 
    .PARAMETER Priority
        Specifies the email priority. Valid values are 'Low', 'Normal', and 'High'.
 
    .PARAMETER SeparateTo
        Specifies if Separate To should be used.
 
    .PARAMETER ReplyTo
        Specifies if a separate ReplyTo address should be used. If not specified, the sender's email address (From) will be used.
     
    .PARAMETER SendAt
        Specifies the date and time to send the email. If not specified, the email will be sent immediately. Both datetime and unix timestamp formats are accepted.
        A unix timestamp allowing you to specify when your email should be delivered. Scheduling delivery more than 72 hours in advance is forbidden.
 
    .PARAMETER TemplateId
        Specifies the template ID to use. An email template ID. A template that contains a subject and content — either text or html — will override any subject and content values specified at the personalizations or message level.
 
    .PARAMETER Categories
        Specifies an array of category names for this message. Each category name may not exceed 255 characters.
     
    .PARAMETER BatchId
        Specifies an ID representing a batch of emails to be sent at the same time. Including a batch_id in your request allows you include this email in that batch. It also enables you to cancel or pause the delivery of that batch. For more information, see the Cancel Scheduled Sends API.
 
    .EXAMPLE
        PS C:\> Send-SGMailMessage -From 'sender@example.com' -To 'recipient@example.com' -Subject 'Test Email' -Body 'Hello, this is a test email.'
         
        This command sends an email with the specified parameters via the SendGrid API.
    #>

    [CmdletBinding(
        SupportsShouldProcess,
        DefaultParameterSetName = 'Default'
    )]
    [Alias('Send-SGMessage', 'Send-SGMail')]
    param (
        # Specifies the sender's email address.
        [Parameter(
            Position = 0,
            Mandatory = $true,
            ParameterSetName = 'Default'
        )]
        [Parameter(
            Position = 0,
            Mandatory = $true,
            ParameterSetName = 'SeparateTo'
        )]
        [MailAddress]$From,

        # One or an array of recipients who will receive your email. Each object in this array must contain the recipient's email address. Each object in the array may optionally contain the recipient's name. 'Name<Name@example.com>'
        [Parameter(
            Position = 1,
            Mandatory = $true,
            ParameterSetName = 'Default'
        )]
        [Parameter(
            Position = 1,
            Mandatory = $true,
            ParameterSetName = 'SeparateTo'
        )]
        [Alias('Recipient')]
        [MailAddress[]]$To,

        # An array of recipients who will receive a copy of your email. Each object in this array must contain the recipient's email address. Each object in the array may optionally contain the recipient's name. 'Name<Name@example.com>'
        [Parameter(
            Position = 2,
            ParameterSetName = 'Default'
        )]
        [MailAddress[]]$CC,

        # An array of recipients who will receive a blind copy of your email. Each object in this array must contain the recipient's email address. Each object in the array may optionally contain the recipient's name. 'Name<Name@example.com>'
        [Parameter(
            Position = 3,
            ParameterSetName = 'Default'
        )]
        [MailAddress[]]$BCC,

        # Specifies the email subject.
        [Parameter(
            Position = 4,
            Mandatory = $true,
            ParameterSetName = 'Default'
        )]
        [Parameter(
            Position = 4,
            Mandatory = $true,
            ParameterSetName = 'SeparateTo'
        )]
        [ValidateLength(1, 998)]
        [string]$Subject,

        # Specifies the email body.
        [Parameter(
            Position = 5,
            Mandatory = $true,
            ParameterSetName = 'Default'
        )]
        [Parameter(
            Position = 5,
            Mandatory = $true,
            ParameterSetName = 'SeparateTo'
        )]
        [string]$Body,

        # Specifies if the email body is formatted as HTML.
        [Parameter(
            Position = 6,
            ParameterSetName = 'Default'
        )]
        [Parameter(
            Position = 6,
            ParameterSetName = 'SeparateTo'
        )]
        [switch]$BodyAsHtml,

        # Specifies the attachment(s) to be included in the email.
        [Parameter(
            Position = 7,
            ParameterSetName = 'Default'
        )]
        [Parameter(
            Position = 7, 
            ParameterSetName = 'SeparateTo'
        )]
        [Alias('Attachments')]
        [System.Net.Mail.Attachment[]]$Attachment,

        # Specifies the email priority. Valid values are 'Low', 'Normal', and 'High'.
        [Parameter(ParameterSetName = 'Default')]
        [Parameter(ParameterSetName = 'SeparateTo')]
        [Alias('Importance')]
        [ValidateSet('Low', 'Normal', 'High')]
        [string]$Priority,

        # Specifies if Separate To should be used.
        [Parameter(ParameterSetName = 'SeparateTo')]
        [switch]$SeparateTo,

        # Specifies if a separate ReplyTo address should be used.
        [Parameter(ParameterSetName = 'Default')]
        [Parameter(ParameterSetName = 'SeparateTo')]
        [MailAddress]$ReplyTo,

        # Specifies the date and time to send the email. If not specified, the email will be sent immediately. Both datetime and unix timestamp formats are accepted.
        # Scheduling delivery more than 72 hours in advance is forbidden.
        [Parameter(ParameterSetName = 'Default')]
        [Parameter(ParameterSetName = 'SeparateTo')]
        [UnixTime]$SendAt,

        # Specifies the template ID to use. An email template ID. A template that contains a subject and content — either text or html — will override any subject and content values specified at the personalizations or message level.
        [Parameter(ParameterSetName = 'Default')]
        [Parameter(ParameterSetName = 'SeparateTo')]
        [string]$TemplateId,

        # Specifies an array of category names for this message. Each category name may not exceed 255 characters.
        [Parameter(ParameterSetName = 'Default')]
        [Parameter(ParameterSetName = 'SeparateTo')]
        [ValidateLength(1, 10)]
        [string[]]$Categories,

        # Specifies an ID representing a batch of emails to be sent at the same time. Including a batch_id in your request allows you include this email in that batch. It also enables you to cancel or pause the delivery of that batch. For more information, see the Cancel Scheduled Sends API.
        [Parameter(ParameterSetName = 'Default')]
        [Parameter(ParameterSetName = 'SeparateTo')]
        [string]$BatchId,

        <#
            Specifies an object of type [SGASM] that allows you to specify how to handle unsubscribes.
 
            The [SGASM] class represents a set of options for handling unsubscribes. It has the following properties:
 
            - GroupId: An integer that represents the group ID for unsubscribes. Default value is 0.
            - GroupsToDisplay: An array of integers that represents the groups to display for unsubscribes. Default value is an empty array.
 
            You can create an instance of [SGASM] using the following constructors:
            - SGASM(): Creates an instance with default values for GroupId and GroupsToDisplay.
            - SGASM([int]$GroupId): Creates an instance with the specified GroupId and default value for GroupsToDisplay.
            - SGASM([int]$GroupId, [int[]]$GroupsToDisplay): Creates an instance with the specified GroupId and GroupsToDisplay.
 
            The ToString() method returns a string representation of the GroupId.
 
            Example usage:
            $unsubscribe = [SGASM]::new(123, @(1, 2, 3))
            Send-SGMailMessage -Unsubscribe $unsubscribe
        #>

        [Parameter(ParameterSetName = 'Default')]
        [Parameter(ParameterSetName = 'SeparateTo')]
        [ValidateNotNullOrEmpty()]
        [SGASM]$Unsubscribe


    )
    begin {
        $InvokeSplat = @{
            Method        = 'Post'
            Namespace     = 'mail/send'
            ErrorAction   = 'Stop'
            CallingCmdlet = $PSCmdlet.MyInvocation.MyCommand.Name
        }
        [hashtable]$ContentBody = @{
            personalizations = [System.Collections.Generic.List[hashtable]]::new()
        }
        $RecipientCount = $To.Count + $CC.Count + $BCC.Count
    }
    process {
        if ($PSCmdlet.ShouldProcess(('{0} to "{1}" recipients with subject: "{2}"' -f $From.Address, $RecipientCount, $Subject))) {
        
            # Convert the MailAddress objects to SendGrid API compatible objects.
            $FromList = ConvertTo-SendGridAddress -Address $From
            $ToList = ConvertTo-SendGridAddress -Address $To
            $CCList = ConvertTo-SendGridAddress -Address $CC
            $BCCList = ConvertTo-SendGridAddress -Address $BCC
            $ReplyToList = ConvertTo-SendGridAddress -Address $ReplyTo
            <#
            Personalizations
            An array of messages and their metadata. Each object within personalizations can be thought of as an envelope - it defines who should receive an individual message and how that message should be handled. See our Personalizations documentation for examples.
            maxItems: 1000
            Personalizations can contain the following fields:
                from
                to
                cc = An array of recipients who will receive a copy of your email. Each object in this array must contain the recipient's email address. Each object in the array may optionally contain the recipient's name.
                bcc = An array of recipients who will receive a blind carbon copy of your email. Each object in this array must contain the recipient's email address. Each object in the array may optionally contain the recipient's name.
                subject = The subject of your email. See character length requirements according to RFC 2822.
                headers = A collection of JSON key/value pairs allowing you to specify handling instructions for your email. You may not overwrite the following headers: x-sg-id, x-sg-eid, received, dkim-signature, Content-Type, Content-Transfer-Encoding, To, From, Subject, Reply-To, CC, BCC
                substitutions = Substitutions allow you to insert data without using Dynamic Transactional Templates. This field should not be used in combination with a Dynamic Transactional Template, which can be identified by a template_id starting with d-. This field is a collection of key/value pairs following the pattern "substitution_tag":"value to substitute". The key/value pairs must be strings. These substitutions will apply to the text and html content of the body of your email, in addition to the subject and reply-to parameters. The total collective size of your substitutions may not exceed 10,000 bytes per personalization object.
                dynamic_template_data = Dynamic template data is available using Handlebars syntax in Dynamic Transactional Templates. This field should be used in combination with a Dynamic Transactional Template, which can be identified by a template_id starting with d-. This field is a collection of key/value pairs following the pattern "variable_name":"value to insert".
                custom_args = Values that are specific to this personalization that will be carried along with the email and its activity data. Substitutions will not be made on custom arguments, so any string that is entered into this parameter will be assumed to be the custom argument that you would like to be used. This field may not exceed 10,000 bytes.
                send_at = A unix timestamp allowing you to specify when your email should be delivered. Scheduling delivery more than 72 hours in advance is forbidden.
            #>

            if ($SeparateTo) {
                foreach ($T in $To) {
                    $Personalizations = @{
                        subject = $Subject
                        to      = @(
                            ConvertTo-SendGridAddress -Address $T
                        )
                    }
                    $ContentBody.personalizations.Add($Personalizations)
                }
            }
            else {
                $ContentBody.personalizations.Add(@{
                        subject = $Subject
                        to      = @($ToList)
                        cc      = @($CCList)
                        bcc     = @($BCCList)
                    })
            }
            $ContentBody.personalizations | Remove-EmptyHashtable -Recursive
            $ContentBody.Add('from', $FromList)
            if ($PSBoundParameters.ContainsKey('ReplyTo')) {
                $ContentBody.Add('reply_to', $ReplyToList)
            }
            $ContentBody.Add('content', @(
                    @{
                        type  = if ($BodyAsHtml) { 'text/html' } else { 'text/plain' }
                        value = $Body
                    }
                ))
            if ($PSBoundParameters.ContainsKey('Attachment')) {
                $ContentBody.Add('attachments', @(
                        foreach ($A in $Attachment) {
                            @{
                                content     = [Convert]::ToBase64String([IO.File]::ReadAllBytes($A.ContentStream.Name))
                                filename    = $A.Name
                                type        = $A.ContentType.MediaType
                                disposition = 'attachment'
                            }
                        }
                    ))
            }
            if ($PSBoundParameters.ContainsKey('Priority')) {
                $ContentBody.Add('priority', $Priority)
            }
            if ($PSBoundParameters.ContainsKey('SendAt')) {
                $ContentBody.Add('send_at', $SendAt.ToUnixTime())
            }
            if ($PSBoundParameters.ContainsKey('TemplateId')) {
                $ContentBody.Add('template_id', $TemplateId)
            }
            if ($PSBoundParameters.ContainsKey('Categories')) {
                $ContentBody.Add('categories', $Categories)
            }

            try {
                Remove-EmptyHashtable -Hashtable $ContentBody -Recursive
                $InvokeSplat.Add('ContentBody', $ContentBody)
                Invoke-SendGrid @InvokeSplat
            }
            catch {
                Write-Error ('Failed to send email via SendGrid API. {0}' -f $_.Exception.Message) -ErrorAction Stop
            }
        }
    }
}
#EndRegion '.\Public\Send-SGMailMessage.ps1' 352
#Region '.\Public\Set-SGAddressWhitelistSetting.ps1' 0
function Set-SGAddressWhitelistSetting {
    <#
    .SYNOPSIS
        Updates the address whitelist mail settings on SendGrid.
    .DESCRIPTION
        Set-SGAddressWhitelistSetting updates the address whitelist mail settings on SendGrid.
    .PARAMETER Enabled
        Specifies whether the email address whitelist is enabled.
    .PARAMETER List
        Specifies a list of email addresses or domains to be whitelisted.
    .PARAMETER OnBehalfOf
        Specifies an On Behalf Of header to allow you to make API calls from a parent account on behalf of the parent's Subusers or customer accounts.
    .EXAMPLE
        PS C:\> Set-SGAddressWhitelistSetting -Enabled $true -List @('example.com')
        This command updates the address whitelist mail settings on SendGrid to enable the whitelist and add 'example.com' to the whitelist.
    #>

    [CmdletBinding()]
    param (
        # Specifies whether the email address whitelist is enabled.
        [Parameter()]
        [switch]$Enabled,

        # Specifies a list of email addresses or domains to be whitelisted. To clear the list, pass an empty array (e.g. @()
        [Parameter()]
        [AllowEmptyCollection()]
        [string[]]$List,

        # Specifies an On Behalf Of header to allow you to make API calls from a parent account on behalf of the parent's Subusers or customer accounts.
        [Parameter()]
        [string]$OnBehalfOf
    )
    process {
        [hashtable]$ContentBody = @{}
        $InvokeSplat = @{
            Method        = 'Patch'
            Namespace     = 'mail_settings/address_whitelist'
            ErrorAction   = 'Stop'
            CallingCmdlet = $PSCmdlet.MyInvocation.MyCommand.Name
        }
        if ($PSBoundParameters.OnBehalfOf) {
            $InvokeSplat.Add('OnBehalfOf', $OnBehalfOf)
        }
        
        if ($PSBoundParameters.ContainsKey('Enabled')) {
            $ContentBody.Add('enabled', $Enabled.IsPresent)
        }
        if ($PSBoundParameters.ContainsKey('List')) {
            if ($List.Count -eq 0) {
                $ContentBody.Add('list', @())
            }
            else {
                $ContentBody.Add('list', @($List))
            }
        }
        $InvokeSplat.Add('ContentBody', $ContentBody)
        try {
            Invoke-SendGrid @InvokeSplat
        }
        catch {
            Write-Error ('Failed to update SendGrid address whitelist settings. {0}' -f $_.Exception.Message) -ErrorAction Stop
        }
    }
}
#EndRegion '.\Public\Set-SGAddressWhitelistSetting.ps1' 64
#Region '.\Public\Set-SGAlert.ps1' 0
function Set-SGAlert {
    <#
    .SYNOPSIS
        Updates an existing alert on SendGrid.
 
    .DESCRIPTION
        Set-SGAlert updates an existing alert on SendGrid based on the provided parameters.
 
    .PARAMETER AlertId
        Specifies the ID of the alert to update.
 
    .PARAMETER EmailTo
        Specifies the new email address the alert will be sent to.
 
    .PARAMETER Frequency
        Specifies the new frequency at which the alert will be sent. Required for 'stats_notification'.
 
    .PARAMETER Percentage
        Specifies the new usage threshold at which the alert will be sent. Required for 'usage_alert'.
 
    .PARAMETER OnBehalfOf
        Specifies an On Behalf Of header to allow you to make API calls from a parent account on behalf of the parent's Subusers or customer accounts.
 
    .EXAMPLE
        PS C:\> Set-SGAlert -AlertId 123 -EmailTo 'test@example.com' -Percentage 90
 
        This command updates the alert with the ID 123 on SendGrid to be sent to 'test@example.com' when the usage threshold reaches 90%.
 
    .EXAMPLE
        PS C:\> Set-SGAlert -AlertId 123 -EmailTo 'test@example.com' -Frequency 'daily' -OnBehalfOf 'Subuser'
 
        This command updates the alert with the ID 123 on SendGrid to be sent to 'test@example.com' daily on behalf of the Subuser 'Subuser'.
    #>

    [CmdletBinding(
        SupportsShouldProcess
    )]
    param (
        # Specifies the ID of the alert to update.
        [Parameter(
            Mandatory,
            ValueFromPipeline,
            ValueFromPipelineByPropertyName,
            Position = 0
        )]
        [Alias('Id')]
        [int]$AlertId,

        # Specifies the new email address the alert will be sent to.
        [Parameter(
            Position = 1
        )]
        [MailAddress]$EmailTo,

        # Specifies the new frequency at which the alert will be sent. Required for 'stats_notification'.
        [Parameter(
            Position = 2
        )]
        [ValidateSet('Daily', 'Weekly', 'Monthly')]
        [string]$Frequency,

        # Specifies the new usage threshold at which the alert will be sent. Required for 'usage_alert'.
        [Parameter()]
        [ValidateRange(1, 100)]
        [int]$Percentage,

        # Specifies an On Behalf Of header to allow you to make API calls from a parent account on behalf of the parent's Subusers or customer accounts.
        [Parameter()]
        [string]$OnBehalfOf
    )
    process {
        if ($PSCmdlet.ShouldProcess(('Update alert with ID {0}.' -f $AlertId))) {
            try {
                $Verify = Get-SGAlert -AlertId $AlertId -OnBehalfOf $OnBehalfOf
            }
            catch {
                Write-Error ('Failed to retrieve SendGrid alert. {0}' -f $_.Exception.Message) -ErrorAction Stop
            }

            $ContentBody = @{}

            switch ($Verify.Type) {
                'usage_alert' {
                    if ($PSBoundParameters.Percentage) {
                        $ContentBody.Add('percentage', $Percentage)
                    }
                    elseif ($PSBoundParameters.Frequency) {
                        Write-Verbose ('The alert with ID {0} is a usage_alert alert and does not require a frequency to be updated. Will ignore' -f $AlertId)
                    }
                    elseif ($PSBoundParameters.EmailTo) {
                        # Fail safe
                    }
                    else {
                        Write-Error ('The alert with ID {0} is a usage_alert alert and requires a percentage to be updated.' -f $AlertId) -ErrorAction Stop
                    }
                    break;
                }
                'stats_notification' {
                    if ($PSBoundParameters.Percentage) {
                        Write-Verbose ('The alert with ID {0} is a stats_notification alert and does not require a percentage to be updated. Will be ignored' -f $AlertId)
                    }
                    elseif ($PSBoundParameters.Frequency) {
                        $ContentBody.Add('frequency', $Frequency.ToLower())
                    }
                    elseif ($PSBoundParameters.EmailTo) {
                        # Fail safe
                    }
                    else {
                        Write-Error ('The alert with ID {0} is a stats_notification alert and requires a frequency to be updated.' -f $AlertId) -ErrorAction Stop
                    }
                    break;
                }
                Default {
                    Write-Error ('The alert with ID {0} is an unknown type. Create an issue on GitHub.' -f $AlertId) -ErrorAction Stop
                    break;
                }
            }

            if ($PSBoundParameters.EmailTo) {
                $ContentBody.Add('email_to', $EmailTo.Address)
            }

            $InvokeSplat = @{
                Method        = 'Patch'
                Namespace     = "alerts/$AlertId"
                ErrorAction   = 'Stop'
                CallingCmdlet = $PSCmdlet.MyInvocation.MyCommand.Name
            }
            if ($PSBoundParameters.OnBehalfOf) {
                $InvokeSplat.Add('OnBehalfOf', $OnBehalfOf)
            }

            $InvokeSplat['ContentBody'] = $ContentBody
        
            try {
                Invoke-SendGrid @InvokeSplat
            }
            catch {
                Write-Error ('Failed to update SendGrid alert. {0}' -f $_.Exception.Message) -ErrorAction Stop
            }
        }
    }
}
#EndRegion '.\Public\Set-SGAlert.ps1' 143
#Region '.\Public\Set-SGApiKey.ps1' 0
function Set-SGApiKey {
    <#
    .SYNOPSIS
        Update the name and scopes of a given API key.
 
    .DESCRIPTION
        Set-SGApiKey updates the name and scopes of a given API key.
 
    .PARAMETER ApiKeyID
        Specifies the ID of the API Key to be updated.
 
    .PARAMETER Scopes
        Specifies the new scopes of the API Key.
 
    .PARAMETER NewName
        Specifies the new name of the API Key. This parameter is not mandatory.
 
    .EXAMPLE
        PS C:\> Set-SGApiKey -ApiKeyID 'R2l2W3kZSQukQv4lCkG3zW' -Scopes 'access_settings.activity.read', 'alerts.create', 'alerts.read'
 
        This command updates the scopes of the API Key with the specified ID within the current SendGrid instance.
 
    .EXAMPLE
        PS C:\> Set-SGApiKey -ApiKeyID 'R2l2W3kZSQukQv4lCkG3zW' -Scopes 'access_settings.activity.read', 'alerts.create', 'alerts.read' -NewName 'MyUpdatedKey'
 
        This command updates both the name and scopes of the API Key with the specified ID within the current SendGrid instance.
    #>

    [CmdletBinding(
        SupportsShouldProcess
    )]
    param (
        # Specifies the UniqueId of the API Key to be updated.
        [Parameter(
            Mandatory,
            ValueFromPipeline,
            ValueFromPipelineByPropertyName,
            DontShow,
            ParameterSetName = 'InputObject'
        )]
        [Object[]]$InputObject,
        
        # Specifies the UniqueId of the API Key to be updated.
        [Parameter(
            Mandatory,
            Position = 0,
            ParameterSetName = 'UniqueId'
        )]
        [Alias('Id')]
        [string[]]$UniqueId,

        # Specifies the new scopes of the API Key.
        [Parameter(
            Position = 1
        )]
        [ValidateSet([SendGridScopes])]
        [string[]]$Scopes,

        # Specifies the new name of the API Key. This parameter is not mandatory.
        [Parameter()]
        [string]$NewName,

        # Specifies a On Behalf Of header to allow you to make API calls from a parent account on behalf of the parent's Subusers or customer accounts.
        [Parameter()]
        [string]$OnBehalfOf
    )
    process {
        if ($PSCmdlet.ParameterSetName -eq 'InputObject') {
            $UniqueId = @()
            foreach ($Object in $InputObject) {
                switch ($Object) {
                    { $_ -is [string] } { $UniqueId += $_; break }
                    { $_ -is [int] } { $UniqueId += $_; break }
                    { $_ -is [System.Management.Automation.PSCustomObject] } { $UniqueId += $_.Id; break }
                    default { Write-Error ('Failed to convert InputObject to Id.') -ErrorAction Stop }
                }
            }            
        }
        if ($UniqueId.Count -gt 1 -and $PSBoundParameters.ContainsKey('NewName')) {
            Write-Warning ('Only one API Key can renamed per Set-SGApiKey. Scopes will be updated for {0} API Keys.' -f ($UniqueId.Count - 1))
            $PSBoundParameters.Remove('NewName')
        }
        foreach ($Id in $UniqueId) {
            $InvokeSplat = @{
                Method        = 'Put'
                Namespace     = "api_keys/$Id"
                ErrorAction   = 'Stop'
                CallingCmdlet = $PSCmdlet.MyInvocation.MyCommand.Name
            }
            $GetSplat = @{
                ApiKeyID    = $Id
                ErrorAction = 'Stop'
            }

            if ($PSBoundParameters.OnBehalfOf) {
                $InvokeSplat.Add('OnBehalfOf', $OnBehalfOf)
                $GetSplat.Add('OnBehalfOf', $OnBehalfOf)
            }
            $CurrentKey = Get-SGApiKey @GetSplat
            if ($PSCmdlet.ShouldProcess($Id)) {
                Write-Verbose -Message ('Updating key {0}' -f $SGApiKey.Name)

                if ($PSBoundParameters.ContainsKey('Scopes')) {
                    [hashtable]$ContentBody = @{
                        scopes = $Scopes
                    }
                }
                else {
                    [hashtable]$ContentBody = @{
                        scopes = $CurrentKey.Scopes
                    }
                }
                
                if ($PSBoundParameters.ContainsKey('NewName')) {
                    $ContentBody.Add('name', $NewName)
                    
                }
                else {
                    $ContentBody.Add('name', $CurrentKey.Name)
                }
                $InvokeSplat.Add('ContentBody', $ContentBody)
                try {
                    Invoke-SendGrid @InvokeSplat
                }
                catch {
                    Write-Error ('Failed to update SendGrid API Key. {0}' -f $_.Exception.Message) -ErrorAction Stop
                }
            }
        }
    }
}
#EndRegion '.\Public\Set-SGApiKey.ps1' 131
#Region '.\Public\Set-SGAuthenticatedDomain.ps1' 0
function Set-SGAuthenticatedDomain {
    <#
    .SYNOPSIS
        Sets properties for an Authenticated Domain within the current SendGrid instance.
    .DESCRIPTION
        Set-SGAuthenticatedDomain sets properties for an authenticated domain in the current SendGrid instance. This can include setting the domain as the default sending domain or setting a custom SPF record. You must provide the unique identifier of the domain to modify.
    .PARAMETER UniqueId
        Specifies the unique identifier for the authenticated domain to modify.
    .PARAMETER SetDefault
        Specifies whether to set the authenticated domain as the default sending domain.
    .PARAMETER SetCustomSPF
        Specifies whether to set a custom SPF record for the authenticated domain.
    .EXAMPLE
        PS C:\> Set-SGAuthenticatedDomain -UniqueId '1234567' -SetDefault
        Sets the authenticated domain with the unique identifier '1234567' as the default sending domain.
    .EXAMPLE
        PS C:\> Set-SGAuthenticatedDomain -UniqueId '1234567' -SetCustomSPF
        Sets a custom SPF record for the authenticated domain with the unique identifier '1234567'.
    .NOTES
        To use this function, you must be connected to a SendGrid instance. Use the Connect-SendGrid function to establish a connection.
    #>

    [CmdletBinding(
        SupportsShouldProcess
    )]
    param (
        # Specifies the unique identifier for the authenticated domain to modify.
        [Parameter(
            Mandatory,
            ValueFromPipeline,
            ValueFromPipelineByPropertyName,
            DontShow,
            ParameterSetName = 'InputObject'
        )]
        [Object[]]$InputObject,
        
        # Specifies the unique identifier for the authenticated domain to modify.
        [Parameter(
            Mandatory,
            Position = 0,
            ParameterSetName = 'UniqueId'
        )]
        [Alias('Id')]
        [string[]]$UniqueId,
        
        # Specifies whether to set the authenticated domain as the default sending domain.
        [Parameter()]
        [switch]$SetDefault,

        # Specifies whether to set a custom SPF record for the authenticated domain.
        [Parameter()]
        [switch]$SetCustomSPF,

        # Specifies a On Behalf Of header to allow you to make API calls from a parent account on behalf of the parent's Subusers or customer accounts.
        [Parameter()]
        [string]$OnBehalfOf
    )   
    process {
        if ($PSCmdlet.ParameterSetName -eq 'InputObject') {
            $UniqueId = @()
            foreach ($Object in $InputObject) {
                switch ($Object) {
                    { $_ -is [string] } { $UniqueId += $_; break }
                    { $_ -is [int] } { $UniqueId += $_; break }
                    { $_ -is [System.Management.Automation.PSCustomObject] } { $UniqueId += $_.Id; break }
                    default { Write-Error ('Failed to convert InputObject to Id.') -ErrorAction Stop }
                }
            }            
        }
        foreach ($UniqueId in $Id) { 
            $InvokeSplat = @{
                Method        = 'Patch'
                Namespace     = "whitelabel/domains/$UniqueId"
                ErrorAction   = 'Stop'
                CallingCmdlet = $PSCmdlet.MyInvocation.MyCommand.Name
            }
            $ContentBody = @{}
            if ($SetDefault) {
                $ContentBody.Add('default', $true)
            }
            if ($SetCustomSPF) {
                $ContentBody.Add('custom_spf', $true)
            }
            if ($PSBoundParameters.OnBehalfOf) {
                $InvokeSplat.Add('OnBehalfOf', $OnBehalfOf)
            }
            $InvokeSplat.Add('ContentBody', $ContentBody)
            if ($PSCmdlet.ShouldProcess(('Authenticated Domain {0}' -f $UniqueId))) {
                try {
                    Invoke-SendGrid @InvokeSplat
                }
                catch {
                    Write-Error ('Failed to set properties for SendGrid Authenticated Domain. {0}' -f $_.Exception.Message) -ErrorAction Stop
                }
            }
        }
    }
}
#EndRegion '.\Public\Set-SGAuthenticatedDomain.ps1' 98
#Region '.\Public\Set-SGAuthenticatedDomainToSubUser.ps1' 0
function Set-SGAuthenticatedDomainToSubUser {
    <#
    .SYNOPSIS
        Assign a specified Authenticated Domain to a subuser.
 
    .DESCRIPTION
        Authenticated domains can be associated with (i.e. assigned to) subusers from a parent account.
        This functionality allows subusers to send mail using their parent's domain authentication.
        To associate an authenticated domain with a subuser, the parent account must first authenticate and validate the domain.
        The parent may then associate the authenticated domain via the subuser management tools.
 
    .PARAMETER UniqueId
        Specifies the ID of the authenticated domain to assign to the subuser. This parameter is mandatory.
 
        .PARAMETER UserName
        Specifies username of the subuser to assign the authenticated domain to. This parameter is mandatory.
 
    .EXAMPLE
        PS C:\> Set-SGAuthenticatedDomainToSubUser -UniqueId '1234567' -UserName 'subuser'
 
        This command assigns the authenticated domain with the unique ID '1234567' to the subuser 'subuser'.
 
    .EXAMPLE
        PS C:\> Get-SGAuthenticatedDomain | Where-Object { $_.Domain -eq 'example.com' } | Set-SGAuthenticatedDomainToSubUser -UserName 'subuser'
         
        This command assigns the authenticated domain 'example.com' to the subuser 'subuser' using its unique ID obtained from the Get-SGAuthenticatedDomain cmdlet.
    #>

    [CmdletBinding(
        SupportsShouldProcess
    )]
    param (

        # Specifies the ID of a specific authenticated domain to assign to the subuser.
        [Parameter(
            Mandatory,
            ValueFromPipeline,
            ValueFromPipelineByPropertyName,
            Position = 0
        )]
        [Alias('Id')]
        [string]$UniqueId,

        # Specifies username of the subuser to assign the authenticated domain to.
        [Parameter(
            Mandatory,
            ValueFromPipelineByPropertyName,
            Position = 1
        )]
        [string]$UserName
    )
    process {
        $InvokeSplat = @{
            Method        = 'Post'
            Namespace     = "whitelabel/domains/$UniqueId/subuser"
            ErrorAction   = 'Stop'
            CallingCmdlet = $PSCmdlet.MyInvocation.MyCommand.Name
        }
        $GetSplat = @{
            UniqueId    = $UniqueId
            ErrorAction = 'Stop'
        }
        $SGAuthenticatedDomain = Get-SGAuthenticatedDomain @GetSplat
        if ($PSCmdlet.ShouldProcess(('{0}.{1}' -f $SGAuthenticatedDomain.Subdomain, $SGAuthenticatedDomain.Domain))) {
            try {
                [hashtable]$ContentBody = @{
                    username = $UserName
                }
                $InvokeSplat.Add('ContentBody', $ContentBody)
                Invoke-SendGrid @InvokeSplat
            }
            catch {
                Write-Error ('Failed to assign authenticated domain. {0}' -f $_.Exception.Message) -ErrorAction Stop
            }
        }
    }
}
#EndRegion '.\Public\Set-SGAuthenticatedDomainToSubUser.ps1' 77
#Region '.\Public\Set-SGBouncePurgeSetting.ps1' 0
function Set-SGBouncePurgeSetting {
    <#
    .SYNOPSIS
        Updates the bounce purge mail settings on SendGrid.
    .DESCRIPTION
        Set-SGBouncePurgeSetting updates the bounce purge mail settings on SendGrid.
    .PARAMETER Enabled
        Specifies whether the bounce purge mail setting is enabled.
    .PARAMETER SoftBounces
        The number of days after which SendGrid will purge all contacts from your soft bounces suppression lists.
    .PARAMETER HardBounces
        The number of days after which SendGrid will purge all contacts from your hard bounces suppression lists.
    .PARAMETER OnBehalfOf
        Specifies an On Behalf Of header to allow you to make API calls from a parent account on behalf of the parent's Subusers or customer accounts.
    .EXAMPLE
        PS C:\> Set-SGBouncePurgeSetting -Enabled $true -SoftBounces 5 -HardBounces 10
        This command updates the bounce purge mail settings on SendGrid to enable the setting and set the purge days for soft and hard bounces.
    #>

    [CmdletBinding()]
    param (
        # Specifies whether the bounce purge mail setting is enabled.
        [Parameter()]
        [switch]$Enabled,
        
        # The number of days after which SendGrid will purge all contacts from your soft bounces suppression lists.
        [Parameter()]
        [int]$SoftBounces,

        # The number of days after which SendGrid will purge all contacts from your hard bounces suppression lists.
        [Parameter()]
        [int]$HardBounces,

        # Specifies an On Behalf Of header to allow you to make API calls from a parent account on behalf of the parent's Subusers or customer accounts.
        [Parameter()]
        [string]$OnBehalfOf
    )
    process {
        [hashtable]$ContentBody = @{}
        $InvokeSplat = @{
            Method        = 'Patch'
            Namespace     = 'mail_settings/bounce_purge'
            ErrorAction   = 'Stop'
            CallingCmdlet = $PSCmdlet.MyInvocation.MyCommand.Name
        }
        if ($PSBoundParameters.OnBehalfOf) {
            $InvokeSplat.Add('OnBehalfOf', $OnBehalfOf)
        }
        
        if ($PSBoundParameters.ContainsKey('Enabled')) {
            $ContentBody.Add('enabled', $Enabled.IsPresent)
        }
        if ($PSBoundParameters.ContainsKey('SoftBounces')) {
            $ContentBody.Add('soft_bounces', $SoftBounces)
        }
        if ($PSBoundParameters.ContainsKey('HardBounces')) {
            $ContentBody.Add('hard_bounces', $HardBounces)
        }
        
        $InvokeSplat.Add('ContentBody', $ContentBody)
        
        try {
            Invoke-SendGrid @InvokeSplat
        }
        catch {
            Write-Error ('Failed to update SendGrid bounce purge settings. {0}' -f $_.Exception.Message) -ErrorAction Stop
        }
    }
}
#EndRegion '.\Public\Set-SGBouncePurgeSetting.ps1' 69
#Region '.\Public\Set-SGBrandedDomainLink.ps1' 0
function Set-SGBrandedDomainLink {
    <#
    .SYNOPSIS
        Sets properties for a Branded Domain Link within the current SendGrid instance.
    .DESCRIPTION
        Set-SGBrandedDomainLink sets properties for a branded domain link in the current SendGrid instance. This can include setting the link as the default branded domain link. You must provide the unique identifier of the domain link to modify.
    .PARAMETER UniqueId
        Specifies the unique identifier for the branded domain link to modify.
    .PARAMETER SetDefault
        Specifies whether to set the branded domain link as the default.
    .EXAMPLE
        PS C:\> Set-SGBrandedDomainLink -UniqueId '1234567' -SetDefault
        Sets the branded domain link with the unique identifier '1234567' as the default branded domain link.
    .NOTES
        To use this function, you must be connected to a SendGrid instance. Use the Connect-SendGrid function to establish a connection.
    #>

    [CmdletBinding(
        SupportsShouldProcess
    )]
    param (
        # Specifies the unique identifier for the branded domain link to modify.
        [Parameter(
            Mandatory,
            ValueFromPipeline,
            ValueFromPipelineByPropertyName,
            DontShow,
            ParameterSetName = 'InputObject'
        )]
        [Object[]]$InputObject,
        
        # Specifies the unique identifier for the branded domain link to modify.
        [Parameter(
            Mandatory,
            Position = 0,
            ParameterSetName = 'UniqueId'
        )]
        [Alias('Id')]
        [string[]]$UniqueId,
        
        # Specifies whether to set the branded domain link as the default.
        [Parameter()]
        [switch]$SetDefault,
        
        # Specifies a On Behalf Of header to allow you to make API calls from a parent account on behalf of the parent's Subusers or customer accounts.
        [Parameter()]
        [string]$OnBehalfOf
    )   
    process {
        if ($PSCmdlet.ParameterSetName -eq 'InputObject') {
            $UniqueId = @()
            foreach ($Object in $InputObject) {
                switch ($Object) {
                    { $_ -is [string] } { $UniqueId += $_; break }
                    { $_ -is [int] } { $UniqueId += $_; break }
                    { $_ -is [System.Management.Automation.PSCustomObject] } { $UniqueId += $_.Id; break }
                    default { Write-Error ('Failed to convert InputObject to Id.') -ErrorAction Stop }
                }
            }            
        }
        foreach ($Id in $UniqueId) { 
            $InvokeSplat = @{
                Method        = 'Patch'
                Namespace     = "whitelabel/links/$Id"
                ErrorAction   = 'Stop'
                CallingCmdlet = $PSCmdlet.MyInvocation.MyCommand.Name
            }
            $ContentBody = @{}
            if ($SetDefault) {
                $ContentBody.Add('default', $true)
            }
            if ($PSBoundParameters.OnBehalfOf) {
                $InvokeSplat.Add('OnBehalfOf', $OnBehalfOf)
            }
            $InvokeSplat.Add('ContentBody', $ContentBody)
            if ($PSCmdlet.ShouldProcess(('Branded Domain Link {0}' -f $Id))) {
                    try {
                        Invoke-SendGrid @InvokeSplat
                    }
                    catch {
                        Write-Error ('Failed to set properties for SendGrid Branded Domain Link. {0}' -f $_.Exception.Message) -ErrorAction Stop
                    }
                }
            }
        }
    }
#EndRegion '.\Public\Set-SGBrandedDomainLink.ps1' 86
#Region '.\Public\Set-SGForwardBounceSetting.ps1' 0
function Set-SGForwardBounceSetting {
    <#
    .SYNOPSIS
        Updates the forward bounce mail settings on SendGrid.
    .DESCRIPTION
        Set-SGForwardBounceSetting updates the forward bounce mail settings on SendGrid.
    .EXAMPLE
        PS C:\> Set-SGForwardBounceSetting -Email 'example@example.com' -Enabled $true This command updates the forward bounce mail settings on SendGrid.
    .NOTES
        To use this function, you must be connected to a SendGrid instance. Use the Connect-SendGrid function to establish a connection.
    #>

    [CmdletBinding()]
    param (
        # The email address that you would like your bounce reports forwarded to. If you do not want to forward bounce reports, set this to $null.
        [Parameter()]
        [AllowNull()]
        [MailAddress]$Email,

        # Indicates if the bounce forwarding mail setting is enabled.
        [Parameter()]
        [switch]$Enabled,

        # Specifies an On Behalf Of header to allow you to make API calls from a parent account on behalf of the parent's Subusers or customer accounts.
        [Parameter()]
        [string]$OnBehalfOf

    )
    process {
        $ContentBody = @{}
        $InvokeSplat = @{
            Method        = 'Patch'
            Namespace     = 'mail_settings/forward_bounce'
            ErrorAction   = 'Stop'
            CallingCmdlet = $PSCmdlet.MyInvocation.MyCommand.Name
        }

        if ($PSBoundParameters.OnBehalfOf) {
            $InvokeSplat.Add('OnBehalfOf', $OnBehalfOf)
        }

        if ($PSBoundParameters.ContainsKey('Enabled')) {
            $ContentBody.Add('enabled', $Enabled.IsPresent)
        }

        if ($PSBoundParameters.ContainsKey('Email')) {
            if ($null -eq $Email) {
                $ContentBody.Add('email', '')
            }
            else {
                $ContentBody.Add('email', $Email.Address)
            }
        }

        $InvokeSplat.Add('ContentBody', $ContentBody)
        try {
            Invoke-SendGrid @InvokeSplat
        }
        catch {
            Write-Error ('Failed to update SendGrid forward bounce settings. {0}' -f $_.Exception.Message) -ErrorAction Stop
        }
    }
}
#EndRegion '.\Public\Set-SGForwardBounceSetting.ps1' 63
#Region '.\Public\Set-SGForwardSpamSetting.ps1' 0
function Set-SGForwardSpamSetting {
    <#
    .SYNOPSIS
        Updates the forward spam mail settings on SendGrid.
    .DESCRIPTION
        Set-SGForwardSpamSetting updates the forward spam mail settings on SendGrid.
    .EXAMPLE
        PS C:\> Set-SGForwardSpamSetting -Email 'example@example.com' -Enabled $true
        This command updates the forward spam mail settings on SendGrid.
    .NOTES
        To use this function, you must be connected to a SendGrid instance. Use the Connect-SendGrid function to establish a connection.
    #>

    [CmdletBinding()]
    param (
        # The email address that you would like your spam reports forwarded to. If you do not want to forward spam reports, set this to $null.
        [Parameter()]
        [AllowNull()]
        [MailAddress[]]$Email,

        # Indicates if the spam forwarding mail setting is enabled.
        [Parameter()]
        [switch]$Enabled,

        # Specifies an On Behalf Of header to allow you to make API calls from a parent account on behalf of the parent's Subusers or customer accounts.
        [Parameter()]
        [string]$OnBehalfOf
    )
    process {
        $ContentBody = @{}
        $InvokeSplat = @{
            Method        = 'Patch'
            Namespace     = 'mail_settings/forward_spam'
            ErrorAction   = 'Stop'
            CallingCmdlet = $PSCmdlet.MyInvocation.MyCommand.Name
        }

        if ($PSBoundParameters.OnBehalfOf) {
            $InvokeSplat.Add('OnBehalfOf', $OnBehalfOf)
        }
        
        if ($PSBoundParameters.ContainsKey('Enabled')) {
            $ContentBody.Add('enabled', $Enabled.IsPresent)
        }

        if ($PSBoundParameters.ContainsKey('Email')) {
            if ($null -eq $Email) {
                $ContentBody.Add('email', '')
            }
            else {
                $ContentBody.Add('email', (($Email | ForEach-Object { $_.Address }) -join ', '))
            }
        }

        $InvokeSplat.Add('ContentBody', $ContentBody)
        $InvokeSplat
        try {
            Invoke-SendGrid @InvokeSplat
        }
        catch {
            Write-Error ('Failed to update SendGrid forward spam settings. {0}' -f $_.Exception.Message) -ErrorAction Stop
        }
    }
}
#EndRegion '.\Public\Set-SGForwardSpamSetting.ps1' 64
#Region '.\Public\Set-SGSuppressionGroup.ps1' 0
function Set-SGSuppressionGroup {
    <#
    .SYNOPSIS
        Updates a suppression group.
 
    .DESCRIPTION
        The Set-SGSuppressionGroup function updates a suppression group in SendGrid.
         
    .PARAMETER GroupId
        Specifies the ID of the suppression group.
 
    .PARAMETER Name
        Specifies the name of the suppression group.
 
    .PARAMETER Description
        Specifies the description of the suppression group.
 
    .PARAMETER IsDefault
        Specifies whether the suppression group is the default group.
 
    .PARAMETER OnBehalfOf
        Specifies a On Behalf Of header to allow you to make API calls from a parent account on behalf of the parent's Subusers or customer accounts.
 
    .EXAMPLE
        PS C:\> Set-SGSuppressionGroup -GroupId 123 -Name 'My Group' -Description 'This is my group.' -IsDefault $false
        This command updates the suppression group with the ID 123.
    #>

    [CmdletBinding(
        SupportsShouldProcess = $true
    )]
    param (
        # Specifies the ID of the suppression group.
        [Parameter(
            Mandatory,
            ValueFromPipeline,
            ValueFromPipelineByPropertyName,
            DontShow,
            ParameterSetName = 'InputObject'
        )]
        [Object[]]$InputObject,
        
        # Specifies the ID of the suppression group.
        [Parameter(
            Mandatory,
            Position = 0,
            ParameterSetName = 'UniqueId'
        )]
        [Alias('Id')]
        [int]$UniqueId,

        # Specifies the name of the suppression group.
        [Parameter(
            Position = 1
        )]
        [string]$Name,

        # Specifies the description of the suppression group.
        [Parameter(
            Position = 2
        )]
        [string]$Description,

        # Specifies whether the suppression group is the default group.
        [Parameter()]
        [switch]$IsDefault,

        # Specifies a On Behalf Of header to allow you to make API calls from a parent account on behalf of the parent's Subusers or customer accounts.
        [Parameter()]
        [string]$OnBehalfOf
    )
    process {
        if ($PSCmdlet.ParameterSetName -eq 'InputObject') {
            $UniqueId = @()
            foreach ($Object in $InputObject) {
                switch ($Object) {
                    { $_ -is [string] } { $UniqueId += $_; break }
                    { $_ -is [int] } { $UniqueId += $_; break }
                    { $_ -is [System.Management.Automation.PSCustomObject] } { $UniqueId += $_.Id; break }
                    default { Write-Error ('Failed to convert InputObject to Id.') -ErrorAction Stop }
                }
            }            
        }
        $InvokeSplat = @{
            Method        = 'Patch'
            Namespace     = "asm/groups/$UniqueId"
            ErrorAction   = 'Stop'
            CallingCmdlet = $PSCmdlet.MyInvocation.MyCommand.Name
        }
        if ($PSBoundParameters.ContainsKey('OnBehalfOf')) {
            $InvokeSplat.OnBehalfOf = $OnBehalfOf
        }
        $InvokeSplat['ContentBody'] = @{
            'name' = $Name
            'description' = $Description
            'is_default' = $IsDefault.IsPresent
        }
        if ($PSCmdlet.ShouldProcess(('Update suppression group with ID {0}.' -f $UniqueId))) {
            try {
                Invoke-SendGrid @InvokeSplat
            }
            catch {
                Write-Error ('Failed to update suppression group. {0}' -f $_.Exception.Message) -ErrorAction Stop
            }
        }
    }
}
#EndRegion '.\Public\Set-SGSuppressionGroup.ps1' 107