Skip to main content

Microsoft Graph

For credentials go to: Azure portal

The Microsoft Graph module provides a Laravel binding around Microsoft's official PHP SDK and registers a Laravel mail transport named microsoft-graph.

Use it when an application needs server-to-server access to Microsoft Graph, such as reading mailboxes, sending mail, listing Microsoft Entra users, or calling any other Graph endpoint exposed by the SDK.

Install

composer require qore-next/microsoft-graph

The package auto-discovers MicrosoftGraphServiceProvider.

No migrations, config or routes are published by this module. Install it, enable it in the modules UI and configure the Microsoft Graph credentials before using the default client or mail transport in production.

SDK

This module uses microsoft/microsoft-graph, Microsoft's official Graph SDK for PHP.

That package is preferred over Laravel-specific wrappers because it is maintained by Microsoft, generated for the full Graph API surface, and supports the SDK authentication contexts for application, delegated, and on-behalf-of flows. The Qore module only adds Laravel registration and mail transport integration.

SDK calls are asynchronous. Call ->wait() on get(), post(), patch(), and similar operations.

Configure

Enable the module in Qore's modules UI, then save these Microsoft Entra app credentials in the module settings:

  • Tenant ID
  • Client ID
  • Client secret

The credentials are stored as:

qore()->settings()->getSetting('microsoft-graph.tenant_id');
qore()->settings()->getSetting('microsoft-graph.client_id');
qore()->settings()->getSetting('microsoft-graph.client_secret');

Resolve the module service and get the native SDK client:

use Qore\Next\MicrosoftGraph\MicrosoftGraph;

$graph = app(MicrosoftGraph::class)->getClient();

You can also override credentials for a specific client:

$graph = app(MicrosoftGraph::class)->getClient([
'tenant_id' => $tenantId,
'client_id' => $clientId,
'client_secret' => $clientSecret,
]);

The module settings remain the default source for credentials. Use explicit overrides only for exceptional cases, such as a multi-tenant flow that needs a different app registration.

Microsoft Entra Users

List users:

use Microsoft\Graph\Generated\Users\UsersRequestBuilderGetRequestConfiguration;

$request = new UsersRequestBuilderGetRequestConfiguration(
queryParameters: UsersRequestBuilderGetRequestConfiguration::createQueryParameters(
select: ['id', 'displayName', 'mail', 'userPrincipalName'],
top: 25,
),
);

$users = $graph->users()->get($request)->wait();

Read one user:

$user = $graph->users()->byUserId('jane@example.com')->get()->wait();

Required permissions:

OperationLeast privileged application permission
List or read usersUser.Read.All
Read richer directory dataDirectory.Read.All
Write usersUser.ReadWrite.All or Directory.ReadWrite.All

Use delegated permissions only when the request is made on behalf of a signed-in user. For delegated list/read access, Microsoft lists User.ReadBasic.All as the least privileged option for work or school accounts.

Inbox Messages

List messages from a mailbox:

use Microsoft\Graph\Generated\Users\Item\Messages\MessagesRequestBuilderGetRequestConfiguration;

$request = new MessagesRequestBuilderGetRequestConfiguration(
queryParameters: MessagesRequestBuilderGetRequestConfiguration::createQueryParameters(
select: ['id', 'sender', 'subject', 'receivedDateTime'],
top: 10,
),
);

$messages = $graph
->users()
->byUserId('invoices@example.com')
->messages()
->get($request)
->wait();

Read messages from a folder:

$messages = $graph
->users()
->byUserId('invoices@example.com')
->mailFolders()
->byMailFolderId('inbox')
->messages()
->get($request)
->wait();

Required permissions:

OperationLeast privileged application permission
List message metadata/basic fieldsMail.ReadBasic.All
Read full messagesMail.Read
Read and update messagesMail.ReadWrite

Use $select to request only the message fields you need, especially for larger mailboxes.

Sending Mail

Configure a Laravel mailer in config/mail.php:

'mailers' => [
'graph' => [
'transport' => 'microsoft-graph',
'user' => env('MICROSOFT_GRAPH_MAIL_USER', 'development@qlic.nl'),
'save_to_sent_items' => true,
],
],

And update your MAIL_MAILER in .env or provide a mailer in your mail notification.

The mailer uses the module settings credentials by default. You can also put tenant_id, client_id, and client_secret directly on the mailer config to override them for that mailer.

user must be the mailbox user ID or user principal name used in Graph URLs, for example billing@example.com. When it is omitted, the transport uses the Symfony sender address.

Required permissions:

OperationLeast privileged application permission
Send mail without attachments or with small attachmentsMail.Send
Send mail with large attachmentsMail.Send and Mail.ReadWrite
warning

Large attachments need Mail.ReadWrite because Graph upload sessions attach files to an existing Outlook item. The transport creates a draft message, uploads the attachments, and sends the draft. Microsoft Graph supports Outlook attachment upload sessions for files from 3 MB up to 150 MB; tenant and Exchange Online message-size limits still apply.

Delegated Clients

The default Qore binding creates an application client with ClientCredentialContext. For signed-in-user flows, instantiate the SDK directly with the relevant Kiota context:

use Microsoft\Graph\GraphServiceClient;
use Microsoft\Kiota\Authentication\Oauth\AuthorizationCodeContext;

$context = new AuthorizationCodeContext(
tenantId: $tenantId,
clientId: $clientId,
clientSecret: $clientSecret,
authCode: $authCode,
redirectUri: $redirectUri,
);

$graph = new GraphServiceClient($context, ['User.Read', 'Mail.Read']);

Use delegated scopes such as User.Read, Mail.ReadBasic, Mail.Read, Mail.ReadWrite, and Mail.Send depending on the signed-in user's workflow.

Permission Checklist

FeatureApplication permissions
List/read Entra usersUser.Read.All
Read broader directory dataDirectory.Read.All
List inbox message basicsMail.ReadBasic.All
Read inbox messagesMail.Read
Update inbox messagesMail.ReadWrite
Send mailMail.Send
Send mail with large attachmentsMail.Send, Mail.ReadWrite

After adding application permissions in Microsoft Entra, grant admin consent before using the client credentials flow.