Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Microsoftgraph Laravel Package

lloadout/microsoftgraph

Laravel package for integrating the Microsoft Graph API. Connect your app to Microsoft 365 to work with Outlook mail, calendars, OneDrive files, Teams, and Azure AD users through a fluent interface.

View on GitHub
Deep Wiki
Context7

Getting Started

  • Requirements: PHP 8.2+, Laravel 11, 12 or 13 (orchestra/testbench 9–11). If you are still on PHP 8.1 or Laravel 10, stay pinned to v1.20.
  • Install: composer require lloadout/microsoftgraph
  • Register an Entra ID app: add an app registration, grant the application permissions you need (Mail.Send for the mailer, Files.ReadWrite.All for the disk), click Grant admin consent, and create a client secret.
  • Configure: publish the package config (see the README for the current vendor:publish tag/provider) and set the tenant ID, client ID and secret in .env. Re-run php artisan config:clear any time you change them — the client caches tokens per config.
  • First use case — mail: add a mailer to config/mail.php that uses the package transport, point MAIL_MAILER at it (or call it explicitly), and keep sending mail the normal way:
    Mail::mailer('microsoftgraph')->to($user)->send(new InvoiceReady($invoice));
    
  • Second use case — files: the package registers a onedrive disk, so Storage::disk('onedrive')->put('reports/q1.pdf', $pdf) works like any other Flysystem disk.

Look at the README first — v1.21 added a requirements table and refreshed the Laravel docs links — then at config/microsoftgraph.php for the credential keys and the filesystems / mail snippets it documents.

Implementation Patterns

Mail routing. Define the Graph mailer once in config/mail.php with the package transport, then either make it the default MAIL_MAILER or select it per message with Mail::mailer('microsoftgraph'). This is the usual escape hatch for Microsoft 365 tenants where SMTP basic auth has been disabled. Queue the Mailable rather than sending inline — Graph throttles, and a queue gives you retries for free.

Filesystem usage. Treat the disk as ordinary Flysystem: put, get, exists, delete, files, allFiles. For anything large, use writeStream() / readStream() so you aren't holding whole files in memory, and pass ['overwrite' => true] (or an explicit visibility) rather than assuming the default conflict behaviour.

Multiple drives or tenants. Register additional disks yourself with Storage::extend('onedrive-archive', ...) in a service provider and reuse the package adapter with a differently configured client. This is the documented extension point for multi-tenant apps where each tenant has its own drive.

Testing. Storage::fake('onedrive') and Mail::fake() cover almost everything without touching Graph — the disk is just Flysystem underneath and the mailer is just a transport. Reserve real Graph calls for a single integration test against a test tenant.

HTTP client. The adapter/transport accept a client instance, so you can wrap Guzzle with RetryMiddleware and your own logging handler instead of writing retry logic around every call.

Gotchas and Tips

  • read() no longer returns false. OnedriveAdapter now matches the Flysystem 3 signatures and throws League\Flysystem\UnableToReadFile. Audit any code that inspects the adapter directly (custom wrappers, $adapter->read() checks, === false branches) and switch to catching the exception. Code going through Storage::get() was already exception-based, so most apps need no change.
  • Laravel 13 rebinds Storage::extend() closures. v1.21 fixed this internally by capturing the provider explicitly. If you copied the old provider pattern into your own package or app, do the same — don't rely on $this inside the closure, it won't be what you expect on Laravel 13.
  • PHP 8.4 signature change. MicrosoftGraphTransport::send() now declares an explicit nullable Envelope. If you subclass the transport, your override must use ?Envelope $envelope = null or you'll hit a fatal signature incompatibility.
  • Application permissions send as whoever you say. With client-credentials + Mail.Send, Graph sends as the from address you set; a typo or an unlicensed mailbox returns ErrorInvalidUser/403 rather than a friendly bounce. Validate the from address in config.
  • Throttling shows up as 429 with Retry-After. Handle it at the queue level (backoff(), retryUntil()) instead of catching it ad hoc.
  • Attachment limits. Graph's simple sendMail accepts roughly 3 MB total; larger attachments require an upload session. For big files, upload to OneDrive and mail a link instead.
  • Storage::url() won't work on this disk. There is no public URL to synthesise — use a Graph sharing link or temporaryUrl if the disk exposes it, and don't assume asset()-style paths.
  • Debugging 401s. A 401 immediately after editing .env is almost always a cached token or a stale config:cache. Clear both before digging into the app registration.
  • Switch to larastan/larastan. If you run PHPStan with Larastan, move off the abandoned nunomaduro/larastan — the package did the same in this release, and staying on the old one will drift from the new Flysystem signatures.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log
gregsphotography/site-builder-components
io-digital/clickatell
snowsoft/laravel-admin
oxygen/auth
relicsoftware/barakah-payment-gateway
tobya/work-with-composer
equipc/laravel-email-validator
equipc/laravel-email-database-log
adedsec/nova-translated-labels
wazza/laravel-db-encryption
hokny/laravel-generator
vonsogt/backup
jengo/queues
jeremykenedy/laravel-observability
coleus/frame
thtg88/journalism
filagora/filagora-ai-forums