Problem Statement
Users who send email via Microsoft 365 / Outlook using SMTP XOAUTH2 have to write their own token-fetching logic — POST to the Entra ID token endpoint, handle errors, cache the token, and refresh when near expiry. This is boilerplate that every Microsoft 365 user will write identically.
Proposed Solution
Ship a `MicrosoftOAuthProvider` class in the library implementing the `OAuthTokenProvider` interface (see issue #66):
```php
namespace WebFiori\Mail;
class MicrosoftOAuthProvider implements OAuthTokenProvider {
public function __construct(
private string $tenantId,
private string $clientId,
private string $clientSecret
) {}
public function getToken(): string {
// POST to https://login.microsoftonline.com/{tenant}/oauth2/v2.0/token
// grant_type=client_credentials
// scope=https://outlook.office365.com/.default
// Cache token with 5-minute expiry buffer
}
}
```
Usage:
```php
$provider = new MicrosoftOAuthProvider(
tenantId: 'your-tenant-id',
clientId: 'your-client-id',
clientSecret: 'your-client-secret'
);
$account->setTokenProvider($provider);
```
Alternatives Considered
Leave it entirely to application code. Works, but means every user duplicates the same cURL + JSON-decode + caching logic.
Breaking Change
No
Additional Context
Problem Statement
Users who send email via Microsoft 365 / Outlook using SMTP XOAUTH2 have to write their own token-fetching logic — POST to the Entra ID token endpoint, handle errors, cache the token, and refresh when near expiry. This is boilerplate that every Microsoft 365 user will write identically.
Proposed Solution
Ship a `MicrosoftOAuthProvider` class in the library implementing the `OAuthTokenProvider` interface (see issue #66):
```php
namespace WebFiori\Mail;
class MicrosoftOAuthProvider implements OAuthTokenProvider {
public function __construct(
private string $tenantId,
private string $clientId,
private string $clientSecret
) {}
}
```
Usage:
```php
$provider = new MicrosoftOAuthProvider(
tenantId: 'your-tenant-id',
clientId: 'your-client-id',
clientSecret: 'your-client-secret'
);
$account->setTokenProvider($provider);
```
Alternatives Considered
Leave it entirely to application code. Works, but means every user duplicates the same cURL + JSON-decode + caching logic.
Breaking Change
No
Additional Context