Send Mail with Attachment via Microsoft Graph

Hi All,
I had to debug an Application that sends a Mail with an Attachment via Graph API. I’ve created this Small Script to Test the Functionality.
Entra Application
You need an Entra Application.
Entra Application:
Certificate Authentication:
Permissions:
- Application: Mail.ReadWrite
- Application: Mail.Send
Application Access Policy
I’ve written a whole Article Application Access Policy in Exchange Online
Connect-ExchangeOnline -ShowBanner:$False
Get-DistributionGroup -Identity PostmasterGraphRestriction | fl DisplayName, PrimarySmtpAddress, ExternalDirectoryObjectId
Get-DistributionGroupMember -Identity PostmasterGraphRestriction | fl DisplayName, PrimarySmtpAddress,ExternalDirectoryObjectId
With this Application Access Policy you restrict the Graph Permissions of the Entra Application to the Members of the Distribution Group.
New-ApplicationAccessPolicy -AccessRight RestrictAccess -AppId "5cf8b5b9-1532-44bf-9e39-5f70534a2e90" -PolicyScopeGroupId "PostmasterGraphRestriction@icewolf.ch" -Description "Restrict this app to members of this Group"
Send Attachment via Graph API
Now we come to the Part where we send a Mail with an Attachment. It involves multiple steps:
- Create the Message (in Drafts)
- Add the Attachment (in Drafts)
- Send the Draft Message
First we need to Connect with the Graph API
###############################################################################
# Variables
###############################################################################
$AppID = "5cf8b5b9-1532-44bf-9e39-5f70534a2e90" #DemoSendAttachment
$TenantId = "icewolfch.onmicrosoft.com"
$CertificateThumbprint = "A3A07A3C2C109303CCCB011B10141A020C8AFDA3" #O365PowerShell4
Connect-MgGraph -ClientId $AppID -TenantId $TenantId -CertificateThumbprint $CertificateThumbprint -NoWelcome
Let’s create the Draft Message
###############################################################################
# Create Mailbox Message
# https://docs.microsoft.com/en-us/graph/api/user-post-messages?view=graph-rest-1.0&tabs=http
###############################################################################
$Mailbox = "Postmaster@icewolf.ch"
$URI = "https://graph.microsoft.com/v1.0/users/$Mailbox/messages"
$ContentType = "application/json"
$Headers = @{"Authorization" = "Bearer "+ $AccessToken}
$Body = @"
{
"subject":"Demo Attachement",
"body":{
"contentType":"HTML",
"content":"Look at the <b>awesome</b> attachment!"
},
"toRecipients":[
{
"emailAddress":{
"address":"a.bohren@icewolf.ch"
}
}
]
}
"@
$Result = Invoke-GraphRequest -URI $URI -Method POST -Body $Body -ContentType $ContentType
$MessageID = $Result.id
$MessageID
this is the Drafts Message in Outlook on the Web
Let’s add the Attachment. Note that the Content needs to be loaded as Bytearray and then convert to Base64
###############################################################################
# Add Attachment to Mailbox Message (max 3MB)
# https://docs.microsoft.com/en-us/graph/api/message-post-attachments?view=graph-rest-1.0&tabs=http
###############################################################################
$URI = "https://graph.microsoft.com/v1.0/users/$Mailbox/messages/$MessageID/attachments"
#Get Byte Content
If ($host.version -ge "7.0")
{
#PowerShell 7
$ContentByte = Get-Content -Path "C:\Temp\AndresBohren.jpg" -AsByteStream
} else {
#PowerShell 5
$ContentByte = Get-Content -Path "C:\Temp\AndresBohren.jpg" -Encoding Byte
}
#Convert to Base64
$Base64 =[Convert]::ToBase64String($ContentByte)
$ContentType = "application/json"
$Headers = @{"Authorization" = "Bearer "+ $AccessToken}
$Body = @"
{
"@odata.type": "#microsoft.graph.fileAttachment",
"name": "AndresBohren.jpg",
"contentBytes": "$Base64"
}
"@
$Result = Invoke-GraphRequest -URI $URI -Method POST -Body $Body -ContentType $ContentType
The File is now attached to the Draft Message
Now, we can send the Message
###############################################################################
# Send draft message
# https://learn.microsoft.com/en-us/graph/api/message-send?view=graph-rest-1.0&tabs=http
###############################################################################
$URI = "https://graph.microsoft.com/v1.0/users/$Mailbox/messages/$MessageID/Send"
$Result = Invoke-GraphRequest -URI $URI -Method POST
This is the Message i received in Outlook Classic
Summary
Now you have learned how the send an Mail with Attachment via the Graph Api and PowerShell. Hope you find this useful.
Regards
Andres Bohren