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:
| Operation | Least privileged application permission |
|---|---|
| List or read users | User.Read.All |
| Read richer directory data | Directory.Read.All |
| Write users | User.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:
| Operation | Least privileged application permission |
|---|---|
| List message metadata/basic fields | Mail.ReadBasic.All |
| Read full messages | Mail.Read |
| Read and update messages | Mail.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:
| Operation | Least privileged application permission |
|---|---|
| Send mail without attachments or with small attachments | Mail.Send |
| Send mail with large attachments | Mail.Send and Mail.ReadWrite |
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
| Feature | Application permissions |
|---|---|
| List/read Entra users | User.Read.All |
| Read broader directory data | Directory.Read.All |
| List inbox message basics | Mail.ReadBasic.All |
| Read inbox messages | Mail.Read |
| Update inbox messages | Mail.ReadWrite |
| Send mail | Mail.Send |
| Send mail with large attachments | Mail.Send, Mail.ReadWrite |
After adding application permissions in Microsoft Entra, grant admin consent before using the client credentials flow.