GOV.UK.Notify.psm1
|
<# GOV.UK.Notify root module. GENERATED FILE - DO NOT EDIT. Compiled from the per-function source files under src/GOV.UK.Notify/Private and src/GOV.UK.Notify/Public by build.ps1. Edit those files, then re-run: pwsh -File ./build.ps1 -Task Build #> # -- Module-scoped session context. Populated by Connect-GovUKNotify and read by the API helpers. $script:GovUKNotifyContext = $null #region src/GOV.UK.Notify/Private/ConvertTo-GovUKNotifyBase64Url.ps1 function ConvertTo-GovUKNotifyBase64Url { <# .SYNOPSIS Encodes a byte array as a base64url string (RFC 7515) with padding removed. .DESCRIPTION Internal helper used when building JSON Web Tokens. Converts standard base64 to the URL-safe alphabet ('+' -> '-', '/' -> '_') and strips '=' padding. .PARAMETER Bytes The bytes to encode. .OUTPUTS System.String #> [CmdletBinding()] [OutputType([string])] param( [Parameter(Mandatory = $true)] [byte[]]$Bytes ) return [Convert]::ToBase64String($Bytes).TrimEnd('=').Replace('+', '-').Replace('/', '_') } #endregion src/GOV.UK.Notify/Private/ConvertTo-GovUKNotifyBase64Url.ps1 #region src/GOV.UK.Notify/Private/Invoke-GovUKNotifyApi.ps1 function Invoke-GovUKNotifyApi { <# .SYNOPSIS Sends an authenticated request to the GOV.UK Notify REST API. .DESCRIPTION Internal request engine used by every public cmdlet. It resolves the API key and base URL, generates a fresh JWT for each attempt, serialises the request body to JSON, and parses the response. Transient failures (HTTP 429, 500, 502, 503, 504) are retried with exponential backoff, honouring a Retry-After header when present. GOV.UK Notify error responses are parsed and surfaced as a single, descriptive terminating error containing the HTTP status code and the Notify error type. .PARAMETER Method The HTTP method, 'GET' or 'POST'. .PARAMETER Path The request path appended to the base URL, for example '/v2/notifications/email'. .PARAMETER Body An optional hashtable serialised to a JSON request body for POST requests. .PARAMETER ApiKey An explicit API key. If omitted, the connected session context is used. .PARAMETER BaseUrl An explicit base URL. If omitted, the connected session context or the production default is used. .PARAMETER Raw Return the raw response bytes instead of parsed JSON. Used for the letter PDF endpoint. .PARAMETER MaxRetry Maximum number of retries for transient failures. Defaults to 3. .PARAMETER RetryDelaySeconds Base delay, in seconds, used for exponential backoff between retries. Defaults to 1. .OUTPUTS The parsed JSON response object, or System.Byte[] when -Raw is specified. #> [CmdletBinding()] param( [Parameter(Mandatory = $true)] [ValidateSet('GET', 'POST')] [string]$Method, [Parameter(Mandatory = $true)] [string]$Path, [hashtable]$Body, [string]$ApiKey, [string]$BaseUrl, [switch]$Raw, [int]$MaxRetry = 3, [int]$RetryDelaySeconds = 1 ) $Context = Resolve-GovUKNotifyContext -ApiKey $ApiKey -BaseUrl $BaseUrl $Uri = '{0}{1}' -f $Context.BaseUrl, $Path $JsonBody = $null if ($PSBoundParameters.ContainsKey('Body') -and $null -ne $Body) { $JsonBody = $Body | ConvertTo-Json -Depth 10 } $RetryableStatus = @(429, 500, 502, 503, 504) $Attempt = 0 while ($true) { $Attempt++ # -- A fresh token per attempt: GOV.UK Notify tokens expire ~30 seconds after issue. $Token = New-GovUKNotifyJwt -ApiKey $Context.ApiKey $Headers = @{ Authorization = "Bearer $Token" } try { if ($Raw) { $Response = Invoke-WebRequest -Uri $Uri -Method $Method -Headers $Headers -UseBasicParsing -ErrorAction Stop # -- Return the byte array as a single object so the pipeline does not unroll it. return , $Response.RawContentStream.ToArray() } $RequestParams = @{ Uri = $Uri Method = $Method Headers = $Headers ErrorAction = 'Stop' } if ($null -ne $JsonBody) { $RequestParams.Body = $JsonBody $RequestParams.ContentType = 'application/json' } return Invoke-RestMethod @RequestParams } catch { $ErrorRecordItem = $_ $StatusCode = $null $ResponseBody = $null # -- Extract the HTTP status code (the StatusCode enum type is shared across PS editions). if ($ErrorRecordItem.Exception.Response) { try { $StatusCode = [int]$ErrorRecordItem.Exception.Response.StatusCode } catch { $StatusCode = $null } } # -- Extract the response body. PowerShell 7 populates ErrorDetails.Message; Windows # PowerShell 5.1 requires reading the response stream. if ($ErrorRecordItem.ErrorDetails -and $ErrorRecordItem.ErrorDetails.Message) { $ResponseBody = $ErrorRecordItem.ErrorDetails.Message } elseif ($ErrorRecordItem.Exception.Response -and ($ErrorRecordItem.Exception.Response | Get-Member -Name GetResponseStream -ErrorAction SilentlyContinue)) { try { $Stream = $ErrorRecordItem.Exception.Response.GetResponseStream() $Reader = [System.IO.StreamReader]::new($Stream) try { $ResponseBody = $Reader.ReadToEnd() } finally { $Reader.Dispose() } } catch { $ResponseBody = $null } } # -- Parse the Notify error payload (status_code + errors[]) for a friendly message. $ErrorSummary = $null if (-not [string]::IsNullOrWhiteSpace($ResponseBody)) { try { $Parsed = $ResponseBody | ConvertFrom-Json -ErrorAction Stop if ($Parsed.status_code) { $StatusCode = [int]$Parsed.status_code } if ($Parsed.errors) { $ErrorSummary = ($Parsed.errors | ForEach-Object { "$($_.error): $($_.message)" }) -join '; ' } } catch { $ErrorSummary = $ResponseBody } } if ([string]::IsNullOrWhiteSpace($ErrorSummary)) { $ErrorSummary = $ErrorRecordItem.Exception.Message } # -- Retry transient failures with exponential backoff. if ($StatusCode -in $RetryableStatus -and $Attempt -le $MaxRetry) { $Delay = [Math]::Min([Math]::Pow(2, $Attempt - 1) * $RetryDelaySeconds, 30) # -- Honour Retry-After when the server provides it. try { $ResponseHeaders = $ErrorRecordItem.Exception.Response.Headers if ($ResponseHeaders) { if ($ResponseHeaders['Retry-After']) { $Delay = [int]$ResponseHeaders['Retry-After'] } elseif ($ResponseHeaders.RetryAfter -and $ResponseHeaders.RetryAfter.Delta) { $Delay = [int]$ResponseHeaders.RetryAfter.Delta.TotalSeconds } } } catch { Write-Verbose 'Unable to read the Retry-After header; using the computed backoff delay.' } Write-Verbose ("GOV.UK Notify request failed (HTTP {0}). Retry {1}/{2} in {3}s." -f $StatusCode, $Attempt, $MaxRetry, $Delay) Start-Sleep -Seconds $Delay continue } # -- Non-retryable, or retries exhausted: throw a single descriptive terminating error. $StatusText = if ($StatusCode) { " (HTTP $StatusCode)" } else { '' } $Message = "GOV.UK Notify API request '$Method $Path' failed${StatusText}: $ErrorSummary" $Exception = [System.Exception]::new($Message, $ErrorRecordItem.Exception) $NewError = [System.Management.Automation.ErrorRecord]::new( $Exception, 'GovUKNotifyApiError', [System.Management.Automation.ErrorCategory]::InvalidOperation, $Path ) throw $NewError } } } #endregion src/GOV.UK.Notify/Private/Invoke-GovUKNotifyApi.ps1 #region src/GOV.UK.Notify/Private/New-GovUKNotifyJwt.ps1 function New-GovUKNotifyJwt { <# .SYNOPSIS Creates a short-lived JSON Web Token for GOV.UK Notify API authentication. .DESCRIPTION GOV.UK Notify authenticates requests with a JWT (HS256) carried in the Authorization header. The token's 'iss' claim is the service id and it is signed with the secret key, both of which are embedded in the API key using the format '{key_name}-{service_id}-{secret_key}', where service_id and secret_key are each UUIDs. The token's 'iat' (issued at) claim is the current UTC time in epoch seconds. GOV.UK Notify rejects tokens whose 'iat' is more than 30 seconds from its own clock, so a fresh token is generated for every request. This is an internal helper and is not exported by the module. .PARAMETER ApiKey The GOV.UK Notify API key, in the format '{key_name}-{service_id}-{secret_key}'. .OUTPUTS System.String. The encoded JWT. #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '', Justification = 'Generates a token value in memory; it does not change any system state.')] [CmdletBinding()] [OutputType([string])] param( [Parameter(Mandatory = $true)] [string]$ApiKey ) # -- The key name may itself contain hyphens, so parse the two UUIDs from the end of the key. $Parts = $ApiKey -split '-' if ($Parts.Count -lt 11) { throw "Invalid GOV.UK Notify API key format. Expected '{key_name}-{service_id}-{secret_key}', where service_id and secret_key are UUIDs." } $SecretKey = ($Parts[-5..-1]) -join '-' $ServiceId = ($Parts[-10..-6]) -join '-' # -- Build the JWT header and payload. $Header = [ordered]@{ typ = 'JWT'; alg = 'HS256' } | ConvertTo-Json -Compress $Payload = [ordered]@{ iss = $ServiceId iat = [DateTimeOffset]::UtcNow.ToUnixTimeSeconds() } | ConvertTo-Json -Compress $EncodedHeader = ConvertTo-GovUKNotifyBase64Url -Bytes ([System.Text.Encoding]::UTF8.GetBytes($Header)) $EncodedPayload = ConvertTo-GovUKNotifyBase64Url -Bytes ([System.Text.Encoding]::UTF8.GetBytes($Payload)) $SigningInput = "$EncodedHeader.$EncodedPayload" # -- Sign with HMAC-SHA256 using the secret key. $Hmac = [System.Security.Cryptography.HMACSHA256]::new([System.Text.Encoding]::UTF8.GetBytes($SecretKey)) try { $SignatureBytes = $Hmac.ComputeHash([System.Text.Encoding]::UTF8.GetBytes($SigningInput)) } finally { $Hmac.Dispose() } $EncodedSignature = ConvertTo-GovUKNotifyBase64Url -Bytes $SignatureBytes return "$SigningInput.$EncodedSignature" } #endregion src/GOV.UK.Notify/Private/New-GovUKNotifyJwt.ps1 #region src/GOV.UK.Notify/Private/Resolve-GovUKNotifyContext.ps1 function Resolve-GovUKNotifyContext { <# .SYNOPSIS Resolves the API key and base URL to use for a request. .DESCRIPTION Internal helper. An explicitly supplied -ApiKey (and optional -BaseUrl) always takes precedence. Otherwise the values stored by Connect-GovUKNotify in the module session context are used. If neither is available, a terminating error is thrown. .PARAMETER ApiKey An explicit API key that overrides the connected session, if supplied. .PARAMETER BaseUrl An explicit base URL that overrides the connected session, if supplied. .OUTPUTS System.Collections.Hashtable with 'ApiKey' and 'BaseUrl' keys. #> [CmdletBinding()] [OutputType([hashtable])] param( [string]$ApiKey, [string]$BaseUrl ) $DefaultBaseUrl = 'https://api.notifications.service.gov.uk' # -- Resolve the API key: explicit parameter first, then the connected session context. if ([string]::IsNullOrWhiteSpace($ApiKey)) { if ($null -eq $script:GovUKNotifyContext) { throw 'Not connected to GOV.UK Notify. Run Connect-GovUKNotify -ApiKey <key> first, or pass -ApiKey to this command.' } $ApiKey = $script:GovUKNotifyContext.ApiKey } # -- Resolve the base URL: explicit parameter, then session context, then the production default. if ([string]::IsNullOrWhiteSpace($BaseUrl)) { if ($null -ne $script:GovUKNotifyContext -and -not [string]::IsNullOrWhiteSpace($script:GovUKNotifyContext.BaseUrl)) { $BaseUrl = $script:GovUKNotifyContext.BaseUrl } else { $BaseUrl = $DefaultBaseUrl } } return @{ ApiKey = $ApiKey BaseUrl = $BaseUrl.TrimEnd('/') } } #endregion src/GOV.UK.Notify/Private/Resolve-GovUKNotifyContext.ps1 #region src/GOV.UK.Notify/Public/Connect-GovUKNotify.ps1 function Connect-GovUKNotify { <# .SYNOPSIS Stores a GOV.UK Notify API key for the current session. .DESCRIPTION Validates the supplied API key and stores it, together with the base URL, in the module session context. Once connected, the other GOV.UK.Notify cmdlets can be called without passing an API key. The key is held in memory only and is never written to disk. Each command still accepts an explicit -ApiKey, which overrides the connected session. This is useful when you need to work with more than one Notify service in the same session. .PARAMETER ApiKey The GOV.UK Notify API key, in the format '{key_name}-{service_id}-{secret_key}'. Create API keys on the API integration page of the GOV.UK Notify dashboard. .PARAMETER BaseUrl The API base URL. Defaults to the production endpoint 'https://api.notifications.service.gov.uk'. .PARAMETER PassThru Return the resulting (masked) connection context. .EXAMPLE Connect-GovUKNotify -ApiKey $env:GOVUKNOTIFY_API_KEY Connects using an API key held in an environment variable. .EXAMPLE Connect-GovUKNotify -ApiKey $key -PassThru Connects and returns the masked connection context. .OUTPUTS None by default, or a PSCustomObject describing the connection when -PassThru is used. .LINK https://docs.notifications.service.gov.uk/rest-api.html#api-keys #> [CmdletBinding()] [OutputType([pscustomobject])] param( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$ApiKey, [Parameter()] [ValidateNotNullOrEmpty()] [string]$BaseUrl = 'https://api.notifications.service.gov.uk', [switch]$PassThru ) # -- Validate the key shape and extract the service id and key name for display. $Parts = $ApiKey -split '-' if ($Parts.Count -lt 11) { throw "Invalid GOV.UK Notify API key format. Expected '{key_name}-{service_id}-{secret_key}', where service_id and secret_key are UUIDs." } $ServiceId = ($Parts[-10..-6]) -join '-' $KeyName = ($Parts[0..($Parts.Count - 11)]) -join '-' $script:GovUKNotifyContext = @{ ApiKey = $ApiKey BaseUrl = $BaseUrl.TrimEnd('/') ServiceId = $ServiceId KeyName = $KeyName } Write-Verbose ("Connected to GOV.UK Notify service '{0}' ({1}) at {2}." -f $KeyName, $ServiceId, $script:GovUKNotifyContext.BaseUrl) if ($PassThru) { return Get-GovUKNotifyContext } } #endregion src/GOV.UK.Notify/Public/Connect-GovUKNotify.ps1 #region src/GOV.UK.Notify/Public/Disconnect-GovUKNotify.ps1 function Disconnect-GovUKNotify { <# .SYNOPSIS Clears the stored GOV.UK Notify connection for the current session. .DESCRIPTION Removes the API key and base URL stored by Connect-GovUKNotify from the module session context. After disconnecting, cmdlets require an explicit -ApiKey again. .EXAMPLE Disconnect-GovUKNotify .OUTPUTS None. .LINK https://github.com/deanlongstaff/GOV.UK.Notify #> [CmdletBinding(SupportsShouldProcess = $true)] param() if ($null -eq $script:GovUKNotifyContext) { Write-Verbose 'No active GOV.UK Notify connection to disconnect.' return } if ($PSCmdlet.ShouldProcess('GOV.UK Notify session', 'Disconnect')) { $script:GovUKNotifyContext = $null Write-Verbose 'Disconnected from GOV.UK Notify.' } } #endregion src/GOV.UK.Notify/Public/Disconnect-GovUKNotify.ps1 #region src/GOV.UK.Notify/Public/Get-GovUKNotifyContext.ps1 function Get-GovUKNotifyContext { <# .SYNOPSIS Returns the current GOV.UK Notify connection context. .DESCRIPTION Returns a summary of the connection established by Connect-GovUKNotify, including the key name, service id and base URL. The API key itself is never returned in full; only the last four characters are shown. Returns $null when there is no active connection. .EXAMPLE Get-GovUKNotifyContext .OUTPUTS System.Management.Automation.PSCustomObject, or $null when not connected. .LINK https://github.com/deanlongstaff/GOV.UK.Notify #> [CmdletBinding()] [OutputType([pscustomobject])] param() if ($null -eq $script:GovUKNotifyContext) { Write-Verbose 'No active GOV.UK Notify connection.' return $null } $Key = [string]$script:GovUKNotifyContext.ApiKey $Ending = if ($Key.Length -ge 4) { $Key.Substring($Key.Length - 4) } else { $Key } return [pscustomobject]@{ PSTypeName = 'GOV.UK.Notify.Context' KeyName = $script:GovUKNotifyContext.KeyName ServiceId = $script:GovUKNotifyContext.ServiceId BaseUrl = $script:GovUKNotifyContext.BaseUrl ApiKeyEnding = $Ending } } #endregion src/GOV.UK.Notify/Public/Get-GovUKNotifyContext.ps1 #region src/GOV.UK.Notify/Public/Get-GovUKNotifyLetterPdf.ps1 function Get-GovUKNotifyLetterPdf { <# .SYNOPSIS Retrieves the PDF contents of a GOV.UK Notify letter notification. .DESCRIPTION Calls 'GET /v2/notifications/{id}/pdf' and returns the raw PDF bytes, or writes them to a file with -OutFile. The PDF is only available once the letter has finished processing and has passed its virus scan. .PARAMETER NotificationId The id of the letter notification. .PARAMETER OutFile Optional path to write the PDF to. When supplied, no bytes are returned. .PARAMETER ApiKey An explicit API key, overriding any connected session. .PARAMETER BaseUrl An explicit base URL, overriding any connected session. .EXAMPLE Get-GovUKNotifyLetterPdf -NotificationId $id -OutFile ./letter.pdf .OUTPUTS System.Byte[] when -OutFile is not used; otherwise nothing. .LINK https://docs.notifications.service.gov.uk/rest-api.html#get-a-pdf-for-a-letter-notification #> [CmdletBinding()] [OutputType([byte[]])] param( [Parameter(Mandatory = $true, Position = 0)] [ValidateNotNullOrEmpty()] [string]$NotificationId, [Parameter()] [string]$OutFile, [Parameter()] [string]$ApiKey, [Parameter()] [string]$BaseUrl ) $ConnectionParams = @{} if ($PSBoundParameters.ContainsKey('ApiKey')) { $ConnectionParams['ApiKey'] = $ApiKey } if ($PSBoundParameters.ContainsKey('BaseUrl')) { $ConnectionParams['BaseUrl'] = $BaseUrl } $Bytes = Invoke-GovUKNotifyApi -Method 'GET' -Path "/v2/notifications/$NotificationId/pdf" -Raw @ConnectionParams if ($PSBoundParameters.ContainsKey('OutFile') -and -not [string]::IsNullOrWhiteSpace($OutFile)) { $ResolvedPath = $PSCmdlet.GetUnresolvedProviderPathFromPSPath($OutFile) [System.IO.File]::WriteAllBytes($ResolvedPath, $Bytes) Write-Verbose "Saved letter PDF to $ResolvedPath." return } # -- Return the byte array as a single object rather than streaming individual bytes. return , $Bytes } #endregion src/GOV.UK.Notify/Public/Get-GovUKNotifyLetterPdf.ps1 #region src/GOV.UK.Notify/Public/Get-GovUKNotifyNotification.ps1 function Get-GovUKNotifyNotification { <# .SYNOPSIS Retrieves the data for one or more GOV.UK Notify messages. .DESCRIPTION With -NotificationId, calls 'GET /v2/notifications/{id}' and returns a single message. Otherwise calls 'GET /v2/notifications' and returns messages, optionally filtered by template type, status, and reference. Each page returns up to 250 messages; use -All to follow pagination and return every matching message. You can only retrieve messages within your data retention period (7 days by default). .PARAMETER NotificationId The id of a single notification to retrieve. .PARAMETER TemplateType Filter the list by template type: 'email', 'sms' or 'letter'. .PARAMETER Status Filter the list by one or more delivery statuses, for example 'delivered' or 'permanent-failure'. .PARAMETER Reference Filter the list by the reference you supplied when sending. .PARAMETER OlderThan Return messages older than this notification id (pagination). .PARAMETER IncludeJobs Include notifications sent as part of a batch (bulk) upload. .PARAMETER All Follow pagination and return every matching message, not just the first page of up to 250. .PARAMETER ApiKey An explicit API key, overriding any connected session. .PARAMETER BaseUrl An explicit base URL, overriding any connected session. .EXAMPLE Get-GovUKNotifyNotification -NotificationId '740e5834-3a29-46b4-9a6f-16142fde533a' .EXAMPLE Get-GovUKNotifyNotification -TemplateType email -Status delivered -All .OUTPUTS A single notification object, or a stream of notification objects for the list. .LINK https://docs.notifications.service.gov.uk/rest-api.html#get-message-data #> [CmdletBinding(DefaultParameterSetName = 'List')] param( [Parameter(Mandatory = $true, ParameterSetName = 'Single', Position = 0)] [ValidateNotNullOrEmpty()] [string]$NotificationId, [Parameter(ParameterSetName = 'List')] [ValidateSet('email', 'sms', 'letter')] [string]$TemplateType, [Parameter(ParameterSetName = 'List')] [string[]]$Status, [Parameter(ParameterSetName = 'List')] [string]$Reference, [Parameter(ParameterSetName = 'List')] [string]$OlderThan, [Parameter(ParameterSetName = 'List')] [switch]$IncludeJobs, [Parameter(ParameterSetName = 'List')] [switch]$All, [Parameter()] [string]$ApiKey, [Parameter()] [string]$BaseUrl ) $ConnectionParams = @{} if ($PSBoundParameters.ContainsKey('ApiKey')) { $ConnectionParams['ApiKey'] = $ApiKey } if ($PSBoundParameters.ContainsKey('BaseUrl')) { $ConnectionParams['BaseUrl'] = $BaseUrl } if ($PSCmdlet.ParameterSetName -eq 'Single') { return Invoke-GovUKNotifyApi -Method 'GET' -Path "/v2/notifications/$NotificationId" @ConnectionParams } # -- Build the static part of the query (everything except older_than). $BaseQuery = [System.Collections.Generic.List[string]]::new() if ($TemplateType) { $BaseQuery.Add("template_type=$TemplateType") } foreach ($SingleStatus in $Status) { $BaseQuery.Add("status=$([uri]::EscapeDataString($SingleStatus))") } if ($Reference) { $BaseQuery.Add("reference=$([uri]::EscapeDataString($Reference))") } if ($IncludeJobs) { $BaseQuery.Add('include_jobs=true') } $CurrentOlderThan = $OlderThan do { $Query = [System.Collections.Generic.List[string]]::new($BaseQuery) if ($CurrentOlderThan) { $Query.Add("older_than=$CurrentOlderThan") } $Path = '/v2/notifications' if ($Query.Count -gt 0) { $Path += '?' + ($Query -join '&') } $Response = Invoke-GovUKNotifyApi -Method 'GET' -Path $Path @ConnectionParams $Items = @($Response.notifications) if ($Items.Count -gt 0) { $Items $CurrentOlderThan = $Items[-1].id } } while ($All -and $Items.Count -ge 250) } #endregion src/GOV.UK.Notify/Public/Get-GovUKNotifyNotification.ps1 #region src/GOV.UK.Notify/Public/Get-GovUKNotifyReceivedText.ps1 function Get-GovUKNotifyReceivedText { <# .SYNOPSIS Retrieves text messages received by your GOV.UK Notify service. .DESCRIPTION Calls 'GET /v2/received-text-messages' and returns received text messages, most recent first. Each page returns up to 250 messages; use -All to follow pagination and return every message. You can only retrieve messages that are 7 days old or newer. Receiving text messages must be enabled in your service settings. .PARAMETER OlderThan Return received text messages older than this message id (pagination). .PARAMETER All Follow pagination and return every received text message, not just the first page of up to 250. .PARAMETER ApiKey An explicit API key, overriding any connected session. .PARAMETER BaseUrl An explicit base URL, overriding any connected session. .EXAMPLE Get-GovUKNotifyReceivedText -All .OUTPUTS A stream of received text message objects. .LINK https://docs.notifications.service.gov.uk/rest-api.html#get-received-text-messages #> [CmdletBinding()] param( [Parameter()] [string]$OlderThan, [Parameter()] [switch]$All, [Parameter()] [string]$ApiKey, [Parameter()] [string]$BaseUrl ) $ConnectionParams = @{} if ($PSBoundParameters.ContainsKey('ApiKey')) { $ConnectionParams['ApiKey'] = $ApiKey } if ($PSBoundParameters.ContainsKey('BaseUrl')) { $ConnectionParams['BaseUrl'] = $BaseUrl } $CurrentOlderThan = $OlderThan do { $Path = '/v2/received-text-messages' if ($CurrentOlderThan) { $Path += "?older_than=$CurrentOlderThan" } $Response = Invoke-GovUKNotifyApi -Method 'GET' -Path $Path @ConnectionParams $Items = @($Response.received_text_messages) if ($Items.Count -gt 0) { $Items $CurrentOlderThan = $Items[-1].id } } while ($All -and $Items.Count -ge 250) } #endregion src/GOV.UK.Notify/Public/Get-GovUKNotifyReceivedText.ps1 #region src/GOV.UK.Notify/Public/Get-GovUKNotifyTemplate.ps1 function Get-GovUKNotifyTemplate { <# .SYNOPSIS Retrieves one template, a specific template version, or all templates. .DESCRIPTION With -TemplateId, calls 'GET /v2/template/{id}' for the latest version, or 'GET /v2/template/{id}/version/{version}' when -Version is also supplied. Without -TemplateId, calls 'GET /v2/templates' and returns all templates, optionally filtered by -Type. .PARAMETER TemplateId The id of a single template to retrieve. .PARAMETER Version A specific version number of the template to retrieve. .PARAMETER Type Filter the list of all templates by type: 'email', 'sms' or 'letter'. .PARAMETER ApiKey An explicit API key, overriding any connected session. .PARAMETER BaseUrl An explicit base URL, overriding any connected session. .EXAMPLE Get-GovUKNotifyTemplate -TemplateId $tid .EXAMPLE Get-GovUKNotifyTemplate -TemplateId $tid -Version 2 .EXAMPLE Get-GovUKNotifyTemplate -Type email .OUTPUTS A single template object, or a stream of template objects for the list. .LINK https://docs.notifications.service.gov.uk/rest-api.html#get-a-template #> [CmdletBinding(DefaultParameterSetName = 'List')] param( [Parameter(Mandatory = $true, ParameterSetName = 'Single', Position = 0)] [ValidateNotNullOrEmpty()] [string]$TemplateId, [Parameter(ParameterSetName = 'Single')] [ValidateRange(1, 2147483647)] [int]$Version, [Parameter(ParameterSetName = 'List')] [ValidateSet('email', 'sms', 'letter')] [string]$Type, [Parameter()] [string]$ApiKey, [Parameter()] [string]$BaseUrl ) $ConnectionParams = @{} if ($PSBoundParameters.ContainsKey('ApiKey')) { $ConnectionParams['ApiKey'] = $ApiKey } if ($PSBoundParameters.ContainsKey('BaseUrl')) { $ConnectionParams['BaseUrl'] = $BaseUrl } if ($PSCmdlet.ParameterSetName -eq 'Single') { if ($PSBoundParameters.ContainsKey('Version')) { return Invoke-GovUKNotifyApi -Method 'GET' -Path "/v2/template/$TemplateId/version/$Version" @ConnectionParams } return Invoke-GovUKNotifyApi -Method 'GET' -Path "/v2/template/$TemplateId" @ConnectionParams } $Path = '/v2/templates' if ($Type) { $Path += "?type=$Type" } $Response = Invoke-GovUKNotifyApi -Method 'GET' -Path $Path @ConnectionParams return $Response.templates } #endregion src/GOV.UK.Notify/Public/Get-GovUKNotifyTemplate.ps1 #region src/GOV.UK.Notify/Public/Get-GovUKNotifyTemplatePreview.ps1 function Get-GovUKNotifyTemplatePreview { <# .SYNOPSIS Generates a preview of a GOV.UK Notify template with personalisation applied. .DESCRIPTION Calls 'POST /v2/template/{id}/preview' to render a template with the supplied personalisation and returns the resulting subject, body and (for emails) HTML. The keys in -Personalisation must match the template's placeholder fields; extra keys are ignored by GOV.UK Notify. .PARAMETER TemplateId The id of the template to preview. .PARAMETER Personalisation A hashtable of placeholder values for the template. .PARAMETER ApiKey An explicit API key, overriding any connected session. .PARAMETER BaseUrl An explicit base URL, overriding any connected session. .EXAMPLE Get-GovUKNotifyTemplatePreview -TemplateId $tid -Personalisation @{ first_name = 'Amala' } .OUTPUTS The rendered template preview object returned by GOV.UK Notify. .LINK https://docs.notifications.service.gov.uk/rest-api.html#generate-a-preview-template #> [CmdletBinding()] param( [Parameter(Mandatory = $true, Position = 0)] [ValidateNotNullOrEmpty()] [string]$TemplateId, [Parameter()] [hashtable]$Personalisation, [Parameter()] [string]$ApiKey, [Parameter()] [string]$BaseUrl ) $Body = @{ personalisation = if ($Personalisation) { $Personalisation } else { @{} } } $ConnectionParams = @{} if ($PSBoundParameters.ContainsKey('ApiKey')) { $ConnectionParams['ApiKey'] = $ApiKey } if ($PSBoundParameters.ContainsKey('BaseUrl')) { $ConnectionParams['BaseUrl'] = $BaseUrl } return Invoke-GovUKNotifyApi -Method 'POST' -Path "/v2/template/$TemplateId/preview" -Body $Body @ConnectionParams } #endregion src/GOV.UK.Notify/Public/Get-GovUKNotifyTemplatePreview.ps1 #region src/GOV.UK.Notify/Public/New-GovUKNotifyFileAttachment.ps1 function New-GovUKNotifyFileAttachment { <# .SYNOPSIS Builds a file object for sending a file by email through GOV.UK Notify. .DESCRIPTION Produces the hashtable that GOV.UK Notify expects for a "send a file by email" placeholder. Assign the result to a template placeholder in the -Personalisation argument of Send-GovUKNotifyEmail. Supply the file as a path, a byte array, or an already base64-encoded string. .PARAMETER Path Path to the file to attach. The file is read and base64-encoded automatically, and its name is used as the filename unless -FileName is given. .PARAMETER Bytes The file contents as a byte array. .PARAMETER Base64Content The file contents as an already base64-encoded string. .PARAMETER FileName The filename shown to the recipient. Should include the correct file extension. .PARAMETER ConfirmEmailBeforeDownload Whether the recipient must confirm their email address before downloading. GOV.UK Notify defaults this to true. Set to $false to turn the check off (not recommended for sensitive files). .PARAMETER RetentionPeriod How long the file is available to download, for example '4 weeks'. Allowed range is 1 to 78 weeks. Defaults to 26 weeks at GOV.UK Notify if omitted. .EXAMPLE $file = New-GovUKNotifyFileAttachment -Path ./report.csv -RetentionPeriod '4 weeks' Send-GovUKNotifyEmail -EmailAddress 'amala@example.com' -TemplateId $tid -Personalisation @{ link_to_file = $file } .OUTPUTS System.Collections.Hashtable representing the file object. .LINK https://docs.notifications.service.gov.uk/rest-api.html#send-a-file-by-email #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '', Justification = 'Builds an in-memory personalisation object; it does not change any system state.')] [CmdletBinding(DefaultParameterSetName = 'Path')] [OutputType([hashtable])] param( [Parameter(Mandatory = $true, ParameterSetName = 'Path', Position = 0)] [ValidateNotNullOrEmpty()] [string]$Path, [Parameter(Mandatory = $true, ParameterSetName = 'Bytes')] [ValidateNotNull()] [byte[]]$Bytes, [Parameter(Mandatory = $true, ParameterSetName = 'Base64')] [ValidateNotNullOrEmpty()] [string]$Base64Content, [Parameter()] [string]$FileName, [Parameter()] [bool]$ConfirmEmailBeforeDownload, [Parameter()] [ValidatePattern('^\d+\s+weeks?$')] [string]$RetentionPeriod ) switch ($PSCmdlet.ParameterSetName) { 'Path' { $ResolvedPath = (Resolve-Path -LiteralPath $Path -ErrorAction Stop).ProviderPath $FileBytes = [System.IO.File]::ReadAllBytes($ResolvedPath) $EncodedContent = [Convert]::ToBase64String($FileBytes) if (-not $PSBoundParameters.ContainsKey('FileName')) { $FileName = [System.IO.Path]::GetFileName($ResolvedPath) } } 'Bytes' { $EncodedContent = [Convert]::ToBase64String($Bytes) } 'Base64' { $EncodedContent = $Base64Content } } $Attachment = @{ file = $EncodedContent } if ($FileName) { $Attachment.filename = $FileName } if ($PSBoundParameters.ContainsKey('ConfirmEmailBeforeDownload')) { $Attachment.confirm_email_before_download = $ConfirmEmailBeforeDownload } if ($RetentionPeriod) { $Attachment.retention_period = $RetentionPeriod } return $Attachment } #endregion src/GOV.UK.Notify/Public/New-GovUKNotifyFileAttachment.ps1 #region src/GOV.UK.Notify/Public/Send-GovUKNotifyEmail.ps1 function Send-GovUKNotifyEmail { <# .SYNOPSIS Sends an email using a GOV.UK Notify template. .DESCRIPTION Calls 'POST /v2/notifications/email' to send an email built from one of your GOV.UK Notify templates. To send a file by email, build the value for a template placeholder with New-GovUKNotifyFileAttachment and include it in -Personalisation. .PARAMETER EmailAddress The recipient's email address. .PARAMETER TemplateId The id of the email template to use. Copy it from the Templates page of the GOV.UK Notify dashboard. .PARAMETER Personalisation A hashtable of placeholder values for the template. Values may be strings, arrays (rendered as bullet points), or a file object from New-GovUKNotifyFileAttachment. .PARAMETER Reference An optional identifier for the message or batch. Must not contain personal data. .PARAMETER EmailReplyToId An optional reply-to address id configured on your service. .PARAMETER OneClickUnsubscribeUrl An optional one-click unsubscribe URL added to the email headers for subscription emails. .PARAMETER SanitiseContentFor An optional list of personalisation keys whose content GOV.UK Notify should sanitise (escape Markdown and remove URLs) to reduce the risk of malicious content injection. .PARAMETER ApiKey An explicit API key, overriding any connected session. .PARAMETER BaseUrl An explicit base URL, overriding any connected session. .EXAMPLE Send-GovUKNotifyEmail -EmailAddress 'amala@example.com' -TemplateId $tid -Personalisation @{ first_name = 'Amala' } .EXAMPLE $file = New-GovUKNotifyFileAttachment -Path ./invite.pdf Send-GovUKNotifyEmail -EmailAddress 'amala@example.com' -TemplateId $tid -Personalisation @{ link_to_file = $file } .OUTPUTS The notification response object returned by GOV.UK Notify. .LINK https://docs.notifications.service.gov.uk/rest-api.html#send-an-email #> [CmdletBinding(SupportsShouldProcess = $true)] param( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$EmailAddress, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$TemplateId, [Parameter()] [hashtable]$Personalisation, [Parameter()] [string]$Reference, [Parameter()] [string]$EmailReplyToId, [Parameter()] [string]$OneClickUnsubscribeUrl, [Parameter()] [string[]]$SanitiseContentFor, [Parameter()] [string]$ApiKey, [Parameter()] [string]$BaseUrl ) $Body = @{ email_address = $EmailAddress template_id = $TemplateId } if ($Personalisation) { $Body.personalisation = $Personalisation } if ($Reference) { $Body.reference = $Reference } if ($EmailReplyToId) { $Body.email_reply_to_id = $EmailReplyToId } if ($OneClickUnsubscribeUrl) { $Body.one_click_unsubscribe_url = $OneClickUnsubscribeUrl } if ($SanitiseContentFor) { $Body.sanitise_content_for = $SanitiseContentFor } $ConnectionParams = @{} if ($PSBoundParameters.ContainsKey('ApiKey')) { $ConnectionParams['ApiKey'] = $ApiKey } if ($PSBoundParameters.ContainsKey('BaseUrl')) { $ConnectionParams['BaseUrl'] = $BaseUrl } if ($PSCmdlet.ShouldProcess($EmailAddress, 'Send GOV.UK Notify email')) { return Invoke-GovUKNotifyApi -Method 'POST' -Path '/v2/notifications/email' -Body $Body @ConnectionParams } } #endregion src/GOV.UK.Notify/Public/Send-GovUKNotifyEmail.ps1 #region src/GOV.UK.Notify/Public/Send-GovUKNotifyLetter.ps1 function Send-GovUKNotifyLetter { <# .SYNOPSIS Sends a letter using a GOV.UK Notify template. .DESCRIPTION Calls 'POST /v2/notifications/letter' to send a letter built from one of your GOV.UK Notify templates. The -Personalisation hashtable must include the recipient's address as 'address_line_1' through 'address_line_7'. The address must have at least 3 lines; the first two lines must contain alphanumeric characters and the last line must be a real UK postcode or the name of a country outside the UK. Your service must be live to send letters. .PARAMETER TemplateId The id of the letter template to use. .PARAMETER Personalisation A hashtable of placeholder values, including the required address lines and any other template placeholders. .PARAMETER Reference An optional identifier for the letter or batch. Must not contain personal data. .PARAMETER ApiKey An explicit API key, overriding any connected session. .PARAMETER BaseUrl An explicit base URL, overriding any connected session. .EXAMPLE $address = @{ address_line_1 = 'Amala Bird' address_line_2 = '123 High Street' address_line_3 = 'SW14 6BH' } Send-GovUKNotifyLetter -TemplateId $tid -Personalisation $address .OUTPUTS The notification response object returned by GOV.UK Notify. .LINK https://docs.notifications.service.gov.uk/rest-api.html#send-a-letter #> [CmdletBinding(SupportsShouldProcess = $true)] param( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$TemplateId, [Parameter(Mandatory = $true)] [ValidateNotNull()] [hashtable]$Personalisation, [Parameter()] [string]$Reference, [Parameter()] [string]$ApiKey, [Parameter()] [string]$BaseUrl ) $Body = @{ template_id = $TemplateId personalisation = $Personalisation } if ($Reference) { $Body.reference = $Reference } $ConnectionParams = @{} if ($PSBoundParameters.ContainsKey('ApiKey')) { $ConnectionParams['ApiKey'] = $ApiKey } if ($PSBoundParameters.ContainsKey('BaseUrl')) { $ConnectionParams['BaseUrl'] = $BaseUrl } if ($PSCmdlet.ShouldProcess("letter template $TemplateId", 'Send GOV.UK Notify letter')) { return Invoke-GovUKNotifyApi -Method 'POST' -Path '/v2/notifications/letter' -Body $Body @ConnectionParams } } #endregion src/GOV.UK.Notify/Public/Send-GovUKNotifyLetter.ps1 #region src/GOV.UK.Notify/Public/Send-GovUKNotifyPrecompiledLetter.ps1 function Send-GovUKNotifyPrecompiledLetter { <# .SYNOPSIS Sends a precompiled (PDF) letter through GOV.UK Notify. .DESCRIPTION Calls 'POST /v2/notifications/letter' with a base64-encoded PDF. Supply the letter either as a file with -Path (which is read and encoded for you) or as an already base64-encoded string with -Content. The PDF must meet the GOV.UK Notify letter specification. Your service must be live and you must use a live API key (not a team key). .PARAMETER Reference A required identifier for the letter or batch. Must not contain personal data. .PARAMETER Path Path to a PDF file to send. The file is read and base64-encoded automatically. .PARAMETER Content An already base64-encoded PDF string. .PARAMETER Postage Optional postage class: 'first', 'second' or 'economy'. Defaults to second class at GOV.UK Notify if omitted. .PARAMETER ApiKey An explicit API key, overriding any connected session. .PARAMETER BaseUrl An explicit base URL, overriding any connected session. .EXAMPLE Send-GovUKNotifyPrecompiledLetter -Reference 'batch-001' -Path ./letter.pdf -Postage first .OUTPUTS The notification response object returned by GOV.UK Notify. .LINK https://docs.notifications.service.gov.uk/rest-api.html#send-a-precompiled-letter #> [CmdletBinding(SupportsShouldProcess = $true, DefaultParameterSetName = 'Path')] param( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$Reference, [Parameter(Mandatory = $true, ParameterSetName = 'Path')] [ValidateNotNullOrEmpty()] [string]$Path, [Parameter(Mandatory = $true, ParameterSetName = 'Content')] [ValidateNotNullOrEmpty()] [string]$Content, [Parameter()] [ValidateSet('first', 'second', 'economy')] [string]$Postage, [Parameter()] [string]$ApiKey, [Parameter()] [string]$BaseUrl ) if ($PSCmdlet.ParameterSetName -eq 'Path') { $ResolvedPath = (Resolve-Path -LiteralPath $Path -ErrorAction Stop).ProviderPath $Bytes = [System.IO.File]::ReadAllBytes($ResolvedPath) $Content = [Convert]::ToBase64String($Bytes) } $Body = @{ reference = $Reference content = $Content } if ($Postage) { $Body.postage = $Postage } $ConnectionParams = @{} if ($PSBoundParameters.ContainsKey('ApiKey')) { $ConnectionParams['ApiKey'] = $ApiKey } if ($PSBoundParameters.ContainsKey('BaseUrl')) { $ConnectionParams['BaseUrl'] = $BaseUrl } if ($PSCmdlet.ShouldProcess("precompiled letter '$Reference'", 'Send GOV.UK Notify precompiled letter')) { return Invoke-GovUKNotifyApi -Method 'POST' -Path '/v2/notifications/letter' -Body $Body @ConnectionParams } } #endregion src/GOV.UK.Notify/Public/Send-GovUKNotifyPrecompiledLetter.ps1 #region src/GOV.UK.Notify/Public/Send-GovUKNotifySms.ps1 function Send-GovUKNotifySms { <# .SYNOPSIS Sends a text message using a GOV.UK Notify template. .DESCRIPTION Calls 'POST /v2/notifications/sms' to send a text message built from one of your GOV.UK Notify templates. .PARAMETER PhoneNumber The recipient's phone number. This can be a UK or international number. .PARAMETER TemplateId The id of the text message template to use. .PARAMETER Personalisation A hashtable of placeholder values for the template. .PARAMETER Reference An optional identifier for the message or batch. Must not contain personal data. .PARAMETER SmsSenderId An optional text message sender id configured on your service. Omit to use the default sender. .PARAMETER ApiKey An explicit API key, overriding any connected session. .PARAMETER BaseUrl An explicit base URL, overriding any connected session. .EXAMPLE Send-GovUKNotifySms -PhoneNumber '+447900900123' -TemplateId $tid -Personalisation @{ code = '123456' } .OUTPUTS The notification response object returned by GOV.UK Notify. .LINK https://docs.notifications.service.gov.uk/rest-api.html#send-a-text-message #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseSingularNouns', '', Justification = 'SMS is an acronym, not a plural noun.')] [CmdletBinding(SupportsShouldProcess = $true)] param( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$PhoneNumber, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$TemplateId, [Parameter()] [hashtable]$Personalisation, [Parameter()] [string]$Reference, [Parameter()] [string]$SmsSenderId, [Parameter()] [string]$ApiKey, [Parameter()] [string]$BaseUrl ) $Body = @{ phone_number = $PhoneNumber template_id = $TemplateId } if ($Personalisation) { $Body.personalisation = $Personalisation } if ($Reference) { $Body.reference = $Reference } if ($SmsSenderId) { $Body.sms_sender_id = $SmsSenderId } $ConnectionParams = @{} if ($PSBoundParameters.ContainsKey('ApiKey')) { $ConnectionParams['ApiKey'] = $ApiKey } if ($PSBoundParameters.ContainsKey('BaseUrl')) { $ConnectionParams['BaseUrl'] = $BaseUrl } if ($PSCmdlet.ShouldProcess($PhoneNumber, 'Send GOV.UK Notify text message')) { return Invoke-GovUKNotifyApi -Method 'POST' -Path '/v2/notifications/sms' -Body $Body @ConnectionParams } } #endregion src/GOV.UK.Notify/Public/Send-GovUKNotifySms.ps1 Export-ModuleMember -Function @( 'Connect-GovUKNotify' 'Disconnect-GovUKNotify' 'Get-GovUKNotifyContext' 'Get-GovUKNotifyLetterPdf' 'Get-GovUKNotifyNotification' 'Get-GovUKNotifyReceivedText' 'Get-GovUKNotifyTemplate' 'Get-GovUKNotifyTemplatePreview' 'New-GovUKNotifyFileAttachment' 'Send-GovUKNotifyEmail' 'Send-GovUKNotifyLetter' 'Send-GovUKNotifyPrecompiledLetter' 'Send-GovUKNotifySms' ) |