Are you still using Send-MailMessage to Send Mail In PowerShell? You need to stop. The command needs SMTPAuth enabled for your organization. If you are looking for ways to security harden you M365 tenant, disabling this feature is a good way to go. But you still need to send email in PowerShell, right? I will show you in three steps.
Step One – Send Mail In PowerShell (Set up an App is Azure)
The first step involves setting up an App registration that will let you send mail. Create an App Registration in Azure Ad by going to Azure AD / Application / App Registrations and creating one:
Click register. Now that you have you App for sending mail registered, go to API Permission and give the App permissions to Send mail as any user.
Please don’t forget to click on “Grant admin consent for” on the app.
To finish our Azure App, we need to configure the Authentication Method to use as a Client Secret. Navigate to “Certificates & secrets” and select “New client secret.”
Enter a Name and Expire Date. Not this date because when it expires, your scripts that use this app will stop working and you will have to renew it.
NOTE:
When you click “Add”, the Secret is created and you have a unique chance to get the Client Secret. This is a one-time shot, so copy the Secret, before refreshing the Page or navigating to a different Section.
Now on to step two.
Step Two – Send Mail In PowerShell (Set Security Group in Exchange Online)
Once you are done creating an App, you need to set and application policy that will only let you use only the email address you specify in your organization to send mail as:
Connect to Exchange-Online and then run the following command in PowerShell:
- Connect to Exchange Online with the ExchangeOnlineManagement PowerShell module Connect-ExchangeOnline
- Create a mail enabled security group which contains all the accounts you want to send mails from $restrictedGroup = New-DistributionGroup -Name “Mail service accounts” -Type “Security” -Members @(“[email protected]”)
- Optionally hide the group from the address list Set-DistributionGroup -Identity $restrictedGroup.Identity -HiddenFromAddressListsEnabled $true
- Create the application access policy to only allow sending the app mails for the specified distribution group
- Run this last set of commands:
$params = @{
AccessRight = “RestrictAccess”
AppId = “1f5ffbea-f13f-4f1a-af63-258ce4344daf”
PolicyScopeGroupId = $restrictedGroup.PrimarySmtpAddress
Description = “Restrict app permissions to only allow access to service account”
}
New-ApplicationAccessPolicy @params
Once this group is created you can go to into in admin.microsoft.com (Admin portal) and Navigating to Users / Teams & Groups / Mail Enabled Security Groups and making changes as necessary:
When you send mail using MS Graph, only the email address list above will be the only one able to send as.
Step Three – Send Mail In PowerShell (Use MS Graph in PowerShell)
In order to send mail in this new set up, you need to take note of three pieces of information from your app registration:
- Tenant ID – you can get it by looking here
- Client Secret (NOTE:) from above
- App (Client ID) – you need to got to the listing of your app registration and you App (Client ID will be listed here (See below)
Then, use this script to send your mail:
#Declare Parameters
$clientID = “your ID from App Registration”
$clientSecret = “your client secret from App Registration”
$tenantID = “your tenant ID”
#Run Script
$MailSender = “[email protected]”
#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": "[email protected]"
}
}
]
},
"saveToSentItems": "false"
}
“@
Invoke-RestMethod -Method POST -Uri $URLsend -Headers $headers -Body $BodyJsonsend
Conclusion
It seems like a lot of work but this is just to set it up. Now that you have a good base, whenever you need to send a mail for whatever reason in PowerShell all you have to do is make sure the required email sender address is in the Mail Enabled Security Group and in the variable in the script and you are good to go. A good example is notifying users that they are using external forwarding!
Happy IT’ing
Dan