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))) } 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() } [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] 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' 65 #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(-12) 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(-12) 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) 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) { $Body = $ContentBody | ConvertTo-Json -Depth 5 -ErrorAction Stop $SessionLifeTime = (Get-Date).AddHours(-12) 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) 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(-12) 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) 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(-12) 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) throw ('Unable to query Sendgrid: {0}' -f $_.Exception.Message) } } } [string]ToString() { return $this._Connected } } #EndRegion '.\Classes\SGSession.ps1' 323 #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 )] [ValidateNotNullOrEmpty()] [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 ) begin { # Function to get unique properties of an object. function Get-UniqueProperties { param ( [Parameter( Mandatory )] [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 { Write-Verbose 'Attempting to invoke query' # 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 'Result' property. if ($Query -is [System.Management.Automation.PSObject[]] -and $Properties -eq 'Result' -and $Properties.Count -eq 1) { $Query = $Query.result $Properties = Get-UniqueProperties -InputObject $Query } # Process each object in the query. foreach ($Object in $Query) { # Create a new custom object. [PSCustomObject]$PSObject = [PSCustomObject]::new() # 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 -replace '[\s_-]+')) -Value $Object.$Property.$InlineProperty } } # Switch based on the property type. switch ($Object.$Property) { { $_ -is [int64] -and $Property -match 'valid' } { $PSObject | Add-Member -MemberType NoteProperty -Name ($Property -replace '[\s_-]+') -Value ((Get-Date -Date '01-01-1970') + ([System.TimeSpan]::FromSeconds(($_)))) break } Default { $PSObject | Add-Member -MemberType NoteProperty -Name ($Property -replace '[\s_-]+') -Value $Object.$Property -Force break } } } if ($PSObject | Get-Member -Name 'Errors' -MemberType 'NoteProperty') { throw $PSObject.Errors.Message } else { $PSObject } } } } } #EndRegion '.\Private\Invoke-SendGrid.ps1' 154 #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\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, ValueFromPipelineByPropertyName, ValueFromPipeline )] [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 { foreach ($Id in $UniqueId) { $InvokeSplat = @{ Method = 'Post' Namespace = "whitelabel/domains/$Id/validate" ErrorAction = 'Stop' } $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' 82 #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, ValueFromPipelineByPropertyName, ValueFromPipeline )] [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 { foreach ($Id in $UniqueId) { $InvokeSplat = @{ Method = 'Post' Namespace = "whitelabel/links/$Id/validate" ErrorAction = 'Stop' } $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' 76 #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 )] param ( # Specifies the username for the Subuser to create. [Parameter( Mandatory, ValueFromPipelineByPropertyName )] [string]$Username ) process { $InvokeSplat = @{ Method = 'Patch' Namespace = "subusers/$Username" ErrorAction = 'Stop' ContentBody = @{ disabled = $true } } if ($PSCmdlet.ShouldProcess($Username)) { try { Invoke-SendGrid @InvokeSplat } catch { Write-Error ('Failed to enable SendGrid Subuser. {0}' -f $_.Exception.Message) -ErrorAction Stop } } } } #EndRegion '.\Public\Disable-SGSubuser.ps1' 55 #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 )] [string]$Username ) process { $InvokeSplat = @{ Method = 'Patch' Namespace = "subusers/$Username" ErrorAction = 'Stop' ContentBody = @{ disabled = $false } } 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' 54 #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 )] [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' } 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' 86 #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-SMSGAuthenticatedDomain 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-SMSGAuthenticatedDomain -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-SMSGAuthenticatedDomain -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 )] [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 { $InvokeSplat = @{ Method = 'Get' Namespace = 'whitelabel/domains' ErrorAction = 'Stop' } if ($PSBoundParameters.OnBehalfOf) { $InvokeSplat.Add('OnBehalfOf', $OnBehalfOf) } if ($PSBoundParameters.UniqueId) { foreach ($Id in $UniqueId) { if ($PSCmdlet.ShouldProcess(('{0}' -f $Id))) { $InvokeSplat['Namespace'] = "whitelabel/domains/$Id" try { $InvokeResult = Invoke-SendGrid @InvokeSplat if ($InvokeResult | Get-Member -Name 'Errors' -MemberType 'NoteProperty') { throw $InvokeResult.Errors.Message } else { $InvokeResult } } 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 SendGrid Authenticated Domain. {0}' -f $_.Exception.Message) -ErrorAction Stop } } } } } #EndRegion '.\Public\Get-SGAuthenticatedDomain.ps1' 138 #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 )] [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 { $InvokeSplat = @{ Method = 'Get' Namespace = 'whitelabel/links' ErrorAction = 'Stop' } if ($PSBoundParameters.OnBehalfOf) { $InvokeSplat.Add('OnBehalfOf', $OnBehalfOf) } if ($PSBoundParameters.UniqueId) { foreach ($Id in $UniqueId) { if ($PSCmdlet.ShouldProcess(('{0}' -f $Id))) { $InvokeSplat['Namespace'] = "whitelabel/links/$Id" try { $InvokeResult = Invoke-SendGrid @InvokeSplat if ($InvokeResult | Get-Member -Name 'Errors' -MemberType 'NoteProperty') { throw $InvokeResult.Errors.Message } else { $InvokeResult } } 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 SendGrid SendGrid Branded Domain Link. {0}' -f $_.Exception.Message) -ErrorAction Stop } } } } } #EndRegion '.\Public\Get-SGBrandedDomainLink.ps1' 131 #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' } try { Invoke-SendGrid @InvokeSplat } catch { Write-Error ('Failed to retrieve SendGrid IPs. {0}' -f $_.Exception.Message) -ErrorAction Stop } } } #EndRegion '.\Public\Get-SGIPAddress.ps1' 36 #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' } 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' 36 #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 retriev 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 )] [string]$Username, # Specifies the number of results you would like to get in each request. [Parameter()] [int]$Limit, [Parameter()] [int]$Offset ) process { $InvokeSplat = @{ Method = 'Get' Namespace = 'subusers' ErrorAction = 'Stop' } #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' 90 #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 )] [Parameter( ParameterSetName = 'FullAccess', Mandatory )] [string]$Name, [Parameter( ParameterSetName = 'Scopes' )] [ValidateSet([SendGridScopes])] [string[]]$Scopes, [Parameter( ParameterSetName = 'FullAccess', Mandatory )] [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' } 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 { $InvokeResult = Invoke-SendGrid @InvokeSplat if ($InvokeResult | Get-Member -Name 'Errors' -MemberType 'NoteProperty') { throw $InvokeResult.Errors.Message } else { $InvokeResult } } 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 not recommended to provide a full domain including a subdomain, for instance email.example.com. .PARAMETER Subdomain Specifies a subdomain to be used, in most cases it's "email". .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. Defaults to 'sg'. .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. .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 not recommended to provide a full domain including a subdomain, for instance email.example.com. [Parameter(Mandatory)] [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 a subdomain to be used, in most cases it's "email". [Parameter()] [string]$Subdomain, # Specifies a subuser to be used, this is optional. [Parameter()] [string]$SubUser, # 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()] [switch]$DisableAutomaticSecurity, # Add a custom DKIM selector. Accepts three letters or numbers. Defaults to 'sg'. [Parameter()] [ValidatePattern('^[a-zA-Z\d]{3}$')] $CustomDkimSelector = 'sg', # 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, # Specifies if the current domain (parameter Domain) should be created despite it contains a subdomain (email.example.com). [Parameter()] [switch]$Force ) DynamicParam { 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 = 4 # 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 = [System.Management.Automation.RuntimeDefinedParameterDictionary]::new() $ParamDictionary.Add('CustomSPF', $CustomSPFParam) # Return the dictionary return $ParamDictionary } } begin { [hashtable]$ContentBody = [hashtable]::new() $ContentBody.Add('domain', $Domain) if ($Domain -match '.*\..*\..*' -and -not $PSBoundParameters.ContainsKey('Subdomain')) { Write-Verbose -Message ("Sendgrid will automatically generate a custom subdomain for you. Example:em1234.$Subdomain.$Domain") -Verbose $ProcessMessage = $Domain } elseif ($Domain -match '.*\..*\..*' -and $PSBoundParameters.ContainsKey('Subdomain') -and -not $Force.IsPresent) { Write-Warning -Message "It's not recommended to use a double custom subdomain. If you know what you are doing, re-run with -Force. Terminating function..." break } elseif ($Domain -match '.*\..*\..*' -and $PSBoundParameters.ContainsKey('Subdomain') -and $Force.IsPresent) { Write-Verbose -Message "Running with force using double subdomain. Sendgrid will automatically generate a subdomain for you. Example:em1234.$Subdomain.$Domain" -Verbose $ProcessMessage = "$Subdomain.$Domain" } else { Write-Verbose -Message ("Sendgrid will automatically generate a custom subdomain for you. Example:em1234.$Subdomain.$Domain") -Verbose $ContentBody.Add('subdomain', $Subdomain) $ProcessMessage = "$Domain" } $ContentBody.Add('custom_dkim_selector', $CustomDkimSelector) $ContentBody.Add('default', $false) 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) } else { $ContentBody.Add('custom_spf', $false) } $InvokeSplat = @{ Method = 'Post' Namespace = 'whitelabel/domains' ErrorAction = 'Stop' } if ($PSBoundParameters.OnBehalfOf) { $InvokeSplat.Add('OnBehalfOf', $OnBehalfOf) } $InvokeSplat.Add('ContentBody', $ContentBody) } process { if ($PSCmdlet.ShouldProcess($ProcessMessage)) { try { Invoke-SendGrid @InvokeSplat } catch { Write-Error ('Failed to add SendGrid Authenticated Domain. {0}' -f $_.Exception.Message) -ErrorAction Stop } } } } #EndRegion '.\Public\New-SGAuthenticatedDomain.ps1' 173 #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 Subdomain Specifies a subdomain to be used, in most cases it's "link". .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)] [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 a subdomain to be used, in most cases it's "link". [Parameter()] [string]$Subdomain = 'link', # 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, # Specifies if the current domain (parameter Domain) should be created despite it contains a subdomain (email.example.com). [Parameter()] [switch]$Force ) begin { [hashtable]$ContentBody = [hashtable]::new() $ContentBody.Add('domain', $Domain) if ($Domain -match '.*\..*\..*' -and -not $Force.IsPresent) { Write-Warning -Message "It's not recommended to use a double custom subdomain. Sendgrid will automatically generate a subdomain for you. If you know what you are doing, re-run with -Force. Terminating function..." break } elseif ($Force.IsPresent) { Write-Verbose -Message ('Sendgrid will automatically generate a custom subdomain for you.') -Verbose $ProcessMessage = $Domain } else { $ContentBody.Add('subdomain', $Subdomain) $ProcessMessage = "$Subdomain.$Domain" } $ContentBody.Add('default', $false) } process { $InvokeSplat = @{ Method = 'Post' Namespace = 'whitelabel/links' ErrorAction = 'Stop' } if ($PSBoundParameters.OnBehalfOf) { $InvokeSplat.Add('OnBehalfOf', $OnBehalfOf) } $InvokeSplat.Add('ContentBody', $ContentBody) if ($PSCmdlet.ShouldProcess($ProcessMessage)) { try { Invoke-SendGrid @InvokeSplat } catch { Write-Error ('Failed to create SendGrid Branded Domain Link. {0}' -f $_.Exception.Message) -ErrorAction Stop } } } } #EndRegion '.\Public\New-SGBrandedDomainLink.ps1' 92 #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 )] [string]$Username, # Specifies the email address to contact this subuser. [Parameter( Mandatory, ValueFromPipelineByPropertyName )] [MailAddress]$Email, # Specifies the password for the Subuser to create. [Parameter( Mandatory, ValueFromPipelineByPropertyName )] [SecureString]$Password, # Specifies the IP addresses that you would like to allow this Subuser to access. [Parameter( Mandatory, ValueFromPipelineByPropertyName )] [IPAddress[]]$Ips ) begin { [hashtable]$ContentBody = @{ username = $Username email = $Email password = (ConvertFrom-SecureString -SecureString $Password -AsPlainText) ips = @($Ips) } } process { $InvokeSplat = @{ Method = 'Post' Namespace = 'subusers' ErrorAction = 'Stop' } $InvokeSplat.Add('ContentBody', $ContentBody) if ($PSCmdlet.ShouldProcess($Username)) { try { #Invoke-SendGrid @InvokeSplat $InvokeSplat } catch { Write-Error ('Failed to create SendGrid Subuser. {0}' -f $_.Exception.Message) -ErrorAction Stop } } } } #{ 'ips':["167.89.80.214"], 'username':"kalletest_omnicit", 'email':"philip@gonjer.com", 'password':"Gonjer.com123!"#","passwordConfirm":"Gonjer.com123!\"#" } #EndRegion '.\Public\New-SGSubuser.ps1' 94 #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)] param ( # Specifies the ID of the API Key to be deleted. [Parameter( Mandatory = $true, ValueFromPipeline, ValueFromPipelineByPropertyName )] [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 { foreach ($Id in $ApiKeyID) { $InvokeSplat = @{ Method = 'Delete' Namespace = "api_keys/$Id" ErrorAction = 'Stop' } $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 { # Deletes the API Key Invoke-SendGrid @InvokeSplat } catch { Write-Error ('Failed to delete SendGrid API Key. {0}' -f $_.Exception.Message) -ErrorAction Stop } } } } } #EndRegion '.\Public\Remove-SGApiKey.ps1' 61 #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 unique identifier for the authenticated domain to remove. [Parameter( Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName )] [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 { foreach ($Id in $UniqueId) { $InvokeSplat = @{ Method = 'Delete' Namespace = "whitelabel/domains/$Id" ErrorAction = 'Stop' } $GetSplat = @{ UniqueId = $Id ErrorAction = 'Stop' } if ($PSBoundParameters.OnBehalfOf) { $InvokeSplat.Add('OnBehalfOf', $OnBehalfOf) $GetSplat.Add('OnBehalfOf', $OnBehalfOf) } $SGAuthenticatedDomain = Get-SGAuthenticatedDomain @GetSplat Write-Verbose -Message ("Don't forget to remove DNS records:") -Verbose $SGAuthenticatedDomain if ($PSCmdlet.ShouldProcess(('{0}.{1}' -f $SGAuthenticatedDomain.Subdomain, $SGAuthenticatedDomain.Domain))) { try { Invoke-SendGrid @InvokeSplat } catch { Write-Error ('Failed to remove SendGrid Authenticated Domain. {0}' -f $_.Exception.Message) -ErrorAction Stop } } } } } #EndRegion '.\Public\Remove-SGAuthenticatedDomain.ps1' 76 #Region '.\Public\Remove-SMSGBrandedDomainLink.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 )] [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 { foreach ($Id in $UniqueId) { $InvokeSplat = @{ Method = 'Delete' Namespace = "whitelabel/links/$Id" ErrorAction = 'Stop' } $GetSplat = @{ UniqueId = $Id ErrorAction = 'Stop' } if ($PSBoundParameters.OnBehalfOf) { $InvokeSplat.Add('OnBehalfOf', $OnBehalfOf) $GetSplat.Add('OnBehalfOf', $OnBehalfOf) } $SGBrandedDomainLink = Get-SGBrandedDomainLink @GetSplat 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-SMSGBrandedDomainLink.ps1' 74 #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' } [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' 351 #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 ID of the API Key to be updated. [Parameter( Mandatory = $true )] [string[]]$ApiKeyID, # Specifies the new scopes of the API Key. [Parameter()] [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 ($ApiKeyID.Count -gt 1) { Write-Warning ('Only one API Key can be updated at a time. Only scopes will be updated for {0} API Keys.' -f ($ApiKeyID.Count - 1)) $PSBoundParameters.Remove('NewName') } foreach ($Id in $ApiKeyID) { $InvokeSplat = @{ Method = 'Put' Namespace = "api_keys/$Id" ErrorAction = 'Stop' } $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' 105 #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 UnqieId 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 API Key to retrieve. If this parameter is not provided, all API Keys are retrieved. [Parameter( Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName )] [string]$UniqueId, # Specifies username of the subuser to assign the authenticated domain to. [Parameter( Mandatory )] [string]$UserName ) process { $InvokeSplat = @{ Method = 'Post' Namespace = "whitelabel/domains/$UniqueId/subuser" ErrorAction = 'Stop' } $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) $InvokeResult = Invoke-SendGrid @InvokeSplat if ($InvokeResult | Get-Member -Name 'Errors' -MemberType 'NoteProperty') { throw $InvokeResult.Errors.Message } else { $InvokeResult } } catch { Write-Error ('Failed to assign authenticated domain. {0}' -f $_.Exception.Message) -ErrorAction Stop } } } } #EndRegion '.\Public\Set-SGAuthenticatedDomainToSubUser.ps1' 79 |