Sending mails with Graph API in PowerShell

Tanmoy Naiya
5 min readMay 16, 2024

--

Sending mails with Graph API in PowerShell

As Microsoft is promoting Graph API like anything and deprecating other in-build modules now it is the right time to utilize and understand the Graph API more and more. It is undeniable that Graph API is a complex concept than all the in-build modules which we were get used to it but at the same time we have to understand that Graph API is more reliable and can offer you plethora of possiblities which were not possible with the in-build modules.

In this blog we will discuss how we can send mails using Graph API in PowerShell. Graph API is supported in many languages but as PowerShell is the very own language of O365 developers so I am choosing PowerShell here..

Permissions :

To be able to send mail we need below permissions as per the Microsoft documentation. We will be using application permission in this blog.

Mail.Send permission

Get ready with the mandate:

Before you jump into the coding, be sure that your have Mail.Send permission in your application and you have the AppID, TenantID and the clientSecret in oreder to get the token.

Get the token:

Once you have the permission in place now it is time to get the token. We can get the token using the AppID, TenantID and the clientSecret.

If you are unsure of “How to get the token” then you can follow this document.

As we have got our desired token, now we can start preparing other madatory things like recepient list, mail body etc.

Prepare recepientList:

We need to prepare the recipient list as Graph API will accept it in JSON format so we will use PowerShell here to prepare one like below.

    # preparing recipient list
$userslist = 'abc@contoso.com','xyz@contoso.com'
$toAddress = @()
[array]$recipientlist = $userslist.split(",")
foreach($user in $recipientlist){
$toAddress += @{
"emailAddress" = @{
"address" = $user
}
}
}

Prepare the mail body:

We can prepare the mail body as below

        # Setting Subject and Content
$mailSubject = "This is a Test Mail"
$msgContent = "This is a Test mail, Please ignore"

# preparing mail body to be sent
$msgBody = (@{
"message" = @{
"subject" = $mailSubject
"body" = @{
"contentType" = 'Text'
"content" = $msgContent
}
"toRecipients" = $toAddress
}
}) | ConvertTo-JSON -Depth 10

Send the mail:

Finally we have got everything and it is the moment of truth whether we can send the mail or not with all the details we have gathered and prepared so far. We can call the sendMail Graph API as below:

# Set the sender address, this email should be a valid user who has mailbox in the mentioned tenant.
$senderAddress = 'sample-email@contoso.com'
# Construct the mail send URL
$url = "https://graph.microsoft.com/v1.0/users/$($senderAddress)/sendMail"

# Calling the API
Invoke-RestMethod -Method POST -Uri $url -Headers @{Authorization = "Bearer $token"} -Body $msgBody -ContentType 'application/json'

Output:

Once you call the Graph API, it should work as expected like below. You may also get into some error, I have discussed some common errors, read below.

Received mail from Graph API

Full PowerShell Script:

# Change your AppID, TenantID and clientSecret

$AzureADAppClientId = "XXX-XXXX-XXXXXXX"
$AzureADAppClientSecret = "XXX-XXXX-XXXXXXX"
$AzureADTenantId = "XXX-XXXX-XXXXXXX"

# function to get the token
function get_token()
{
# Application (client) ID, tenant ID and secret
$clientId = $AzureADAppClientId
$tenantId = $AzureADTenantId
$clientSecret = $AzureADAppClientSecret


# Construct URI
$uri = "https://login.microsoftonline.com/$tenantId/oauth2/v2.0/token"
# Construct Body
$body = @{
client_id = $clientId
scope = "https://graph.microsoft.com/.default"
client_secret = $clientSecret
grant_type = "client_credentials"
}
# Get OAuth 2.0 Token
$tokenRequest = Invoke-WebRequest -Method Post -Uri $uri -ContentType "application/x-www-form-urlencoded" -Body $body -UseBasicParsing
# Access Token
$token = ($tokenRequest.Content | ConvertFrom-Json).access_token
# returning the token
return $token
}

# Getting the token

$token = get_token

# preparing recipient list
$userslist = 'abc@contoso.com','xyz@contoso.com'
$toAddress = @()
[array]$recipientlist = $userslist.split(",")
foreach($user in $recipientlist){
$toAddress += @{
"emailAddress" = @{
"address" = $user
}
}
}

# Setting Subject and Content
$mailSubject = "This is a Test Mail"
$msgContent = "This is a Test mail, Please ignore"

# preparing mail body to be sent
$msgBody = (@{
"message" = @{
"subject" = $mailSubject
"body" = @{
"contentType" = 'Text'
"content" = $msgContent
}
"toRecipients" = $toAddress
}
}) | ConvertTo-JSON -Depth 10


# Set the sender address, this email should be a valid user who has mailbox in the mentioned tenant.
$senderAddress = 'sample-email@contoso.com'
# Construct the mail send URL
$url = "https://graph.microsoft.com/v1.0/users/$($senderAddress)/sendMail"

# Calling the API
Invoke-RestMethod -Method POST -Uri $url -Headers @{Authorization = "Bearer $token"} -Body $msgBody -ContentType 'application/json'

Common Errors:

Even though we expect that we have covered everything and should get the expected result, still sometimes we stumble into some errors, below are athe common errors that you might face,

Error 1: The remote server returned an error: (403) Forbidden.

Invoke-RestMethod : The remote server returned an error: (403) Forbidden.
At line:73 char:1
+ Invoke-RestMethod -Method POST -Uri $url -Headers @{Authorization = " ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:Htt
pWebRequest) [Invoke-RestMethod], WebException
+ FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShe
ll.Commands.InvokeRestMethodCommand

This error can occur due to several reason,

Reason 1: You might not have required permision in your application to send mails. Please check that you have proper permission in your application and that is granted from the Tenant Admin.

Reason 2: Your token might be expired by the time you are calling the API, I that case please renew your token and try again.

Reason 3: Your organization might enabled the application policy to restric the Graph API usage , in that case you must find out the mail-enabled security group by which this application is controled and add your sender to the group and try again, It might take some time to be available depending upon the size of the group. Please remember that this only works with 50K users in the group, even though you can add users more that 50K still the Application policy will not work on more than 50K users, If you end up in such scenario then you you have to create another mail-anabled security group and apply the same application policy on the new group.

Thanks you for being here, Please write down your comments if you have any..

--

--

Tanmoy Naiya

Tanmoy is an M365 and PowerShell expert having more than 9 years of industrial experience. He helped organizations extensively with M365 solutions & automations