Microsoft 365, sending mail in SuiteCRM 8.9.1

i all,
I want to document a fully working setup for sending email from SuiteCRM 8.9.x using Microsoft 365 via Microsoft Graph (SendMail).

This post focuses on what exactly must be configured in Microsoft and what must be changed in SuiteCRM.
No SMTP, no Basic Auth, no Authenticated SMTP.

This is a confirmed working solution.


Background / Problem Description

My situation:

  • SuiteCRM 8.9.x

  • Microsoft 365 / Exchange Online

  • Basic SMTP authentication is deprecated / disabled

  • Authenticated SMTP is not desired

  • OAuth tokens were refreshing correctly in SuiteCRM

  • Microsoft Graph access token was valid

  • BUT email sending still failed or silently fell back to SMTP

The root cause turned out to be inside SuiteCRM, not Microsoft:
PHPMailer returns recipient addresses as arrays, and this broke the Graph mail payload.

Once that was fixed, Graph SendMail worked immediately.


PART 1 β€” Microsoft 365 configuration (required)

All Microsoft-side configuration is done in Microsoft Entra ID
(formerly Azure Active Directory).

No Exchange Admin Center changes are required for Graph SendMail.


1. Create App Registration

Microsoft Entra ID β†’ App registrations β†’ New registration

  • Name: SuiteCRM Graph Mail

  • Supported account types:

    • Single tenant
  • Redirect URI:

    • Not required for SendMail

Save the application.


2. API permissions (CRITICAL)

App registration β†’ API permissions

Add Microsoft Graph permissions:

Application permissions (NOT delegated)

Required:

  • :white_check_mark: Mail.Send

Optional (recommended for troubleshooting):

  • User.Read.All

:red_exclamation_mark: Do NOT use:

  • Mail.Send.Shared

  • Delegated permissions


3. Grant admin consent

Still in API permissions:

  • Click Grant admin consent

  • Confirm

If this step is skipped, Graph SendMail WILL fail.


4. Create client secret

App registration β†’ Certificates & secrets β†’ Client secrets

  • Create new secret

  • Copy the value immediately

  • Store it securely (used in SuiteCRM)


5. Token endpoint used by SuiteCRM

SuiteCRM uses OAuth 2.0 Client Credentials flow.

Token endpoint format:

https://login.microsoftonline.com/<TENANT_ID>/oauth2/v2.0/token

Scopes (internally handled by SuiteCRM):

https://graph.microsoft.com/.default


6. Exchange / Security Defaults

Important clarifications:

  • :cross_mark: Authenticated SMTP is NOT required

  • :cross_mark: Security Defaults do NOT need to be disabled

  • :cross_mark: No Exchange Admin Center settings are required

  • :cross_mark: No mailbox-level SMTP toggles are needed

Graph SendMail works independently of SMTP.


PART 2 β€” SuiteCRM 8.9.x configuration

This is where the actual bug was.


1. Create External OAuth Provider

Admin β†’ External OAuth Providers

Create provider with:

  • Provider type: Microsoft

  • Token endpoint:

    https://login.microsoftonline.com/<TENANT_ID>/oauth2/v2.0/token
    
    
  • Scope:

    https://graph.microsoft.com/.default
    
    

2. Create External OAuth Connection

Admin β†’ External OAuth Connections

Link it to the provider above.

Set:

  • Client ID β†’ from Entra App Registration

  • Client Secret β†’ from Entra App Registration

  • Grant type β†’ Client Credentials

Save and verify:

  • access_token and refresh_token appear in DB

  • Token refresh works (SuiteCRM logs confirm this)


3. Configure Outbound Email in SuiteCRM

Admin β†’ Email β†’ Outbound Email Accounts

For System Outbound Email:

  • Mail send type: SMTP

  • Auth type: OAuth

  • External OAuth Connection: select the one created above

  • SMTP Host:

    outlook.office365.com
    
    
  • Port: 587

  • TLS enabled

:warning: Even though SMTP fields are filled, SMTP auth is never used.
SuiteCRM only uses this to decide routing β€” actual sending is done via Graph.


4. REQUIRED SuiteCRM code changes (core issue)

:red_exclamation_mark: Root cause

PHPMailer methods return arrays:

$this->getToAddresses()
// returns:
[
  ['user@example.com', 'User Name'],
  ...
]

GraphMailer expects:

['user@example.com']

SuiteCRM core code treated these as strings β†’ invalid Graph payload.


5. Fix in SugarPHPMailer.php

File:

public/legacy/include/SugarPHPMailer.php

Correct recipient extraction

$to = [];
foreach ((array)$this->getToAddresses() as $entry) {
    if (is_array($entry) && !empty($entry[0])) {
        $to[] = $entry[0];
    }
}

$cc = [];
foreach ((array)$this->getCcAddresses() as $entry) {
    if (is_array($entry) && !empty($entry[0])) {
        $cc[] = $entry[0];
    }
}

$bcc = [];
foreach ((array)$this->getBccAddresses() as $entry) {
    if (is_array($entry) && !empty($entry[0])) {
        $bcc[] = $entry[0];
    }
}

These arrays are then passed to GraphMailer.


6. GraphMailer implementation

Location:

public/legacy/custom/include/GraphMail/GraphMailer.php

Responsibilities:

  • Accept already-clean email strings

  • Build Microsoft Graph payload:

    • /users/{from}/sendMail
  • Use Authorization: Bearer <access_token>

  • Log:

    • HTTP status

    • Response body (truncated)

Once recipient parsing was fixed, GraphMailer worked immediately.


Final Result

:white_check_mark: Emails send successfully via Microsoft 365
:white_check_mark: OAuth tokens refresh correctly
:white_check_mark: No SMTP authentication
:white_check_mark: No Security Defaults changes
:white_check_mark: Works for:

  • System email

  • User email

  • β€œSend Test Email”


Key lesson

This was NOT a Microsoft problem.
OAuth and Graph permissions were correct from the start.

The actual blocker was SuiteCRM’s handling of PHPMailer recipient arrays.


Recommendation to SuiteCRM core

SuiteCRM should:

  • Normalize PHPMailer recipients before using any non-SMTP transport

  • Document Graph SendMail as a first-class option


I reported this issue here: Microsoft 365 email via Graph API in SuiteCRM 8.9.x Β· Issue #10757 Β· SuiteCRM/SuiteCRM Β· GitHub

Hope this helps others save a lot of time :rocket:

4 Likes

Thank you for detailed guide.

Since it is v8.9.1, you should create bug at below repo:

Thank you. I reported in SuiteCRM Core, and added patches with attachments working.

Br,

Tapio

1 Like