Skip to main content

Microsoft Graph API Mail Server Setup

Rezolve's mail-ticket-service turns inbound email into tickets. To read the mailbox it signs in as an application rather than as a person, using the OAuth 2.0 client credentials flow. This guide covers Steps 1 to 5 — everything your Microsoft 365 / Azure administrator does before handing the values over to Rezolve.

Because the app signs in as itself:

  • No user password is stored, and a password change never breaks the integration.
  • Multi-factor authentication does not apply, because there is no interactive sign-in to challenge.
  • No IMAP host, port or refresh token is involved.
ItemDetail
AudienceYour Microsoft 365 / Azure administrator. No Rezolve involvement is needed until Step 5.
OutcomeRezolve reads one named mailbox through Microsoft Graph — no user password, no MFA prompt, no IMAP.
Time requiredAbout 30 minutes of configuration, plus up to 30 minutes for policy propagation.
Privileges neededGlobal Administrator, or Application Administrator plus Exchange Administrator.
One trade-off to be aware of

The Graph permission the app needs, Mail.ReadWrite, is granted tenant-wide. Step 4 confines it to the mailbox you choose. Step 4 is mandatory — the setup is not safe to leave half-finished.

Setup at a glance: four actions in Microsoft Entra ID, three in Exchange, then the handover to Rezolve

Before you start

  • Administrative access to Microsoft Entra ID, with the ability to register an application and grant tenant-wide admin consent.
  • Exchange Administrator or Global Administrator rights, to create a mail-enabled security group and the access policy.
  • The mailbox must be hosted on Microsoft 365 / Exchange Online. On-premises Exchange is not supported by Graph.
Shared mailboxes are fine

A shared mailbox is a normal Microsoft 365 mailbox, so it works exactly like a licensed user mailbox here. It still has to be added to the security group in Step 4.

Step 1. Register an application

This creates the identity Rezolve will sign in as. It takes about five minutes.

  1. Sign in to portal.azure.com as an administrator.
  2. Go to Microsoft Entra ID (Azure Active Directory) → App registrations+ New registration.
  3. Give it a descriptive name, for example Rezolve Mail Reader – <Client Name>.
  4. For Supported account types, choose Accounts in this organizational directory only (single tenant).
  5. Leave Redirect URI blank, then click Register.

Register an application form with name, single tenant selected, and no redirect URI

Record two identifiers

When registration completes you land on the app's Overview page. Two values there are needed later — copy them with the copy icon rather than retyping them, because a single mistyped character in a GUID produces an authentication failure that is tedious to trace.

Application (client) ID and Directory (tenant) ID on the app Overview page

Portal fieldRezolve configuration fieldNeeded in
Application (client) IDclientId / client_idStep 4 and Step 5
Directory (tenant) IDazureDirId / azure_dir_idStep 5

Step 2. Create a client secret

The secret is the application's password. Rezolve uses it, together with the client ID, to obtain an access token.

  1. In the app registration, open Certificates & secrets.
  2. Click + New client secret.
  3. Enter a description, for example Rezolve Mail Reader, and choose an expiry. 24 months is recommended.
  4. Click Add, then copy the Value immediately.

Client secrets list with the Value column highlighted alongside the Secret ID column

The single most common failure in this setup

Azure displays the secret Value only on this page, only once. As soon as you navigate away it is masked permanently and the only remedy is to create a new secret.

Copying the Secret ID instead of the Value produces the error AADSTS7000215: Invalid client secret provided when Rezolve tries to acquire a token. If you see that error, the value was almost certainly the wrong column.

Note the expiry date as well. Mail collection stops the day the secret expires, so it is worth putting a renewal reminder in the calendar a month ahead.

Step 3. Grant Microsoft Graph API permissions

The app now exists but can do nothing. This step gives it exactly one Graph permission.

  1. In the app registration, open API permissions.
  2. Click + Add a permissionMicrosoft GraphApplication permissions.
  3. Search for Mail.ReadWrite, tick it, and click Add permissions.
  4. Back on the API permissions page, click Grant admin consent for <Organization> and confirm.

Request API permissions panel with Application permissions chosen and Mail.ReadWrite ticked

Application permissions, not delegated

Delegated permissions act on behalf of a signed-in user and are subject to MFA and password changes — which is exactly what this setup exists to avoid. If the Type column later reads Delegated, the wrong tile was chosen and the permission needs to be removed and re-added.

After granting consent, confirm the result on the API permissions page. Type must read Application, Status must show the green tick, and Mail.ReadWrite should be the only Graph permission listed.

API permissions page showing Type Application and the green Granted status

Permission reference

PermissionTypeWhat it allowsNeeded?
Mail.ReadWriteApplicationRead messages, mark them as read, and move them between foldersYes — the service moves processed mail into success and failure folders

No other Graph permission is required. If anything else appears in the list, it can be removed.

Step 4. Restrict mailbox access (mandatory)

Why this step cannot be skipped

Granted as an application permission, Mail.ReadWrite applies to every mailbox in the tenant — the CEO's, HR's, finance's — not only the one Rezolve is configured to read.

Left unrestricted: a typo in the configured mailbox address reads someone else's mail, a leaked client secret exposes the whole organisation, and there is no server-side boundary to fall back on.

An Application Access Policy is Microsoft's supported mechanism for scoping app-only mailbox access. Treat it as part of the deployment, not as hardening to do later.

The step has three parts: create a group, put the mailbox in it, and bind the app to that group with a policy.

4.1 Create a mail-enabled security group

Go to admin.exchange.microsoft.comRecipientsGroups, then click Add a group.

Exchange admin center with Recipients, Groups, and the Add a group button

Choose the group type Mail-enabled security and click Next. This type matters — see the note at the end of this section.

Group type page with Mail-enabled security selected, not Microsoft 365 and not Distribution

Give the group a name that makes its purpose obvious, for example Rezolve-GraphMail-AllowedMailboxes, with a description such as "Mailboxes the Rezolve mail-ticket-service Graph app may access".

Basics page where the group name and description are entered

Assign an owner — yourself, or whoever will maintain the group when mailboxes are added or removed later.

Assign owners page with at least one owner selected

4.2 Add the mailbox to the group

On the Members page, add every mailbox Rezolve will read. In most deployments that is a single support or helpdesk mailbox; add all of them if there are several.

Add members panel with the mailbox searched and ticked

On the Settings page, give the group its own email address. You will need this address in the next part, and again in Step 5.

Settings page with the group email address filled in

Confirmation screen showing that the group has been created

It must be a mail-enabled security group

Microsoft 365 groups and ordinary Entra ID security groups are rejected by the policy command with "The identity of the policy scope is not a security principal."

The Entra ID portal only offers Security and Microsoft 365 group types, so this group can only be created from the Exchange admin center.

A newly created group can take up to an hour to appear everywhere. If the policy command in 4.3 cannot find the group, wait and try again rather than creating a second group.

4.3 Create the Application Access Policy

Application Access Policies have no portal interface; they are created with Exchange Online PowerShell. Azure Cloud Shell runs it in the browser, so nothing has to be installed on your machine.

In portal.azure.com, click the Cloud Shell icon (>_) in the top bar. Choose PowerShell if prompted. On first use Azure asks to create a storage account — click Create storage.

The Cloud Shell icon in the Azure top bar with the terminal starting up

First, install the Exchange Online module. This is only needed the first time and takes about a minute.

# 1. Install the Exchange Online module (first run only)
Install-Module -Name ExchangeOnlineManagement -Scope CurrentUser -Force

Install-Module running in Cloud Shell

note

Warnings that a module is already in use are normal and can be ignored.

Next, connect to Exchange Online. Sign in as an Exchange Administrator or Global Administrator.

# 2. Connect to Exchange Online
Connect-ExchangeOnline

A successful connection prints the module banner and returns to the prompt

Now create the policy, substituting your own client ID from Step 1 and the group address from Step 4.2. The backtick at the end of each line continues the command onto the next.

# 3. Create the policy
New-ApplicationAccessPolicy `
-AppId "<Application (client) ID from Step 1>" `
-PolicyScopeGroupId "<group address from Step 4.2>" `
-AccessRight RestrictAccess `
-Description "Restrict Rezolve mail-ticket-service to configured mailboxes only"

# 4. Disconnect when finished
Disconnect-ExchangeOnline -Confirm:$false

A successful run echoes the policy back. Check that AccessRight reads RestrictAccess and IsValid reads True.

Cloud Shell output echoing the new policy with AccessRight RestrictAccess and IsValid True

What RestrictAccess means

The app can access only the mailboxes in that group. Every other mailbox in the tenant returns HTTP 403.

Cloud Shell sessions time out after 20 minutes of inactivity, but the policy, once created, is permanent.

If the command reports a duplicate policy

Running the command twice for the same app and group returns "Duplicate policy found. Each policy must have a unique app ID and scope identity combination." This is harmless — it means the policy already exists from the earlier run. Verify it with the checks below rather than trying to create it again.

The duplicate-policy message in Cloud Shell after a second run

4.4 Verify the policy

Two checks, and both matter: one mailbox that must work, and one that must not. Testing only the mailbox that should work tells you nothing about whether the restriction is in force.

Connect-ExchangeOnline

# Expect: AccessCheckResult = Granted
Test-ApplicationAccessPolicy -AppId "<clientId>" -Identity "support@company.com"

# Expect: AccessCheckResult = Denied
Test-ApplicationAccessPolicy -AppId "<clientId>" -Identity "ceo@company.com"

Disconnect-ExchangeOnline -Confirm:$false

Both halves of the check: Granted for the configured mailbox, Denied for every other mailbox

Allow up to 30 minutes for propagation

Policies take up to 30 minutes to propagate across Microsoft's infrastructure. During that window the app may still reach other mailboxes.

Do not consider the setup complete until a Denied result has actually been observed for a mailbox outside the group.

Step 5. Hand the values to Rezolve

Six values complete the handover. Send them over a secure channel — a password manager entry, a secrets vault, or an encrypted file share. The client secret must not go by plain email or chat.

The handover checklist: five identifiers and one secret

ValueWhere it came fromSensitive?
Application (client) IDStep 1 — app Overview pageIdentifier
Directory (tenant) IDStep 1 — app Overview pageIdentifier
Client secret VALUEStep 2 — Certificates & secretsSecret — secure channel only
Client secret expiry dateStep 2 — Expires columnIdentifier
Mailbox addressThe mailbox added to the group in Step 4.2Identifier
Security group addressStep 4.2 — used for future mailbox additionsIdentifier

What happens next

Once Rezolve has these values, the administrator's work is done. Rezolve engineering then tests the connection with a utility script, configures the mail server record and folder mapping, and verifies end to end by sending a test message to the mailbox and confirming a ticket is created. Those steps are covered in the full engineering guide and need no further access from your side.

Ongoing administration

Adding another mailbox later

Add the mailbox to the same security group. No new app registration, secret or policy is needed, and the change takes effect within the usual propagation window. Tell Rezolve the new address so a mail server record can be configured for it.

Removing a mailbox

Remove it from the group. Access stops once the change propagates.

Rotating the client secret

Create a new secret before the current one expires, send the new Value to Rezolve, and delete the old secret once the new one is confirmed working. Nothing else in the configuration changes.

Frequently asked questions

Does this work with shared mailboxes?

Yes. A shared mailbox is a normal Microsoft 365 mailbox and is reachable through Graph. It still has to be a member of the security group.

Does it work with on-premises Exchange?

No. Graph covers Exchange Online only. On-premises Exchange requires one of the IMAP authentication types instead.

Can one app registration serve several mailboxes?

Yes. The same client ID, secret and tenant ID are reused, with a different mailbox per mail server record — and every one of those mailboxes must be in the access policy group.

Can the app read mail it should not?

Only if the Application Access Policy is missing, or the wrong mailbox was added to the group. With the policy in place, every other mailbox returns 403. This is why the Denied check in Step 4.4 is worth doing properly.

What breaks this setup?

Two things: the client secret expiring, and the app registration being deleted. Mailbox password changes and MFA policy changes have no effect on it.

Related

Smart Mailbox — Scoped Graph Access covers the newer Exchange Online RBAC for Applications method of scoping the same access. Either mechanism restricts the app to a defined set of mailboxes; use this guide when the administrator is following the Application Access Policy route.