PHPackages                             andrewsauder/microsoft-services - 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. andrewsauder/microsoft-services

ActiveLibrary[API Development](/categories/api)

andrewsauder/microsoft-services
===============================

PHP wrapper for easy implementation of Microsoft Graph services

v1.4.10(1mo ago)11611MITPHPPHP &gt;=8.2

Since Feb 17Pushed 1mo ago1 watchersCompare

[ Source](https://github.com/andrewsauder/microsoftServices)[ Packagist](https://packagist.org/packages/andrewsauder/microsoft-services)[ RSS](/packages/andrewsauder-microsoft-services/feed)WikiDiscussions main Synced 1w ago

READMEChangelog (10)Dependencies (12)Versions (23)Used By (1)

Microsoft Services
==================

[](#microsoft-services)

PHP wrapper for easy implementation of Microsoft Graph services

Requirement
-----------

[](#requirement)

Version &gt;=1.2 requires PHP &gt;=8.1

Installation
------------

[](#installation)

`composer require andrewsauder/microsoft-services`

Service Configuration
---------------------

[](#service-configuration)

```
$config = new \andrewsauder\microsoftServices\config();
$config->clientId = '{Azure Application ID}';
$config->clientSecret = '{Azure Client Secret}';  //certificates not yet supported
$config->tenant = 'example.com';
$config->driveId = '';                            //required if using the files service - cay be found using Graph explorer
$config->fromAddress = 'noreply@example.com';     //required if using mail service - this is just a default
```

Files Usage
-----------

[](#files-usage)

### Get List of Files

[](#get-list-of-files)

#### From Root Directory

[](#from-root-directory)

```
$microsoftFiles = new \andrewsauder\microsoftServices\files( $config );
$files = $microsoftFiles->list();
```

#### From Subdirectory

[](#from-subdirectory)

```
//example subdirectory: {root}/2021-0001/Building 1/Inspections
$microsoftFiles = new \andrewsauder\microsoftServices\files( $config );
$files = $microsoftFiles->list( [ '2021-0001', 'Building 1', 'Inspections' ] );
```

### Upload File

[](#upload-file)

#### Into Root Directory

[](#into-root-directory)

```
$microsoftFiles = new \andrewsauder\microsoftServices\files( $config );
$uploadFileResponse = $microsoftFiles->upload( 'C:\tmp\testFile.txt', 'testFile.txt' );
```

#### Into Subdirectory

[](#into-subdirectory)

```
//example subdirectory: {root}/2021-0001/Building 1/Inspections
$microsoftFiles = new \andrewsauder\microsoftServices\files( $config );
$uploadFileResponse = $microsoftFiles->upload( 'C:\tmp\testFile.txt', 'testFile.txt', [ '2021-0001', 'Building 1', 'Inspections' ] );
```

### Delete File

[](#delete-file)

```
$microsoftFiles = new \andrewsauder\microsoftServices\files( $config );
$deleteResponse = $microsoftFiles->delete( $itemId );
```

Mail Usage
----------

[](#mail-usage)

If no user token is provided, the application token will be used.

If the application token is being used, verify that the Azure application has correct Mail.X permissions for the email address being used. To limit application access to only certain mailboxes, use ExchangeOnline Powershell to apply access policy. More info

If a user access token is provided when creating the service (`mail($config, 'user-access-token-string')`), verify that the user has 'send on behalf' of or 'send as' permissions configured properly in Office 365.

### Send Email

[](#send-email)

If the from address is not provided, the default from address in the config will be used.

```
$microsoftMail = new \andrewsauder\microsoftServices\mail( $config );
$microsoftMail->addAttachment( 'C:\tmp\testFile.txt' );
$rsp = $microsoftMail->send( 'to@example.com', 'Subject', 'HTML compatible message', 'from@example.com' );

if( $rsp->getStatus() < 200 || $rsp->getStatus() >= 300 ) {
    error_log( 'Failed' );
}
```

### Reply Into a Thread

[](#reply-into-a-thread)

Continue an existing conversation instead of starting a new one. `replyIntoThread()` creates a reply draft anchored on a message you previously sent (so it inherits that conversation and its `RE:` subject), sets the recipients and body you provide, and sends it. Store the returned message's immutable id as the anchor for the next reply, and its conversation id for inbound matching.

Provide the `from` mailbox, the immutable id of the last message you sent in the thread, and the recipients/body. Do not set a subject - the reply inherits it.

```
$microsoftMail = new \andrewsauder\microsoftServices\mail( $config );

$sent = $microsoftMail->replyIntoThread(
    'helpdesk@example.com',   // from (owns the anchor message)
    $lastMessageId,           // immutable id of the last message sent in the thread
    [ 'to@example.com' ],     // to
    [],                       // bcc
    'HTML compatible message',
    [ 'cc@example.com' ]      // cc (optional)
);

$nextAnchor     = $sent->getId();              // store as the next thread anchor
$conversationId = $sent->getConversationId();  // store for inbound reply matching
```

If the anchor message no longer exists (deleted), `replyIntoThread()` throws a `serviceException` - catch it and fall back to `createDraft()` / `sendDraft()` to start a fresh thread.

Only the immutable id is needed to reply. If you have lost it but still know the conversation id, recover an anchor with:

```
$latest = $microsoftMail->getLatestMessageInConversation( 'helpdesk@example.com', $conversationId );
$anchorId = $latest?->getId();
```

You can also create just the draft (without sending) with `createReplyDraft( $messageId, $from )`.

### Get All Messages

[](#get-all-messages)

```
$microsoftMail = new \andrewsauder\microsoftServices\mail( $config );
$messages = $microsoftMail->getAllMessages( 'joeschmoe@example.com' );
```

### Get All Messages from Specific Folder

[](#get-all-messages-from-specific-folder)

```
$microsoftMail = new \andrewsauder\microsoftServices\mail( $config );
$messages = $microsoftMail->getMessagesInFolder( 'joeschmoe@example.com', 'mail-folder-id' );
```

### Get All Folders

[](#get-all-folders)

```
$microsoftMail = new \andrewsauder\microsoftServices\mail( $config );
$folders = $microsoftMail->getFolders( 'joeschmoe@example.com' );
```

### Get Attachments for Message

[](#get-attachments-for-message)

```
$microsoftMail = new \andrewsauder\microsoftServices\mail( $config );
$attachments = $microsoftMail->getAttachments( 'joeschmoe@example.com', 'message-id' );
```

### Delete Message

[](#delete-message)

```
$microsoftMail = new \andrewsauder\microsoftServices\mail( $config );
$graphResponse = $microsoftMail->deleteMessage( 'joeschmoe@example.com', 'message-id' );
```

User Usage
----------

[](#user-usage)

### Get All Users in Organization

[](#get-all-users-in-organization)

```
$microsoftUserService = new \andrewsauder\microsoftServices\user( $config );
$users = $microsoftUserService->allUsersInOrganization();
```

### Get User by User Principal Name

[](#get-user-by-user-principal-name)

```
$microsoftUserService = new \andrewsauder\microsoftServices\user( $config );
$users = $microsoftUserService->getUserByUserPrincipalName( 'andrew@sauder.software' );
```

### Get User by Id

[](#get-user-by-id)

```
$microsoftUserService = new \andrewsauder\microsoftServices\user( $config );
$users = $microsoftUserService->getUserById( '15bd6895-bf60-4125-a1d2-affb7e0de5d8' );
```

### Get Users By Advanced Filter

[](#get-users-by-advanced-filter)

See  for filter details

```
$microsoftUserService = new \andrewsauder\microsoftServices\user( $config );
$users = $microsoftUserService->getUsersByFilter( 'startswith(userPrincipalName,"andrew")' );
```

###  Health Score

51

—

FairBetter than 95% of packages

Maintenance93

Actively maintained with recent releases

Popularity15

Limited adoption so far

Community14

Small or concentrated contributor base

Maturity72

Established project with proven stability

 Bus Factor1

Top contributor holds 94.6% 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 ~94 days

Recently: every ~109 days

Total

18

Last Release

33d ago

PHP version history (3 changes)v1.0.0PHP &gt;=8.0

v1.2.0PHP &gt;=8.1

v1.4.3PHP &gt;=8.2

### Community

Maintainers

![](https://www.gravatar.com/avatar/e97ad9c5583ee03e1f670eba13bd11b81e3374da1941dce10f6da80e5dc6d8eb?d=identicon)[andrewsauder](/maintainers/andrewsauder)

---

Top Contributors

[![andrewsauder](https://avatars.githubusercontent.com/u/1380472?v=4)](https://github.com/andrewsauder "andrewsauder (35 commits)")[![claude](https://avatars.githubusercontent.com/u/81847?v=4)](https://github.com/claude "claude (2 commits)")

---

Tags

microsoft-graph-apiphp

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Type Coverage Yes

### Embed Badge

![Health badge](/badges/andrewsauder-microsoft-services/health.svg)

```
[![Health](https://phpackages.com/badges/andrewsauder-microsoft-services/health.svg)](https://phpackages.com/packages/andrewsauder-microsoft-services)
```

###  Alternatives

[tencentcloud/tencentcloud-sdk-php

TencentCloudApi php sdk

3661.3M49](/packages/tencentcloud-tencentcloud-sdk-php)[eslazarev/wildberries-sdk

Wildberries OpenAPI clients (generated).

353.6k](/packages/eslazarev-wildberries-sdk)[files.com/files-php-sdk

Files.com PHP SDK

2482.9k](/packages/filescom-files-php-sdk)[volcengine/volcengine-php-sdk

119.5k](/packages/volcengine-volcengine-php-sdk)

PHPackages © 2026

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