Azure: Sending Email via Azure Communication Services using Managed Identity from an Azure VM.
This article explains how to securely send emails using Azure Communication Services (ACS) by leveraging Managed Identity from within an Azure Virtual Machine. This setup avoids using connection strings or secrets, relying instead on Azure Instance Metadata Service (IMDS) to retrieve access tokens.
Be aware that the Managed Identity only works on Azure. If you want to use the Azure Communication Service outside of Azure
Azure VM (with Managed Identity) is a 6 step process.
1. Call IMDS (169.254.169.254)
2. Get OAuth2 token for ACS
3. Use token in Authorization header
4. POST email payload to ACS endpoint
5. ACS authenticates token and sender domain
6. Email delivered to recipient mailbox
Step-by-Step Implementation
1. Create Azure Communication Service
In Azure Portal, search for “Communication Services” and create a new resource. Enable Email capability and provision a sending domain.
2. Configure Domain Verification (SPF, DKIM)
You’ll receive DNS records (SPF, DKIM) to configure on your domain registrar.
This step validates the sender domain and prevents spoofing.
3. Create a User-Assigned Managed Identity
az identity create --name ManagedIdentityName --resource-group ResouceGroupName4. Assign Managed Identity to the Azure VM & to Azure Communication Service.
5. Get Access Token from Instance Metadata Service (IMDS)
IMDS is accessible only inside the VM and provides tokens for Managed Identity:
response=$(curl -H "Metadata: true" \
"http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://communication.azure.com&client_id=<client-id>")
access_token=$(echo "$response" | jq -r '.access_token')6. Send Email Using ACS Endpoint
Now we need Use this access_token in the Authorization header to send an email via REST:
curl -X POST "https://<your-acs-resource>.communication.azure.com/emails:send?api-version=2023-03-31" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $access_token" \
-d '{
"senderAddress": "DoNotReply@domain.com",
"recipients": {
"to": [{"address": "prashanth.kumar@domain.com"}]
},
"content": {
"subject": "Test Email-04072025",
"plainText": "Hello world via email on 7th Apr 2025.",
"html": "<html><body><h1>Hello world via email on 7th Apr 2025.</h1></body></html>"
}
}'7. ACS Processes Email Request
ACS authenticates the bearer token.
It ensures the sender domain is verified.
8. ACS Authenticates Against the Domain
If SPF and DKIM records are valid and match, the request is accepted.
You can monitor email send status via ACS logs.
9. Email is Delivered to Recipient Mailbox
The email appears in the recipient’s inbox with proper domain alignment and authentication (SPF/DKIM passed).
Logs:
you can check logs via Log Analytics
Similar capability can be used by using Azure SPN with Secret, you just need to add grant type as client_credentials and then add client_id and Secret to generate new bearer token.
response=$(curl --location 'https://login.microsoftonline.com/TenantID/oauth2/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'grant_type=client_credentials' \
--data-urlencode 'client_id=xxxxxx' \
--data-urlencode 'client_secret=xxxxxx' \
--data-urlencode 'resource=https://communication.azure.com')
access_token=$(echo $response | jq -r '.access_token')
echo $access_tokenAs our intention is to Minimize the usage of SPN and create more secure boundary.
Reference Links:
Azure Instance Metadata Service for virtual machines — Azure Virtual Machines | Microsoft Learn