Send-MailMessage is obsolete and no longer supported. Microsoft says this cmdlet does not guarantee a secure connection to SMTP servers. We will use Send-MgUserMail.
This tutorial takes you through using Send-MgUserMail to send emails instead of Send-MailMessage
Table of Contents
- Using Send-MailMessage
- Using Send-MgUserMail as a Replacement For Send-MailMessage
- Send-MgUserMail Basics
- Send-MgUserMail BodyParameter Parameters
- Send-MgUserMail To Send a Basic Message
- Send Email Messages including CC, Bcc.
- Send Email Message with Attachment.
- Send Email With High Priority, Follow-up Flag, Delivery Report, and Read Report
- Send-MgUserMail with Mentions
- Alternative Solution
- Final Though
Using Send-MailMessage
When you try to use the Send-MailMessage cmdlet, you get the following warning.
WARNING: The command ‘Send-MailMessage’ is obsolete. This cmdlet does not guarantee secure connections to SMTP servers. While there is no immediate replacement available in PowerShell, we recommend you do not use Send-MailMessage at this time. See https://aka.ms/SendMailMessage for more information.
Send-MailMessage doesn’t support modern authentication. Suppose you are using Send-MailMessage
to send emails through office 365. In that case, you need to consider using a replacement cmdlet such as Send-MgUserMail
, as by October 1st, 2022, basic authentication won’t work anymore. But if you are using the Send-MailMessage to send emails through your local SMTP server, it’s still OK to use the cmdlet, but consider moving to a supported method.
Using Send-MgUserMail as a Replacement For Send-MailMessage
This tutorial takes you through the required parameter to build all the required parameters to send emails using Send-MgUserMail with parameters to set the priority level mentioned, BCC, CC, Flag, and more.
If you are new to graphs, take a look at Connecting and Understanding Microsoft Graph API Using PowerShell also, you can check the Connect to Office 365 Using Graph API and PowerShell for more information about how to configure Delegate and Application authentication.
The first thing is to know what are the required scope to use
(Find-MgGraphCommand -Command Send-MgUserMail -ApiVersion V1.0).Permissions
The results list the following putout
Name IsAdmin Description FullDescription
---- ------- ----------- ---------------
Mail.Send False Send mail as you Allows the app to send mail as you.
So the only permission needed is Mail.Send
Send-MgUserMail Basics
Unlike the Send-MailMessage
, the Send-MgUserMail
requires a more complex parameter structure. But no worry, all is explained here. But on the other hand, the Send-MgUserMail gives you access to the entire SendMail endpoint, which supports all the message parameters, such as Follow-up Flag, Importance, Reply to, mentions, Request read and delivery report and much much more features.
The endpoint the Send-MgUserMail uses is:
[POST] https://graph.microsoft.com/v1.0/users/USER_UPN/microsoft.graph.sendMail
We don’t need this information while writing the script, but it’s good to know the endpoints as it helps troubleshoot unexpected issues.
Send-MgUserMail
requires a BodyParameter
parameter that includes all the mail parameter settings such as To, CC, Bcc.. etc.
Here are the parameters explained.
Not all the parameters are mandatory.
Send-MgUserMail BodyParameter Parameters
The Send-MgUserMail parameters are simple, and the most important one is the BodyParameter. The BodyParameter is a structure of hashtables and arrays, each one representing a parameter.
The cmdlet looks like the following.
Send-MgUserMail -UserId 'Sender@EmailAddress.com' -BodyParameter $Params
The $Param variable is a hashtable that contains all the message parameter details. Let’s start by explaining the details and later on see the complete code.
- Message: Hashtable contains a list of parameters related to the email message. The Message may include the following parameters.
- [Optional][String]Subject: The message subject.
- [Optional][Bool]isDeliveryReceiptRequested: Request Delivery Report, the sender receive a message reporting the delivery status,
- [Optional][Bool]isReadReceiptRequested: Request Recipient Read Report
- [Optional][String]Importance: Can hold Low, Normal, High.
- [Optional][Hashtable]Body: The message body content and can hold the following keys and values
- [String]ContentType: HTML for rich text content or Text for plain text content.
- [String]Content: For the actual body content, I like to use here-string for short content.
- [Optional][Array]ToRecipients: Contain a list of hashtables. Each hashtable represents a recipient with the following keys and values. You can add multiple EmailAddress hashtables for more the one recipient.
- [Hashtable]EmailAddress
- Address=”To@Address.com”
- [Hashtable]EmailAddress
- [Optional][Array]CcRecipients: Similar to ToRecipients
- [Optional][Array]BccRecipients: Similar to ToRecipients
- [Optional][Array][BETA]Mentions: Include a list of hashtables for users to mention. This appears in the user outlook as @. The Mentions contain the following keys and values.
- [Hashtable]Mentioned: include the Name key for the mentioned user
- Name=”Faris Malaeb”
- Address=”Myemail@PowerShellCenter.com”
- [Hashtable]Mentioned: include the Name key for the mentioned user
- [Optional][Array]Attachments: a list of attachments to include in the email, each attachment represented in a hashtable. that contain the following
- “@odata.type” = “#microsoft.graph.fileAttachment”: Object Type, Use it as is
- [String]Name: Path for the attachment
- [String]ContentType: The MIME type of the attached file, for example, “text/plain”
- [Base64String]ContentBytes: The attachment content should be converted to Base64String. You can use the following line to convert the file [Convert]::ToBase64String([IO.File]::ReadAllBytes($AttachmentPath))
- [Optional][Hashtable]Flag: Contain the follow-up flag status. Should the message has a follow-up flag or not? It contains the following Key and values.
- flagStatus=”flagged”
- [Optional][Boolean]SaveToSentItems: If yes, the sent message will be stored in the user sent items.
The ToRecipients, CcRecipients and BccRecipients are optional, but you must use one. For example, use the BccRecipients and skip the others. But aleast one recipient should be valid
It might not look as friendly as Send-MailMessage, but just go through the code, and you will find it easy.
Here is the complete code.
Import-Module Microsoft.Graph.Users.Actions
$AttachmentPath="C:\MyFile.txt"
$MyMessageContent=@'
<Strong> This is a Test Message</Strong><br>
I Hope you like it
'@
$MessageAttachement = [Convert]::ToBase64String([IO.File]::ReadAllBytes($AttachmentPath))
$params = @{
Message = @{
Subject = "Lets Use Graph"
importance = "Low" #"High"
isDeliveryReceiptRequested = "True"
isReadReceiptRequested = "True"
Body = @{
ContentType = "html"
Content = $MyMessageContent
}
ToRecipients = @(
@{
EmailAddress = @{
Address = "User1@Email.com"
}
}
@{
EmailAddress = @{
Address = "User2@Email.com"
}
}
)
CcRecipients = @(
@{
EmailAddress = @{
Address = "User3@Email.com"
}
}
)
BccRecipients = @(
@{
EmailAddress = @{
Address = "admin@email.com"
}
}
)
Mentions = @( #BETA ONLY
@{
Mentioned = @{
Name = "Faris Malaeb"
Address = "farismalaeb@powershellcenter.com"
}
}
)
Attachments = @(
@{
"@odata.type" = "#microsoft.graph.fileAttachment"
Name = $AttachmentPath
ContentType = "text/plain"
ContentBytes = $MessageAttachement
}
)
Flag = @{
flagStatus="flagged"
}
}
SaveToSentItems = "false"
}
Connect-MgGraph -Scopes Mail.Read
Select-MgProfile -Name beta
Send-MgUserMail -UserId 'Sender@EmailAddress.com' -BodyParameter $params
The result looks like the following.
Send-MgUserMail To Send a Basic Message
$MyMessageContent=@'
<Strong> This is a Test Message</Strong><br>
I Hope you like it
'@
$params = @{
Message = @{
Subject = "Lets Use Graph"
Body = @{
ContentType = "html"
Content = $MyMessageContent
}
ToRecipients = @(
@{
EmailAddress = @{
Address = "ToUser@Domain.com"
}
}
)
}
}
Import-Module Microsoft.Graph.Users.Actions
Connect-MgGraph -Scopes Mail.Read
Send-MgUserMail -UserId 'Sender@PowerShellCenter.com' -BodyParameter $params
Send Email Messages including CC, Bcc.
$MyMessageContent=@'
<Strong> This is a Test Message</Strong><br>
I Hope you like it
'@
$params = @{
Message = @{
Subject = "Lets Use Graph"
Body = @{
ContentType = "html"
Content = $MyMessageContent
}
ToRecipients = @(
@{
EmailAddress = @{
Address = "User1@powershellcenter.com"
}
}
)
CcRecipients = @(
@{
EmailAddress = @{
Address = "user2@powershellcenter.com"
}
}
)
BccRecipients = @(
@{
EmailAddress = @{
Address = "Bcc@powerShellcenter.com"
}
}
)
}
SaveToSentItems = "false"
}
Import-Module Microsoft.Graph.Users.Actions
Connect-MgGraph -Scopes Mail.Read
Send-MgUserMail -UserId 'Sender@powershellcenter.com' -BodyParameter $params
Send Email Message with Attachment.
$AttachmentPath="C:\MyFile.txt"
$MyMessageContent=@'
<Strong> This is a Test Message</Strong><br>
I Hope you like it
'@
$MessageAttachement = [Convert]::ToBase64String([IO.File]::ReadAllBytes($AttachmentPath))
$params = @{
Message = @{
Subject = "Lets Use Graph"
Body = @{
ContentType = "html"
Content = $MyMessageContent
}
ToRecipients = @(
@{
EmailAddress = @{
Address = "ToUser@Domain.com"
}
}
)
Attachments = @(
@{
"@odata.type" = "#microsoft.graph.fileAttachment"
Name = $AttachmentPath
ContentType = "text/plain"
ContentBytes = $MessageAttachement
}
)
}
SaveToSentItems = "false"
}
Import-Module Microsoft.Graph.Users.Actions
Connect-MgGraph -Scopes Mail.Read
Send-MgUserMail -UserId 'Sender@powershellcenter.com' -BodyParameter $params
Send Email With High Priority, Follow-up Flag, Delivery Report, and Read Report
$MyMessageContent=@'
<Strong> This is a Test Message</Strong><br>
I Hope you like it
'@
$params = @{
Message = @{
Subject = "Lets Use Graph"
importance = "High"
isDeliveryReceiptRequested = "True"
isReadReceiptRequested = "True"
Body = @{
ContentType = "html"
Content = $MyMessageContent
}
ToRecipients = @(
@{
EmailAddress = @{
Address = "TestUser@Domain.com"
}
}
)
Flag = @{
flagStatus="flagged"
}
}
SaveToSentItems = "false"
}
Import-Module Microsoft.Graph.Users.Actions
Connect-MgGraph -Scopes Mail.Read
Send-MgUserMail -UserId 'faris@powershellcenter.com' -BodyParameter $params
Send-MgUserMail with Mentions
$MyMessageContent=@'
<Strong> This is a Test Message</Strong><br>
I Hope you like it
'@
$params = @{
Message = @{
Subject = "Lets Use Graph"
Body = @{
ContentType = "html"
Content = $MyMessageContent
}
ToRecipients = @(
@{
EmailAddress = @{
Address = "ToUser@Domain.com"
}
}
)
Mentions = @( #BETA ONLY
@{
Mentioned = @{
Name = "Faris Malaeb"
Address = "faris@powershellcenter.com"
}
}
)
}
SaveToSentItems = "false"
}
Import-Module Microsoft.Graph.Users.Actions
Connect-MgGraph -Scopes Mail.Read
Select-MgProfile -Name beta
Send-MgUserMail -UserId 'faris@powershellcenter.com' -BodyParameter $params
Alternative Solution
I wrote another PowerShell script to simplify the process. The Send-GraphMail
can build everything for you and send the email if you want or just return the JSON structure to your script to use elsewhere.
If you don’t want to go through all these parameters, then take a look at PowerShell Script to Simplify Send-MgUserMail post.
Final Though
I hope this clarifies why to use the Send-MgUserMail instead of Send-MailMessage. the number of supported parameters and options is way more advanced than the Send-MailMessage and supports modern authentication. So, get ready to update your script.
If you want to learn more on how to replace the current cmdlet you have with a Graph API cmdlet, take a look at Migrate Your Script from AzureAD or MSOnline to Graph API
Kindly rate this post if you like it 🙂
So how do you supply credentials if this is a scheduled task running on a service account?
In Graph and for automation and background task processing, you need to register and AAD Application.
Follow this post for a full description of how to do it.
https://www.powershellcenter.com/2022/08/14/connect-office-365-powershell/#Assigning_Permission_For_the_Registered_app