Private/New-MSGraphMailAttachment.ps1
function New-MSGraphMailAttachment { [CmdletBinding()] param ( [Parameter(Mandatory = $True)] [string]$Mailbox, [Parameter(Mandatory = $True)] [string]$MessageID, [string]$Folder, [Parameter(Mandatory = $True)] [string[]]$Attachments, [switch]$InlineAttachments ) Write-Debug "Got attachments $($Attachments -join ', ')" foreach ($AttachmentItem in $Attachments) { if ($InlineAttachments) { $IAParts = $AttachmentItem.Split(';') $CID = $IAParts[0] Write-Verbose ("Content ID: $CID") $Attachment = $IAParts[1] Write-Verbose ("Attachment: $Attachment") } else { $Attachment = $AttachmentItem } Test-Path -Path $Attachment -ErrorAction Stop | Out-Null $AttachmentFile = Get-Item -Path $Attachment -ErrorAction Stop $Bytes = Get-Content -Path $AttachmentFile.FullName -AsByteStream -Raw if ($Bytes.Length -le 2999999) { Write-Debug "Attachment $($AttachmentFile.Fullname) size is $($Bytes.Length) which is less than 3MB - using direct upload" $UploadSession = $False } else { Write-Debug "Attachment $($AttachmentFile.Fullname) size is $($Bytes.Length) which is greater than 3MB - using streaming upload" $UploadSession = $True } $AttachmentItem = @{ "@odata.type" = "#microsoft.graph.fileAttachment" attachmentType = 'file' name = $AttachmentFile.Name } if ($CID) { $AttachmentItem.contentId = $CID $AttachmentItem.isInline = $True if ($AttachmentFile.Extension -eq '.png') { $AttachmentItem.contentType = 'image/png' } elseif (($AttachmentFile.Extension -eq '.jpg') -or ($AttachmentFile.Extension -eq '.jpeg')) { $AttachmentItem.contentType = 'image/jpeg' } elseif ($AttachmentFile.Extension -eq '.gif') { $AttachmentItem.contentType = 'image/gif' } } else { $AttachmentItem.size = $($Bytes.Length) } Write-Debug "Generated attachment item $($AttachmentItem | ConvertTo-JSON)" $RequestURI = [System.UriBuilder]::New('https', 'graph.microsoft.com') if ($UploadSession) { $UploadTry = 0 do { if ($Folder) { $RequestURI.Path = "v1.0/users/$($Mailbox)/mailFolders/$($Folder)/messages/$($MessageID)/attachments/createUploadSession" } else { $RequestURI.Path = "v1.0/users/$($Mailbox)/messages/$($MessageID)/attachments/createUploadSession" } $AttachmentItem.Remove('@odata.type') $SessionAttachmentItem = @{ AttachmentItem = $AttachmentItem } $UploadSessionParams = @{ URI = $RequestURI.ToString() Body = $SessionAttachmentItem ContentType = 'application/json' Raw = $False } try { $UploadTry++ $InternalServerError = $False Write-CustomMessage "Attempting to upload $($AttachmentFile.FullName) attempt number $($UploadTry)" -Type 'Information' $AttachmentSession = New-MSGraphMailPOSTRequest @UploadSessionParams Write-Debug "Got upload session details $($AttachmentSession)" $AttachmentSessionURI = $AttachmentSession.uploadurl } catch { $ErrorRecord = @{ ExceptionType = 'System.Net.Http.HttpRequestException' ErrorMessage = 'Creating session for attachment upload to the Microsoft Graph API failed.' InnerException = $_.Exception ErrorID = 'MSGraphMailFailedToGetAttachmentUploadSession' ErrorCategory = 'ProtocolError' TargetObject = $_.TargetObject ErrorDetails = $_.ErrorDetails BubbleUpDetails = $True } $RequestError = New-MSGraphErrorRecord @ErrorRecord $PSCmdlet.ThrowTerminatingError($RequestError) } if ($AttachmentSession) { $AdditionalHeaders = @{ "Content-Range" = "bytes 0-$($Bytes.Length -1)/$($Bytes.Length)" } $AttachmentUploadParams =@{ URI = $AttachmentSessionURI Body = $Bytes Anonymous = $True AdditionalHeaders = $AdditionalHeaders Raw = $False } try { $AttachmentUpload = New-MSGraphMailPUTRequest @AttachmentUploadParams if ($AttachmentUpload) { $InternalServerError = $False Write-CustomMessage -Message "Attached file '$($AttachmentFile.FullName)' to message $($MessageID)" -Type 'Success' } } catch { if ($_.Exception.InnerException.InnerException.Response.StatusCode.value__ -eq 500) { Write-Warning "Attempt to upload '$($AttachmentFile.FullName)' failed. Retrying." $InternalServerError = $True } else { $ErrorRecord = @{ ExceptionType = 'System.Net.Http.HttpRequestException' ErrorMessage = "Sending attachment '$($AttachmentFile.Name)' to the Microsoft Graph API failed." InnerException = $_.Exception ErrorID = 'MSGraphMailAttachmentUploadFailed' ErrorCategory = 'ProtocolError' TargetObject = $_.TargetObject ErrorDetails = $_.ErrorDetails BubbleUpDetails = $True } $RequestError = New-MSGraphErrorRecord @ErrorRecord $PSCmdlet.ThrowTerminatingError($RequestError) } } } } while (($InternalServerError) -and ($UploadTry -le 5)) } else { if ($Folder) { $RequestURI.Path = "v1.0/users/$($Mailbox)/mailFolders/$($Folder)/messages/$($MessageID)/attachments" } else { $RequestURI.Path = "v1.0/users/$($Mailbox)/messages/$($MessageID)/attachments" } $AttachmentItem.contentBytes = [convert]::ToBase64String($Bytes) $SimpleAttachmentParams = @{ URI = $RequestURI.ToString() Body = $($AttachmentItem) ContentType = 'application/json' Raw = $False } try { $AttachmentUpload = New-MSGraphMailPOSTRequest @SimpleAttachmentParams if ($AttachmentUpload) { Write-CustomMessage -Message "Attached file '$($AttachmentFile.Name)' to message $($MessageID)" -Type 'Success' } } catch { $ErrorRecord = @{ ExceptionType = 'System.Net.Http.HttpRequestException' ErrorMessage = "Sending attachment '$($AttachmentFile.Name)' to the Microsoft Graph API failed." InnerException = $_.Exception ErrorID = 'MSGraphMailAttachmentUploadFailed' ErrorCategory = 'ProtocolError' TargetObject = $_.TargetObject ErrorDetails = $_.ErrorDetails BubbleUpDetails = $True } $RequestError = New-MSGraphErrorRecord @ErrorRecord $PSCmdlet.ThrowTerminatingError($RequestError) } } } } |