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

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”
    • [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”
    • [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.

Email Message

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
Email Result
Email Result

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
An email with Bcc and CC

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
Email with attachment

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
Email sent

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
Email Result

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 🙂

4.8/5 - (13 votes)