This guide uses the client credentials OAuth 2.0 flow — designed for background services and automation scripts that run without user interaction. No user sign-in is required.
Microsoft Entra ID (formerly Azure Active Directory) is the identity platform behind Microsoft 365. To call the Graph API from a script or service, you need an app registration that defines what the application is allowed to do and a client secret that proves its identity.
1. Sign in to the Entra admin center
Open entra.microsoft.com and sign in with a Global Administrator or Application Administrator account.
2. Create a new app registration
Navigate to Identity → Applications → App registrations and click New registration.
Fill in the registration form:
| Field | Value |
|---|---|
Name | A descriptive name for your application (e.g. Proxmox Mail Alerts) |
Supported account types | Accounts in this organizational directory only (single tenant) |
Redirect URI | Leave blank — not needed for client credentials |
Click Register.
3. Note the application identifiers
After registration, you are taken to the app's Overview page. Copy these two values — you will need them for your application's configuration:
| Label in portal | Config variable |
|---|---|
Application (client) ID | GRAPH_CLIENT_ID |
Directory (tenant) ID | GRAPH_TENANT_ID |
4. Add API permissions
Navigate to API permissions in the left sidebar and click Add a permission.
In the panel that opens:
- Select Microsoft Graph
- Select Application permissions (not Delegated)
- Search for
Mail.Sendand check the box - Click Add permissions
Application permissions and Delegated permissions are different. Application permissions run as the app itself (no user context). Delegated permissions require a signed-in user. For background services and scripts, you need Application permissions.
Grant admin consent
After adding the permission, click Grant admin consent for [your org] and confirm. The status column should change to a green checkmark with Granted for [your org].
5. Create a client secret
Navigate to Certificates & secrets in the left sidebar, select the Client secrets tab, and click New client secret.
| Field | Value |
|---|---|
Description | A label to identify this secret (e.g. proxmox-pve1) |
Expires | Choose an expiration period (maximum 24 months) |
Click Add. The secret Value is shown only once — copy it immediately. This is your GRAPH_CLIENT_SECRET.
The secret value is only displayed once. If you navigate away without copying it, you must delete the secret and create a new one. Store it securely.
Record the expiration date and set it as CREDENTIAL_EXPIRES in your application's configuration file. Scripts like our Proxmox and DNF mail handlers will warn you when credentials are within 60 days of expiring.
6. Verify your configuration values
At this point you should have all four values needed for Graph API authentication:
GRAPH_TENANT_ID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
GRAPH_CLIENT_ID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
GRAPH_CLIENT_SECRET=your-secret-value-here
GRAPH_SENDER=alerts@yourdomain.comGRAPH_SENDER is the mailbox the app will send as. This must be a licensed mailbox (or shared mailbox) in your Microsoft 365 tenant. See the hardening section below for restricting which mailboxes the app can impersonate.
7. Test authentication
You can verify the credentials work by requesting an access token from the command line:
curl -s -X POST "https://login.microsoftonline.com/TENANT_ID/oauth2/v2.0/token" \
-d "client_id=CLIENT_ID" \
-d "client_secret=CLIENT_SECRET" \
-d "scope=https://graph.microsoft.com/.default" \
-d "grant_type=client_credentials" | python3 -m json.toolA successful response contains an access_token field. If you see an error, double-check your tenant ID, client ID, and client secret.
8. Recommended hardening
Restrict the sender mailbox
By default, Mail.Send application permission allows the app to send as any mailbox in your tenant. Use an application access policy in Exchange Online to restrict it to a specific mailbox.
In Exchange Online PowerShell:
# Create a mail-enabled security group containing only the allowed sender(s)
New-DistributionGroup -Name "Graph Mail Senders" -Type Security -Members alerts@yourdomain.com
# Create the access policy
New-ApplicationAccessPolicy \
-AppId "YOUR_CLIENT_ID" \
-PolicyScopeGroupId "Graph Mail Senders" \
-AccessRight RestrictAccess \
-Description "Restrict Graph app to alerts mailbox only"Application access policies can take up to 30 minutes to propagate. Test after waiting. If sending fails with an access denied error immediately after policy creation, wait and retry.
Use certificate authentication (optional)
For higher security environments, consider using a certificate credential instead of a client secret. Certificates cannot be accidentally exposed in logs and do not need to be rotated as frequently. Microsoft's documentation covers the certificate credential flow.
Summary
You now have a registered application in Microsoft Entra ID with:
- A client ID and tenant ID for identification
- A client secret for authentication
Mail.Sendapplication permission with admin consent- (Optional) An application access policy restricting the sender mailbox
Use these credentials in any application that needs to send email via the Microsoft Graph API — including our Proxmox email notification and DNF5 automatic email guides.