PHPackages                             delaneydev/microsoftgraph-365-mail - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [API Development](/categories/api)
4. /
5. delaneydev/microsoftgraph-365-mail

ActiveLibrary[API Development](/categories/api)

delaneydev/microsoftgraph-365-mail
==================================

Laravel package for Microsoft graph (Microsoft 365). Manage mail, OneDrive, Teams, Excel, Calendars and Contacts with ease

v1.0.22(6mo ago)21521[1 PRs](https://github.com/DelaneyDev/microsoftgraph-365-mail/pulls)MITPHPPHP ^8.1

Since Mar 26Pushed 6mo agoCompare

[ Source](https://github.com/DelaneyDev/microsoftgraph-365-mail)[ Packagist](https://packagist.org/packages/delaneydev/microsoftgraph-365-mail)[ Docs](https://github.com/lloadout/microsoftgraph)[ RSS](/packages/delaneydev-microsoftgraph-365-mail/feed)WikiDiscussions main Synced 1mo ago

READMEChangelogDependencies (7)Versions (24)Used By (0)

 [![](https://github.com/LLoadout/assets/raw/master/LLoadout_microsoftgraph.png "LLoadout logo")](https://github.com/LLoadout/assets/blob/master/LLoadout_microsoftgraph.png)

[![Latest Version on Packagist](https://camo.githubusercontent.com/5fa3aa8bcdfd4d2706e02054d2ed3140807e43b31481bdcde94d54ce807a6c5d/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f64656c616e65796465762f6d6963726f736f667467726170682d3336352d6d61696c2e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/delaneydev/microsoftgraph-365-mail)[![Total Downloads](https://camo.githubusercontent.com/4bc5a3c8727a384b4471146be5f93989e364acabb5aac869e97351e0aa6118ec/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f64656c616e65796465762f6d6963726f736f667467726170682d3336352d6d61696c2e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/delaneydev/microsoftgraph-365-mail)

Laravel Microsoft Graph (DelaneyDev Fork) Native Laravel Microsoft Mail driver
==============================================================================

[](#laravel-microsoft-graph-delaneydev-fork-native-laravel-microsoft-mail-driver)

**What this package does**

This package is a **Laravel mail driver for Microsoft 365** that sends email via **Microsoft Graph (OAuth2)**.
It’s perfect for:

- **No-reply** and **single mailbox** sending (e.g., `noreply@yourdomain.com`) — **Single-User Mode** ✅
- Classic **per-user** OAuth sign-in (session-scoped tokens) — **Session Mode** ✅

> This is a **fork** of `lloadout/microsoftgraph`.
> **DelaneyDev** adds **Single-User Mode** (database-stored token; no session required) while still supporting the original **Session Mode**.

---

Quick Start (TL;DR)
-------------------

[](#quick-start-tldr)

1. Install &amp; Publish + migrate

```
composer require delaneydev/microsoftgraph-365-mail

php artisan vendor:publish --tag=microsoftgraph-config
php artisan vendor:publish --tag=microsoftgraph-model
php artisan vendor:publish --tag=microsoftgraph-migrations
php artisan migrate
```

3. Create Azure App (delegated **Mail.Send**) and put IDs/secrets in `.env` (see below)
4. Connect once at `/microsoft/connect` while signed in as the **sending mailbox** (e.g., `noreply@...`)
5. Use like normal:

```
Mail::to('user@example.com')->send(new MyMailable());
```

1) Azure App — Create and Grant Delegated Mail.Send (don’t change anything else)
--------------------------------------------------------------------------------

[](#1-azure-app--create-and-grant-delegated-mailsend-dont-change-anything-else)

1. **Azure Portal** → **Azure Active Directory** → **App registrations** → **New registration**
2. **Name:** `Laravel Microsoft Graph Mailer`
3. **Supported account types:** your tenant only (or multi-tenant if required)
4. **Redirect URI (Web):**

    ```
    https://your-domain.com/microsoft/callback

    ```
5. **Register**

**Copy credentials into `.env`:**

- From **Overview**:

    - Application (client) ID → `MS_CLIENT_ID`
    - Directory (tenant) ID → `MS_TENANT_ID` (or `common` if multi-tenant)
- From **Certificates &amp; secrets**:

    - **New client secret** → copy **Value** → `MS_CLIENT_SECRET`

**Grant permissions:**

- **API permissions** → **Add a permission** → **Microsoft Graph** → **Delegated permissions** → add:

    ```
    Mail.Send

    ```
- Click **Add permissions** and **Grant admin consent**.

---

2) Configure `.env`
-------------------

[](#2-configure-env)

> **Set these for both modes.** (Choose mode in the next section.)

```
MS_TENANT_ID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx   # or "common" if multi-tenant
MS_CLIENT_ID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
MS_CLIENT_SECRET=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
MS_GRAPH_API_VERSION=v1.0
MS_REDIRECT_URL=https://your-domain.com/microsoft/callback
MS_REDIRECT_AFTER_CALLBACK_URL=https://your-domain.com/dashboard

MAIL_MAILER=microsoftgraph
```

---

3) Choose a Mode
----------------

[](#3-choose-a-mode)

### A) **Single-User Mode (Recommended for no-reply &amp; single mailbox)**

[](#a-single-user-mode-recommended-for-no-reply--single-mailbox)

**What it is:** Your app always sends as one mailbox (e.g., `noreply@yourdomain.com`). Tokens are **stored in the database** (encrypted), not in the session. No per-request user login required.

**Enable in `.env`:**

```
MICROSOFTGRAPH_SINGLE_USER=true
MICROSOFTGRAPH_ENABLE_CONNECT=false
```

**Listen for the OAuth callback and store tokens (once):**Add to `AppServiceProvider` or `EventServiceProvider`:

```
use Illuminate\Support\Facades\Event;
use LLoadout\Microsoftgraph\Events\MicrosoftGraphCallbackReceived;
use App\Models\MicrosoftGraphAccessToken;
use Illuminate\Support\Facades\Crypt;
use Carbon\Carbon;

Event::listen(MicrosoftGraphCallbackReceived::class, function ($event) {
    $accessData = (array) Crypt::decrypt($event->accessData);
    MicrosoftGraphAccessToken::create([
        'access_token' => Crypt::encrypt($accessData['access_token']),
        'refresh_token' => Crypt::encrypt($accessData['refresh_token']),
        'expires_at' => Carbon::createFromTimestamp((int) $accessData['expires_on']),
    ]);
});
```

**Connect once as the sending mailbox:**

```
https://your-domain.com/microsoft/connect

```

Accept consent. The token is saved and will be reused automatically.

> After this, you can send mail without any user sessions:

```
Mail::to('user@example.com')->send(new \App\Mail\MyMailable());
```

---

### B) **Session Mode (Upstream behaviour; per-user tokens)**

[](#b-session-mode-upstream-behaviour-per-user-tokens)

**What it is:** Each signed-in user authenticates with Microsoft; tokens are stored in **session** and used per request.

**Enable in `.env`:**

```
MICROSOFTGRAPH_ENABLE_OAUTH=true
MICROSOFTGRAPH_SINGLE_USER=false
```

**Routes:**

- Consent redirect: `https://your-domain.com/microsoft/connect`
- Callback (must match Azure Redirect URI): `https://your-domain.com/microsoft/callback`

**Put access data in the session after callback** (example listener):

```
use App\Models\MicrosoftGraphAccessToken;
use LLoadout\Microsoftgraph\EventListeners\MicrosoftGraphCallbackReceived;

public function boot()
{
    Event::listen(function (MicrosoftGraphCallbackReceived $event) {
        session()->put('microsoftgraph-access-data', $event->accessData);
    });
}
```

> The package looks for `session('microsoftgraph-access-data')` when connecting.

---

4) Sending Email (same in both modes)
-------------------------------------

[](#4-sending-email-same-in-both-modes)

**Required API permission:** `Mail.Send` (Delegated)

**`.env`:**

```
MAIL_MAILER=microsoftgraph
# Ensure your "from" address is the account that granted consent
```

**Examples:**

```
// Mailable
Mail::to('user@example.com')->send(new \App\Mail\MyMailable());

// Quick test
Mail::raw('Hello from Microsoft Graph', function ($message) {
    $message->to('john@doe.com')->subject('Graph Test');
});
```

---

5) Package Capabilities (Beyond Mail)
-------------------------------------

[](#5-package-capabilities-beyond-mail)

This package wraps Microsoft Graph endpoints for:

- **OneDrive Storage** (Laravel Storage driver)
- **Teams** (send messages, list teams/channels)
- **Excel** (read/write cell ranges)
- **Calendars**
- **Contacts**
- **Reading &amp; handling Mail**

> You only need **Mail.Send** to send mail. Other features require additional permissions (see below).

---

Storage usage (OneDrive)
------------------------

[](#storage-usage-onedrive)

**Permission:** `Files.ReadWrite.All`**`.env`:**

```
MS_ONEDRIVE_ROOT="me/drive/root"
```

Use the `onedrive` disk like any Laravel filesystem disk:

```
$disk = Storage::disk('onedrive');
$disk->makeDirectory('Test folder');
$disk->put('Test folder/file1.txt','Content');
$contents = Storage::disk('onedrive')->get('Test folder/file1.txt');
```

---

Teams usage
-----------

[](#teams-usage)

**Permission:** `Chat.ReadWrite`*(Extra examples require `Group.Read.All`, `Chat.Read.All`, `ChannelMessage.Read.All`, `ChannelMessage.Send`)*

```
$teams = new \LLoadout\Microsoftgraph\Teams();
$joinedTeams = $teams->getJoinedTeams();
$channels = $teams->getChannels($team);
$chats = $teams->getChats();
$chat = $teams->getChat('your-chat-id');
$members = $teams->getMembersInChat($chat);
$teams->send($teamOrChat, 'Hello world!');
```

---

Excel usage
-----------

[](#excel-usage)

**Permission:** `Files.ReadWrite.All`

```
$excel = new \LLoadout\Microsoftgraph\Excel();

$excel->loadFile('Test folder/file1.xlsx');        // or ->loadFileById($fileId)
$values = ['B1'=>null,'B2'=>'01.01.23','B3'=>3,'B4'=>'250','B5'=>'120','B6'=>'30 cm'];
$excel->setCellValues('B1:B12', $values);
$result = $excel->getCellValues('H1:H20');
```

---

Calendar usage
--------------

[](#calendar-usage)

**Permission:** `Calendars.ReadWrite`

```
$calendar = new \LLoadout\Microsoftgraph\Calendar();
$calendars = $calendar->getCalendars();

$event = $calendar->makeEvent(
  starttime: '2025-08-11T09:00:00',
  endtime:   '2025-08-11T10:00:00',
  timezone:  'Europe/London',
  subject:   'Standup',
  body:      'Daily sync',
  attendees: [['email'=>'teammate@domain.com','name'=>'Teammate']],
  isOnlineMeeting: true
);

$calendar->saveEvent($calendarEntity, $event);
```

---

Contacts usage
--------------

[](#contacts-usage)

**Permission:** `Contacts.ReadWrite`

```
$contacts = new \LLoadout\Microsoftgraph\Contacts();
$list = $contacts->getContacts();
```

---

Reading and handling mail
-------------------------

[](#reading-and-handling-mail)

**Permissions:** `Mail.Read, Mail.ReadWrite, Mail.ReadBasic`

```
$mail = app(\LLoadout\Microsoftgraph\Mail::class);

collect($mail->getMailFolders())->each(fn($f) => print $f['displayName']."\n");

$unread = $mail->getMailMessagesFromFolder('inbox', isRead: false);
collect($unread)->each(fn($m) => print $m['subject']."\n");
```

**Available methods**

```
getMailFolders(): array|GraphResponse|mixed
getSubFolders($id): array|GraphResponse|mixed
getMailMessagesFromFolder($folder='inbox', $isRead=true, $skip=0, $limit=20): array
updateMessage($id, $data): array|GraphResponse|mixed
moveMessage($id, $destinationId): array|GraphResponse|mixed
getMessage($id): array|GraphResponse|mixed
getMessageAttachements($id): array|GraphResponse|mixed
```

---

Differences: DelaneyDev Fork vs Upstream
----------------------------------------

[](#differences-delaneydev-fork-vs-upstream)

Topic**DelaneyDev (this fork)****Upstream (lloadout/microsoftgraph)**Primary goal**Single-User Mode** for no-reply/single mailbox sendingSession-based per-user OAuthToken storage**Database** (encrypted) via model/migration**Session** (`microsoftgraph-access-data`)Sessions needed to send mail**No** (after initial connect)**Yes** (user must have session token)Best forSystem emails, cron, queues, workersUser-initiated emails on behalf of each userSession ModeStill supportedN/A (original behavior)You can enable **either** mode via `.env`.

---

Troubleshooting
---------------

[](#troubleshooting)

- \*\*Queue workers restarted after changing `.env`
- \*\*Clear app cache/Redis if tokens were encrypted with an old key
- **403 / insufficient permissions**Confirm **Mail.Send (Delegated)** is added and **admin consent** granted in Azure.
- **Redirect URI mismatch**The Azure **Redirect URI** must exactly match `MS_REDIRECT_URL`.

---

Testing
-------

[](#testing)

```
composer test
```

Changelog
---------

[](#changelog)

See [CHANGELOG](CHANGELOG.md).

Contributing
------------

[](#contributing)

See [CONTRIBUTING](CONTRIBUTING.md).

Security Vulnerabilities
------------------------

[](#security-vulnerabilities)

Please review [our security policy](../../security/policy).

Credits
-------

[](#credits)

- Fork base: [Dieter Coopman](https://github.com/LLoadout)
- DelaneyDev additions: Single-User Mode + docs
- [All Contributors](../../contributors)

License
-------

[](#license)

MIT — see [LICENSE](LICENSE.md).

```

```

###  Health Score

41

—

FairBetter than 88% of packages

Maintenance72

Regular maintenance activity

Popularity18

Limited adoption so far

Community10

Small or concentrated contributor base

Maturity55

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 76.7% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~10 days

Recently: every ~31 days

Total

23

Last Release

190d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/206de7d5dd3f844fe0dcbf421921937b49d5c55c7aecf5c7a651849e08227145?d=identicon)[DelaneyDev](/maintainers/DelaneyDev)

---

Top Contributors

[![dietercoopman](https://avatars.githubusercontent.com/u/4672752?v=4)](https://github.com/dietercoopman "dietercoopman (102 commits)")[![DelaneyArkICT](https://avatars.githubusercontent.com/u/89026864?v=4)](https://github.com/DelaneyArkICT "DelaneyArkICT (19 commits)")[![DelaneyDev](https://avatars.githubusercontent.com/u/102393830?v=4)](https://github.com/DelaneyDev "DelaneyDev (12 commits)")

---

Tags

laravelmicrosoftgraphLLoadout

###  Code Quality

Code StyleLaravel Pint

### Embed Badge

![Health badge](/badges/delaneydev-microsoftgraph-365-mail/health.svg)

```
[![Health](https://phpackages.com/badges/delaneydev-microsoftgraph-365-mail/health.svg)](https://phpackages.com/packages/delaneydev-microsoftgraph-365-mail)
```

###  Alternatives

[dedoc/scramble

Automatic generation of API documentation for Laravel applications.

2.0k7.8M55](/packages/dedoc-scramble)[scalar/laravel

Render your OpenAPI-based API reference

6183.9k2](/packages/scalar-laravel)[ryangjchandler/bearer

Minimalistic token-based authentication for Laravel API endpoints.

8129.8k](/packages/ryangjchandler-bearer)[combindma/laravel-facebook-pixel

Meta pixel integration for Laravel

4956.9k](/packages/combindma-laravel-facebook-pixel)[stechstudio/laravel-hubspot

A Laravel SDK for the HubSpot CRM Api

2971.0k](/packages/stechstudio-laravel-hubspot)[lloadout/microsoftgraph

Laravel package for Microsoft graph (Microsoft 365). Manage mail, OneDrive, Teams, Excel, Calendars and Contacts with ease

274.7k](/packages/lloadout-microsoftgraph)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
