Public/Send-NSPGraphMail.ps1
|
function Send-NSPGraphMail { <# .SYNOPSIS Sends one message as a mailbox through Graph sendMail, with optional file attachments. .DESCRIPTION Uses the active connection (Connect-NSPGraph / Connect-NSPGraphAppOnly) and transport. An app-only connection needs the Mail.Send application permission, which reaches every mailbox in the tenant unless Exchange RBAC for Applications scopes it; a delegated one sends as the signed-in user or a mailbox they can send as. Attachments are files, sent inline (fileAttachment). Graph's sendMail request is limited to about 4 MB, so the attachments' total size is checked first (-MaxAttachmentBytes, default 3 MB) and the call throws before sending anything when it is over. Throws when Graph rejects the message; returns nothing on success. .EXAMPLE Send-NSPGraphMail -From 'reports@contoso.example' -To 'ops@contoso.example' -Subject 'Nightly run' -Body 'All files sent.' .EXAMPLE Send-NSPGraphMail -From 'reports@contoso.example' -To 'ops@contoso.example' -Cc 'lead@contoso.example' -Subject 'Logs' -Body $text -Attachment (Get-ChildItem .\Logs -File).FullName #> [CmdletBinding(SupportsShouldProcess)] param( [Parameter(Mandatory)][string]$From, [Parameter(Mandatory)][string[]]$To, [string[]]$Cc, [string[]]$Bcc, [Parameter(Mandatory)][string]$Subject, [Parameter(Mandatory)][AllowEmptyString()][string]$Body, [ValidateSet('Text', 'HTML')][string]$BodyType = 'Text', [string[]]$Attachment, [switch]$SaveToSentItems, [ValidateRange(1, 4000000)][int]$MaxAttachmentBytes = 3000000 ) # @() at each call site too: a one-address list would otherwise unroll to a bare hashtable and # serialize as an object, not the array Graph requires. $toRecipient = { param([string[]]$Address) @($Address | Where-Object { $_ } | ForEach-Object { @{ emailAddress = @{ address = $_ } } }) } $files = @($Attachment | Where-Object { $_ } | ForEach-Object { Get-Item -LiteralPath $_ -ErrorAction Stop }) $total = ($files | Measure-Object -Property Length -Sum).Sum if ($total -gt $MaxAttachmentBytes) { throw "Attachments total $total bytes, over the $MaxAttachmentBytes-byte limit for one sendMail request. Send fewer or smaller files." } $message = @{ subject = $Subject body = @{ contentType = $BodyType; content = $Body } toRecipients = @(& $toRecipient $To) } if ($Cc) { $message.ccRecipients = @(& $toRecipient $Cc) } if ($Bcc) { $message.bccRecipients = @(& $toRecipient $Bcc) } if ($files.Count) { $message.attachments = @($files | ForEach-Object { @{ '@odata.type' = '#microsoft.graph.fileAttachment'; name = $_.Name; contentBytes = [Convert]::ToBase64String([IO.File]::ReadAllBytes($_.FullName)) } }) } if (-not $PSCmdlet.ShouldProcess(($To -join ', '), "Send '$Subject' from $From with $($files.Count) attachment(s)")) { return } Invoke-NSPGraphRequest -Method POST -Uri "users/$([uri]::EscapeDataString($From))/sendMail" -Body @{ message = $message; saveToSentItems = [bool]$SaveToSentItems } | Out-Null } |