How to Send Email Using Microsoft Graph API and PowerShell?

If you have some form of PowerShell automation in your infrastructure, like mailbox or SharePoint site monitoring, you probably send emails via PowerShell. If you’re still using the Send-MailMessage cmdlet to do authenticated SMTP relay with Office 365, sad to say, the future looks bleak.

Although The Exchange Team said in their May 2022 update that “We are not turning off SMTP AUTH”, the fact remains that using basic authentication is unsecured. Moving forward, you must consider switching to a more secure email, like Microsoft Graph API.

Honestly, switching to Microsoft Graph API to send mail can be daunting at first because you’re technically leaving behind the usual SMTP and moving to REST API calls via HTTPS with JSON. This article will help you get started on that journey.

Requirements

To send mail using Graph API, you must have access to the following.

  • A Microsoft 365 Enterprise tenant with Exchange Online.
  • Global administrator access to the tenant.
  • An Exchange Online mailbox to use as the email sender ID. A Shared Mailbox without a license should suffice.
  • The Microsoft Graph PowerShell SDK must be installed on your computer.
  • Your computer must have Windows PowerShell 5.1 or PowerShell 7+.

Register the Mailer App in Azure AD

Using the Graph API send mail function, you must first create an application in Azure AD, whose identity you’ll use to authenticate and authorize the send email action.

The application will have the following components.

  • Application ID (aka. Client ID)
  • Client Certificate
  • Microsoft Graph API Permission (Mail.Send)

Note. You’ll only need to register the application once, which will be reusable.

Generate a Self-Signed Certificate

Authenticating your app in Azure AD requires a certificate. This certificate can be from a known certificate provider, such as Digicert and Verisign, or self-generated.

You do not have to pay for the SSL certificate just for this purpose, so in this example, you’ll generate a self-signed certificate instead.

First, open PowerShell as an administrator and run the following code. This code generates and installs a self-signed certificate in the Cert:\CurrentUser\My certificate store with a validity of five years.

# Generate a self-signed certificate
$certSplat = @{
Subject = 'PSGraphMailApp'
NotBefore = ((Get-Date).AddDays(-1))
NotAfter = ((Get-Date).AddYears(5))
CertStoreLocation = "Cert:\CurrentUser\My"
Provider = "Microsoft Enhanced RSA and AES Cryptographic Provider"
HashAlgorithm = "SHA256"
}
$selfSignedCertificate = New-SelfSignedCertificate @certSplat

Confirm that the certificate was created by displaying its properties, as shown below.

# Display the certificate details
$selfSignedCertificate | Format-List PSParentPath, ThumbPrint, Subject, NotAfter

Don’t forget to copy the Thumbprint value because you’ll need this during the authentication process.

send email using microsoft graph api

Finally, export the certificate without its public key to C:\Cert\PSGraphMailApp.cer. You will upload this certificate file to Azure AD later.

# Create the directory to save the certificate
mkdir C:\cert -Force
# Export the public certificate (no private key)
Export-Certificate -Cert $selfSignedCertificate -FilePath 'C:\Cert\PSGraphMailApp.cer'

microsoft graph api send email

Create a New App

Follow these steps to register the app.

graph api send email

On the Register an application page:

  • Enter PSGraphMailApp as the name of the application.
  • Choose Accounts in this organizational directory only.
  • Click Register.
    send email graph api
  • Once the new application is registered, copy the values of Application (client) ID and Directory (tenant) ID. You’ll need these values and the certificate thumbprint you copied earlier for authentication.ms graph api send email

Upload the Certificate

Time to add the certificate credential to the app. Remember that the certificate you are uploading is the same one you created earlier.

  • Click Certificates & secrets → Go to Certificates → Click on Upload certificate.
    graph api to send email

On the Upload certificate fly-out page that appears:

  • Click the browse button → Locate the certificate file you exported earlier → Click Open to upload the certificate.
    send email with graph api
  • Click Add to finish adding the certificate credential.
    send email using graph api
  • You should now see the certificate in the list.

    Note. The Thumbprint value should be the same one you copied earlier when you created the self-signed certificate.

    send mail using graph api

Add Permissions and Grant Consent

Now you need to add the Microsoft Graph API to send mail permission to the app.

  • Click API permissionsAdd a permission.
    microsoft graph api to send email
  • Next, click Microsoft Graph under the Microsoft APIs tab.
    send email using ms graph api
  • Select Application Permissions → Search for and check the Mail.Send permission → Click Add permissions.
    send email ms graph api
  • Once the permission is added, click Grant admin consent for → Yes.
    ms graph api to send email

Connect to Microsoft Graph

Before issuing commands to Microsoft Graph, you must authenticate using your application and certificate credentials.

Run the Connect-MgGraph cmdlet to connect to Microsoft Graph. replace the -ClientId, -TenantID, and -CertificateThumbprint values with your own.

# Authenticate and connect to Microsoft Graph
Connect-MgGraph `
-ClientId 'f39202b0-b720-4e88-b1e4-690c92d35705' `
-TenantId 'd397a279-89ca-42f6-9c8b-d481982c652f' `
-CertificateThumbprint '243B29B4DEAB5758D2C2ACB96A0C3A3211BE2784'

microsoft graph api send email example

That’s it! You’ve authentications with Microsoft Graph in one command. But for good measure, run the below command to inspect your application’s permissions.

Get-MgContext

As you can see below, the current authorization only has Mail.Send permission, which is what we added to the application.

graph api send email with attachment

Send Mail Using Graph API PowerShell

You now have the necessary items to send emails via Microsoft Graph API. At this point, you should have the Client ID, Tenant ID, and Certificate Thumbprint that you’ll use to authenticate with the Azure AD application.

Instead of manually constructing the REST API calls to authenticate and send emails, the following steps will use the cmdlets included in the Microsoft Graph PowerShell SDK, specifically the Send-MgUserMail.

Compose and Send a Plain Text Email

The minimum details that you need to supply in a message when sending an email are the Subject, Body, and one To recipient. You must compose this payload in a nested hashtable format; below is an example.

$mailParams = @{
Message = @{
Subject = "Server Disk Space on COMPUTER_A is below the 30% Threshold."
Body = @{
ContentType = "Text"
Content = "The remaining available diskspace on [C:] is now at 5GB. Please do something."
}
ToRecipients = @(
@{
EmailAddress = @{
Address = "itops@lzex.ga"
}
}
)
}
}

To send this message, you’ll use the Send-MgUserMail cmdlet. Specify the sender address to the -UserId parameter and the $mailParams variable to the -BodyParameter parameter.

Send-MgUserMail -UserId 'mailer365@lzex.ga' -BodyParameter $mailParams

No output means all good.

graph api send email with attachment example

The screenshot below shows that the email was sent to one recipient in the To field, which is expected.

graph api send email example

Add Recipients

What if you need to add more recipients? And not just to the To field but to the CC and possibly the BCC fields too?

To add additional To recipients, create another hashtable entry and insert it into the ToRecipients = @() block. For example, the below code is one email address recipient entry.

@{
EmailAddress = @{
Address = "monitoring@lzex.ga"
}
}

How about CC and BCC? Insert the CcRecipients and BccRecipients entries in one level inside the Message block.

CcRecipients = @(
@{
EmailAddress = @{
Address = "june@lzex.ga"
}
}
)
BccRecipients = @(
@{
EmailAddress = @{
Address = "supremeleader@lzex.ga"
}
}
)

The email object code would now look like the image below.

microsoft graph api send email example

And when you resend the email, you’ll confirm that the new recipients you added also received the email.

send email using graph api file with attachement

Add Attachments

Attaching files to emails is common practice, and Microsoft Graph API lets you attach files to a message. But you are not attaching the files directly. Instead, you must convert the file into a Base64 string. That Base64 string is what you’ll include in the message object.

For example, to convert the file C:\itbro\LoremIpsum.txt into a Base64 string:

# Windows PowerShell 5.1
[convert]::ToBase64String((Get-Content 'C:\itbro\LoremIpsum.txt' -Raw -Encoding Byte))
# PowerShell 6.0+
[convert]::ToBase64String((Get-Content 'C:\itbro\LoremIpsum.txt' -AsByteStream))

First, insert the Attachments=@() block anywhere inside the Message block. You’ll specify the attachment details inside the Attachment block, including the attachment name as it appears in the email and the Base64 content.

The example below inserts the file C:\itbro\LoremIpsum.txt attachment into the message.

$mailParams = @{
Message = @{
Subject = "Server Disk Space on COMPUTER_A is below the 30% Threshold."
Body = @{
ContentType = "Text"
Content = "The remaining available disk space on [C:] is now at 5GB. Please do something."
}
ToRecipients = @(
@{
EmailAddress = @{
Address = "itops@lzex.ga"
}
}
)
Attachments = @(
@{
"@odata.type" = "#microsoft.graph.fileAttachment"
"name" = "LoremIpsum.txt"
"contentBytes" = $(
[convert]::ToBase64String((Get-Content 'C:\itbro\LoremIpsum.txt' -AsByteStream))
)
}
)
}
}

Now let’s send the email again with the attachment.

Send-MgUserMail -UserId 'mailer365@lzex.ga' -BodyParameter $mailParams

As you can see below, the email was received with a file attachment named LoremIpsum.txt.

send email using microsoft graph api file with attachement

Open the attachment to confirm that it is intact.

send email using microsoft graph api attachement

Compose and Send an HTML Email

You can also send HTML messages via Microsoft Graph API if you want more control over your email’s appearance.

First, compose your HTML email body and save it in the $htmlBody variable.

$htmlBody = @'
<html>
<body>
<H2>Server Disk Space on COMPUTER_A is below the 30% Threshold.</H2>
<p><i>The remaining available disk space on <u>[C:] is now at 5GB</u>. Please do something.</i></p>
</body>
</html>
'@

In your email object, change the following Body values.

  • ContentType = “text” to ContentType = “html”.
  • Content = “The remaining available disk space on [C:] is now at 5GB. Please do something” to Content = $htmlBody.
$mailParams = @{
Message = @{
Subject = "Server Disk Space on COMPUTER_A is below the 30% Threshold."
Body = @{
ContentType = "HTML"
Content = $htmlBody
}
ToRecipients = @(
@{
EmailAddress = @{
Address = "itops@lzex.ga"
}
}
)
}
}

Send-MgUserMail -UserId 'mailer365@lzex.ga' -BodyParameter $mailParams

The email body now shows the HTML format message.

send email using microsoft graph api html

You’ve reached the end of this post, and hopefully, you’ve learned enough to help you get started with sending emails using Microsoft Graph API and PowerShell.

Cyril Kardashevsky

Leave a Reply

Your email address will not be published.