Upgrade Guide
August 3, 2026 · View on GitHub
1.x → 2.0
Requirements
- PHP 8.2 or higher (was 8.1)
- Laravel 11, 12, or 13 (was 9.38–13)
- symfony/mailer 7 or 8 (was 6–8)
Breaking changes
access_token_ttl removed. The access token is now cached for the lifetime reported by Microsoft
(expires_in) minus a 60 second safety buffer. Remove the key from your mailer config if you set it —
it now throws no error but has no effect either.
Token cache key changed. Tokens are now cached per tenant and client (previously per tenant only, which made two apps in the same tenant share one token). The first send after upgrading simply acquires a fresh token; no action needed.
Attachment names. Attachment name values now use the real filename including its extension when
the framework exposes one (fixes inline image rendering in clients like Thunderbird). The contentId
used for inline images is unchanged. If you post-process sent payloads by attachment name, review that
logic.
Large mails need Mail.ReadWrite (only if you send them). Mails above ~3 MB total are now sent
automatically via a draft + upload sessions instead of failing with ErrorMessageSizeExceeded. This
path requires the Mail.ReadWrite application permission with admin consent. Small mails continue to
work with Mail.Send alone. save_to_sent_items is honored on this path too: when disabled, the sent
message is deleted from Sent Items after sending (best effort); failed sends delete their draft.
Constructor signatures changed (only relevant if you construct or extend the classes yourself —
normal mailer usage is unaffected): MicrosoftGraphApiService now takes a ClientAuthentication
implementation instead of clientSecret/accessTokenTtl, and MicrosoftGraphTransport gained a
saveToSentItems constructor parameter.
Behavior corrections (no action needed, but worth knowing)
save_to_sent_itemsis now read from the mailer's own config entry. Mailers registered under a custom key (notmicrosoft-graph) previously silently ignored the option and sentsaveToSentItems: false.- The mailer-level
fromis now optional; when the key is omitted entirely, Laravel's globalmail.fromis used. A present-but-emptyfromstill fails fast withConfigurationMissing. - Custom
X-Metadata-*/X-Tag-*headers (Symfony transport instructions) are no longer forwarded to recipients as literal mail headers.
New features
- Certificate authentication: configure
client_certificate(PEM content or file paths) instead ofclient_secret. See the README. - Per-mailable
saveToSentItemsoverride vianew MetadataHeader('save-to-sent-items', 'true'|'false'). - Automatic large-attachment handling via Graph upload sessions (see above).
After upgrading
Run php artisan config:clear && php artisan cache:clear once. Cached tokens do not carry newly granted
permissions (e.g. Mail.ReadWrite), so clear the cache after any permission change too.