Microsoft Office 365 SMTP Integration for Website Contact Forms (2026 Guide – OAuth 2.0 & Graph API)

If your website contact form suddenly stopped sending emails using Microsoft Office 365 SMTP, you are not alone.

Microsoft has permanently removed basic authentication and app passwords, which means traditional SMTP username-password setups no longer work. As a result, thousands of websites are facing errors like:

  • 535 Authentication Unsuccessful

  • Could not connect to SMTP host

  • SMTP login failed

In this guide, we’ll explain:

  • Why Microsoft blocked old SMTP methods

  • The correct and supported way to send emails in 2026

  • How to integrate Office 365 SMTP using OAuth 2.0

  • Why Microsoft Graph API is the best long-term solution

 

Why Microsoft Removed App Passwords & Basic SMTP

Microsoft disabled basic authentication to:

  • Prevent password-based attacks

  • Reduce phishing risks

  • Enforce enterprise-grade security

What no longer works 

  • SMTP with username + password

  • App passwords

  • Shared hosting SMTP hacks

What Microsoft allows now 

  • OAuth 2.0 authentication

  • Microsoft Graph API

 

How Modern Email Sending Works

  • Website Contact Form / Email Funcation
  • Backend Server (PHP / Node / Python)
  • Microsoft OAuth Token Endpoint
  • Access Token Issued
  • SMTP (OAuth) OR Microsoft Graph API
  • Email Delivered

 

Option 1: Office 365 SMTP with OAuth 2.0

This method keeps SMTP but replaces passwords with OAuth tokens.

 

Step 1: Enable SMTP AUTH for the Mailbox

Microsoft disables this by default.

Microsoft 365 Admin Center

  1. Users -> Active Users

  2. Select mailbox (example: contact@yourdomain.com)

  3. Mail -> Manage email apps

  4. Enable Authenticated SMTP

  5. Save

 

Step 2: Create App Registration (Entra ID)

  1. Go to Microsoft Entra ID

  2. App registrations -> New registration

  3. Name: Website SMTP Mailer

  4. Account type: Single tenant

  5. Register

Save:

  • Tenant ID

  • Client ID

 

Step 3: Create Client Secret

  1. Certificates & Secrets

  2. New client secret

  3. Set expiry (6–12 months)

Save it securely -> you won’t see it again.

 

Step 4: Assign API Permissions

  1. API Permissions -> Add

  2. Microsoft Graph

  3. Application Permissions

  4. Add Mail.Send

  5. Grant admin consent

 

Step 5: OAuth Token URL (Very Important)

https://login.microsoftonline.com/{TENANT_ID}/oauth2/v2.0/token
 

Step 6: SMTP Configuration

 

Host: smtp.office365.com
Port: 587
Encryption: STARTTLS
Auth Type: OAuth 2.0
 

 

Option 2: Microsoft Graph API (RECOMMENDED)

Microsoft Graph API completely replaces SMTP.

Why Graph API is better

  • No SMTP ports required

  • Higher delivery rate

  • Better security

  • Fully future-proof

How Graph API Sends Email

POST https://graph.microsoft.com/v1.0/users/contact@yourdomain.com/sendMail
 

Uses the same OAuth token, but avoids SMTP entirely.

 

Basic Graph Email Flow

  1. Contact form submits

  2. Backend requests OAuth token

  3. Backend calls Microsoft Graph

  4. Email sent successfully

 

Microsoft Graph API (without SMTP)

STEP 1: Register App in Microsoft Entra ID (Azure AD)

  1. Go to https://entra.microsoft.com

  2. App registrations -> New registration

Settings

  • Name: Website Contact Form Mailer

  • Account type: Single tenant

  • Redirect URI (Web):

https://yourdomain.com/oauth/callback.php
 

       3. Click Register

 

STEP 2: Create Client Secret

  • App -> Certificates & secrets

  • New client secret

  • Copy:

Client ID

Tenant ID

Client Secret

 

STEP 3: API Permissions

Go to API permissions

Add:

Microsoft Graph --> Application permissions
--> Mail.Send

Then:

  • Click Grant admin consent

 

STEP 4: OAuth Token (Client Credentials Flow)

Create file in cPanel:

/oauth/get_token.php

 

PHP Code - Get Access Token

 

$tenantId = "YOUR_TENANT_ID";
$clientId = "YOUR_CLIENT_ID";
$clientSecret = "YOUR_CLIENT_SECRET";

$url = "https://login.microsoftonline.com/$tenantId/oauth2/v2.0/token";

$data = [
    "client_id" => $clientId,
    "scope" => "https://graph.microsoft.com/.default",
    "client_secret" => $clientSecret,
    "grant_type" => "client_credentials"
];

$ch = curl_init($url);
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => http_build_query($data),
    CURLOPT_RETURNTRANSFER => true
]);

$response = curl_exec($ch);
curl_close($ch);

$token = json_decode($response, true);
echo $token['access_token'];
 

 

STEP 5: Send Email via Graph API

Create:

/sendMail.php
 

PHP Contact Form Mailer

$accessToken = file_get_contents("oauth/access_token.txt");

$sender = "contact@yourdomain.com";
$recipient = "sales@yourdomain.com";

$emailData = [
    "message" => [
        "subject" => "New Contact Form Submission",
        "body" => [
            "contentType" => "HTML",
            "content" => "

Name: $_POST[name]

Email: $_POST[email]

Message: $_POST[message]

"
        ],
        "toRecipients" => [
            ["emailAddress" => ["address" => $recipient]]
        ]
    ]
];

 

$ch = curl_init("https://graph.microsoft.com/v1.0/users/$sender/sendMail");
curl_setopt_array($ch, [
    CURLOPT_HTTPHEADER => [
        "Authorization: Bearer $accessToken",
        "Content-Type: application/json"
    ],
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => json_encode($emailData),
    CURLOPT_RETURNTRANSFER => true
]);

$response = curl_exec($ch);
curl_close($ch);

echo "Mail sent";
 

 

STEP 6: Store & Refresh Token (Important)

Tokens expire in 60 minutes.

Best practice:

  • Cron job every 50 minutes

  • Save token to:

oauth/access_token.txt
 

 

cPanel Cron Job

 

*/50 * * * * php /home/username/public_html/oauth/get_token.php > /home/username/public_html/oauth/access_token.txt
 

 

 

Node.js on cPanel for Microsoft 365 (Graph API Mailer)

Check if Node.js is Enabled in cPanel

Login to cPanel => Software

Look for:

 

Setup Node.js App
 

 

If you don’t see it:

  • Ask hosting support: “Enable Node.js Selector”

  • Most hosts allow Node v16 / v18 / v20

 

Create Node.js App in cPanel

cPanel => Setup Node.js App => Create Application

SSH into cPanel

Enable SSH in cPanel => Terminal
OR use Terminal inside cPanel

 

cd ~/node-mailer
npm init -y
 

 

Install dependencies:

 

npm install express axios dotenv
 

 

Create .env File (OAuth Secrets)

 

nano .env

TENANT_ID=xxxxxxxx-xxxx
CLIENT_ID=xxxxxxxx-xxxx
CLIENT_SECRET=xxxxxxxx
SENDER_EMAIL=contact@yourdomain.com
 

 

index.js (Graph API Mail Sender)

 

require("dotenv").config();
const express = require("express");
const axios = require("axios");

const app = express();
app.use(express.json());
app.use(express.urlencoded({ extended: true }));

async function getAccessToken() {
  const url = `https://login.microsoftonline.com/${process.env.TENANT_ID}/oauth2/v2.0/token`;

  const params = new URLSearchParams();
  params.append("client_id", process.env.CLIENT_ID);
  params.append("client_secret", process.env.CLIENT_SECRET);
  params.append("scope", "https://graph.microsoft.com/.default");
  params.append("grant_type", "client_credentials");

  const res = await axios.post(url, params);
  return res.data.access_token;
}

app.post("/send", async (req, res) => {
  try {
    const token = await getAccessToken();

    const mail = {
      message: {
        subject: "New Contact Form Submission",
        body: {
          contentType: "HTML",
          content: `
           

Name: ${req.body.name}


           

Email: ${req.body.email}


           

Message: ${req.body.message}


          `
        },
        toRecipients: [
          { emailAddress: { address: "sales@yourdomain.com" } }
        ]
      }
    };

 

    await axios.post(
      `https://graph.microsoft.com/v1.0/users/${process.env.SENDER_EMAIL}/sendMail`,
      mail,
      {
        headers: {
          Authorization: `Bearer ${token}`,
          "Content-Type": "application/json"
        }
      }
    );

    res.send("Mail sent successfully");
  } catch (err) {
    console.error(err.response?.data || err.message);
    res.status(500).send("Mail failed");
  }
});

app.listen(3000, () => console.log("Mailer running"));
 

 

Restart Node App in cPanel

  • Go back to Setup Node.js App

  • Click Restart App

Your app now runs internally on port 3000
cPanel automatically proxies it.

 

Microsoft Entra Permissions (Must)

In Entra ID => App Registration:

  • API Permissions => Microsoft Graph

  • Application Permission

 

Mail.Send
 

 

Mail should send now.

Need Support: Book a Meeting

 

 

Share:
Related Blogs
Microsoft Office 365 SMTP Integration for Website Contact Forms (2026 Guide – OAuth 2.0 & Graph API)

Microsoft Office 365 SMTP Integration for Website Contact Forms (2026 Guide – OAuth 2.0 & Graph API)

If your website contact form suddenly stopped sending emails using Microsoft Office 365 SMTP, you are not alone.

Effortlessly Manage Team Emails with Google Workspace Shared Inboxes

Effortlessly Manage Team Emails with Google Workspace Shared Inboxes

In today’s fast-paced business world, efficient communication is key to providing excellent customer service and maintaining team productivity.

Setting Up Microsoft Office 365 for Third-Party Email Clients Using App Passwords

Setting Up Microsoft Office 365 for Third-Party Email Clients Using App Passwords

If your Office 365 account has multi-factor authentication enabled, you will need an App Password to connect a third-party email client such as Thunderbird, Outlook, or Apple Mail to it. Follow this guide to configure the application

Our Partners