We all know that the Basic Authentication end is near and that I am a huge fan of Microsoft Graph API, so I am providing an example on “How to send an Email with PowerShell and Microsoft Graph API.”
To learn more from Microsoft GRAPH API, see my Blog Series:
Part 1 β Authentication and Azure App βΒ Use Microsoft Graph API with PowerShell β Part 1 Β» TechGuy
Part 2 β Oauth2.0 βΒ Use Microsoft Graph API with PowerShell β Part 2 Β» TechGuy
Part 3 β First Powershell Script to get a Teams Lis and Walkthrough βΒ Use Microsoft Graph API with PowerShell β Part 3 Β» TechGuy
Part 4 β this one βΒ Use Microsoft Graph API with PowerShell β Part 4 Β» TechGuy
API Reference and Permissions
The official documentation is here: Send mail – Microsoft Graph v1.0 | Microsoft Docs
Azure App Registration Rights:
- Mail.Send
The Script
$clientID = "yourClientID"
$Clientsecret = "yourSecret"
$tenantID = "yourTenantID"
$MailSender = "michael.seidl@au2mator.com"
#Connect to GRAPH API
$tokenBody = @{
Grant_Type = "client_credentials"
Scope = "https://graph.microsoft.com/.default"
Client_Id = $clientId
Client_Secret = $clientSecret
}
$tokenResponse = Invoke-RestMethod -Uri "https://login.microsoftonline.com/$tenantID/oauth2/v2.0/token" -Method POST -Body $tokenBody
$headers = @{
"Authorization" = "Bearer $($tokenResponse.access_token)"
"Content-type" = "application/json"
}
#Send Mail
$URLsend = "https://graph.microsoft.com/v1.0/users/$MailSender/sendMail"
$BodyJsonsend = @"
{
"message": {
"subject": "Hello World from Microsoft Graph API",
"body": {
"contentType": "HTML",
"content": "This Mail is sent via Microsoft <br>
GRAPH <br>
API<br>
"
},
"toRecipients": [
{
"emailAddress": {
"address": "michael.seidl@au2mator.com"
}
}
]
},
"saveToSentItems": "false"
}
"@
Invoke-RestMethod -Method POST -Uri $URLsend -Headers $headers -Body $BodyJsonsend
The Result
GitHub Repo
Here you can find the GitHub Repo: Seidlm/Microsoft-Graph-API-Examples (github.com)
Michael Seidl aka Techguy
au2mate everything
Hello,
I am receiving the following error:
“Invoke-RestMethod : The remote server returned an error: (401) Unauthorized.”
Any idea ? π
I have looking into for days..
Thanks π
Ivan
Hi, it seems you misconfigured the App Registration ad forgot some permissions.
Awesome post.
I tried for about 2 hours to get the code working with the other URI in the documentation “https://graph.microsoft.com/v.1.0/me/sendMail” and it wasn’t until I found this post that I got it working. In case anyone else has this issue, the /me endpoint doesn’t work with application permissions and only works with delegated permissions! Info here:
https://docs.microsoft.com/en-us/graph/api/user-get?view=graph-rest-1.0&tabs=http
Thanks, will add this as a note to my post
I set the contentType: “HTML” but get:
{“error”:{“code”:”BadRequest”,”message”:”Unable to read JSON request payload. Please ensure Content-Type header is set and payload is of valid JSON format.”,
when I set content: to an html table. The old school send-mailmessage had no issues with this.
You cannot change the content type, you need to integrate your HTML into the JSON Body
You misunderstood:
“message”: {
“subject”: “Hello World from Microsoft Graph API”,
“body”: {
“contentType”: “HTML”,
“content”: “This Mail is sent via Microsoft
GRAPH
API
”
},
Is what you have. All I am doing is changing the content: to include html table code.
When my mail sender has an on-premise mailbox it fails with Invoke-RestMethod : The remote server returned an error: (401) Unauthorized. If the mail sender has an Exchange online mailbox it works fine and then can send to both on-premise and online mailboxes. We had a hybrid exchange setup and it is working as expected with other applications like Teams etc.
Any ideas?
This will only work when the sender Mailbox is in the CLoud.
MS Graph API is for Cloud Access only.
post your complete JSON, so we can take a look.
Thanks Michael. It does say here for REST API anyway it should be supported. https://docs.microsoft.com/en-us/graph/hybrid-rest-support#requirements-for-the-rest-api-to-work-in-hybrid-deployments. I am just testing with your code in this blog post.
$clientID = “”
$Clientsecret = “”
$tenantID = “”
$MailSender = “”
#Connect to GRAPH API
$tokenBody = @{
Grant_Type = “client_credentials”
Scope = “https://graph.microsoft.com/.default”
Client_Id = $clientId
Client_Secret = $clientSecret
}
$tokenResponse = Invoke-RestMethod -Uri “https://login.microsoftonline.com/$tenantID/oauth2/v2.0/token” -Method POST -Body $tokenBody
$headers = @{
“Authorization” = “Bearer $($tokenResponse.access_token)”
“Content-type” = “application/json”
}
#Send Mail
$URLsend = “https://graph.microsoft.com/v1.0/users/$MailSender/sendMail”
$BodyJsonsend = @”
{
“message”: {
“subject”: “Hello World from Microsoft Graph API”,
“body”: {
“contentType”: “HTML”,
“content”: “This Mail is sent via Microsoft
GRAPH
API
”
},
“toRecipients”: [
{
“emailAddress”: {
“address”: “”
}
}
]
},
“saveToSentItems”: “false”
}
“@
Invoke-RestMethod -Method POST -Uri $URLsend -Headers $headers -Body $BodyJsonsend
Oh thanks, interesting.
But unfortunately, I do not have an on-prem server to test.
Hi Michael,
I am trying send mail api with postman
endpoint : POST https://graph.microsoft.com/v1.0/users/$MailSender/sendMail
Header:
Content-Type:application/json
Content-Length:0
Body :
{
“message”: {
“subject”: “Hello World from Microsoft Graph API”,
“body”: {
“contentType”: “HTML”,
“content”: “This Mail is sent via Microsoft ”
},
“toRecipients”: [{
“emailAddress”: {
“address”: “—-@—-”
}
}]
},
“saveToSentItems”: “false”
}
When I hit the send button I am getting below message as a response
response : Bad request 400
{
“error”: {
“code”: “ErrorInvalidParameter”,
“message”: “The value of the parameter ‘Message’ is empty.”
}
}
though my message parameter is not empty in body. Still getting the error for message.
I am following https://docs.microsoft.com/en-us/graph/api/user-sendmail?view=graph-rest-1.0&tabs=http
Kindly assist.
Thanks,
Priya
Hi
Do you know if it’s possible to have parameter with waiting for Delivery receipt ?
Hi,
The parameter can be set to receive a Delivery receipt, the logic to wait for needs to be scripted in PowerSehll.
We can help on this, just let me know
Hi Michael,
I am getting the below error relating to the invoke command. Do you know how I might overcome this?
Invoke-RestMethod : The remote server returned an error: (400) Bad Request.
Many thanks
Hi. Nice post.
have you tried to manage the json through a hash?
Many thanks
THANK YOU. I was hung up on finding an actual PowerShell JSON example that worked and got yours plugged into my almost-done script and got to finish line. Appreciate it π
You are welcome, nice to hear I can help
very nice option to send mail messages from powershell… thank you for that! One question, how can i send to multiple recipients?
Hi, please see the example for BCC here, do the same for Recipient
"message": {
"subject": "$Subject",
"body": {
"contentType": "HTML",
"content": "$Body
"
},
"toRecipients": [
{
"emailAddress": {
"address": "$TO"
}
}
],
"bccRecipients": [
{
"emailAddress": {
"address": "$Bcc1"
}
},
{
"emailAddress": {
"address": "$Bcc2"
}
}
],
},
Hello, if we want to send the same mail several time in a for loop and and in subject “test N1 and increment automatically each time it’s called”, where do we add the loop?
Hi,
see do-while Loop, which is doing what you need.
how it will increment the subject number?
example test 1, test 2, test 3 (as subject each time a mail is sent)?
Hi,
you can read more about here: https://devblogs.microsoft.com/scripting/powershell-looping-understanding-and-using-do-while/
I know how a loop works… my problem is how to increment a number [$i] in the subject that’s all. If you don’t know how to do it, just tell it, but do not provide me article to explain how a loop is working.
My problem is the BodyJsonSend
$BodyJsonsend = @”
{
“message”: {
“subject”: “Test Mail $($i)”,
“body”: {
“contentType”: “HTML”,
“content”: “This Mail is sent via Microsoft
GRAPH
API
”
},
“toRecipients”: [
{
“emailAddress”: {
“address”: “email@domain.com”
}
}
]
},
“saveToSentItems”: “false”
}
“@
For($i = 0;$i -lt 10;$i++)
{
Invoke-RestMethod -Method POST -Uri $URLsend -Headers $headers -Body $BodyJsonsend
}
Hi, if you know how to loop, you should be able to send it.
I would recommend creating a Function to send the Mail and pass the Subject to the Function
In your example, add the $BodyJsonsend in the for Loop, then it should work.
hi, i am getting an Error while sending Mail with Graph API. IT says Message ist empty, but when i Copy my requests top Graph Explorer IT will Work fine.
Hi, letβs see your code!
Sorry for the long code, but hope you can find this error:
{“error”:{“code”:”ErrorInvalidParameter”,”message”:”The value of the parameter ‘Message’ is empty.”}}
Hi, there is no code
code is written in pl/sql.
Hi,
your code looks very long π I haven’t approved it cause it would break the Page maybe
have you tried it first without the attachment?
also, see this Post to send an attachment with GRAPH APU: https://www.techguy.at/send-mail-with-attachment-powershell-and-microsoft-graph-api/
Hi Michael, thanks so much for posting mine is working as expected. I would like to email some .CSV attachments with it to multiple email addresses. Could you provide the code to add please.
Oh so sorry, I have just seen the post about. let me check out that link and get back to you if need be
Thank you! The first Script I’ve come across that actually works, after spending countless hours trying to achieve this.