PHP发送outlook(微软)OAuth 2.0企业版邮箱验证码

一、准备工作:

  1. 登录Azure 门户,使用企业版 Microsoft 365 管理员账号(或拥有应用注册权限的账号)登录。
  2. 在左侧导航栏搜索并进入「Azure Active Directory」→ 「应用注册」→ 「新注册」。
  3. 填写应用注册信息:
    • 名称:自定义(如「PHPMailer-Office365 - 邮件发送」)
    • 支持的账户类型:选择「仅此组织目录中的账户(你的企业域名 - 单一租户)」(企业版专属,更安全)
    • 重定向 URI:选择「Web」,填写你的应用回调地址(如https://你的域名/oauth-callback.php,后续需创建该回调文件)
  4. 注册完成后,记录核心参数(后续代码需使用):
    • 应用(客户端)ID:即client_id
    • 目录(租户)ID:即tenant_id
  5. 配置应用权限:
    • 进入该应用 → 「API 权限」→ 「添加权限」→ 搜索并选择「Microsoft Graph」(注意:不是 Outlook SMTP,OAuth 2.0 依赖 Microsoft Graph API)
    • 选择「应用权限」(后台发送邮件无需用户交互,优先选择;若需用户授权后发送,选择「委托权限」)
    • 勾选 Mail.Send(发送邮件的核心权限)→ 「添加权限」
    • 点击「授予管理员同意(你的企业域名)」(必须完成此步骤,否则权限不生效)
  6. 创建客户端密码:
    • 进入该应用 → 「证书和密码」→ 「客户端密码」→ 「新建客户端密码」
    • 填写描述、选择有效期 → 「添加」
    • 立即记录密码值(即client_secret,仅显示一次,关闭页面后无法再查看)

完成以上步骤即可获得

Tenant ID(租户ID):5f567e67-********-f94036056090

Client ID(应用 ID):a5a85bb5-********-f97a545f19f5

Client Secret(应用密钥):Yrs8Q~aXO6ju2T-********_NCeUtcn6

用来获取发送邮件时的access_token

二、安装扩展

php 复制代码
# 阿里云镜像(推荐,速度最快)
composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/
# 然后再执行依赖安装命令
composer require phpmailer/phpmailer league/oauth2-client

三、完整代码

php 复制代码
<?php
require '../api/vendor/autoload.php';
use League\OAuth2\Clsient\Provider\Exception\IdentityProviderException;

// 配置参数
$TenantId = '';//Tenant ID(租户ID)
$clientId = '';//Client ID(应用 ID)
$clientSecret = '';//Client Secret(应用密钥)
$fromEmail = '';//发送邮箱
$toEmail = '';//目标邮箱

// 1. 用客户端凭证流获取Access Token(无需refresh_token)
$tokenUrl = "https://login.microsoftonline.com/$TenantId/oauth2/v2.0/token";
$postData = [
    'grant_type' => 'client_credentials',
    'client_id' => $clientId,
    'client_secret' => $clientSecret,
    'scope' => 'https://graph.microsoft.com/.default'
];

$ch = curl_init();
curl_setopt_array($ch, [
    CURLOPT_URL => $tokenUrl,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => http_build_query($postData),
    CURLOPT_HTTPHEADER => ['Content-Type: application/x-www-form-urlencoded']
]);
$tokenResponse = json_decode(curl_exec($ch), true);
curl_close($ch);

if (!isset($tokenResponse['access_token'])) {
    echo "Token获取失败:" . json_encode($tokenResponse) . "\n";
    exit;
}
$token = $tokenResponse['access_token'];

// 2. 调用Graph API发送邮件
$mailData = [
    'message' => [
        'subject' => '【登录验证码】',
        'body' => ['contentType' => 'HTML', 'content' => '测试发送'],
        'toRecipients' => [['emailAddress' => ['address' => $toEmail]]],
        'from' => ['emailAddress' => ['address' => $fromEmail]]
    ],
    'saveToSentItems' => true
];

$ch = curl_init();
curl_setopt_array($ch, [
    CURLOPT_URL => "https://graph.microsoft.com/v1.0/users/$fromEmail/sendMail",
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => json_encode($mailData),
    CURLOPT_HTTPHEADER => [
        "Authorization: Bearer $token",
        "Content-Type: application/json"
    ]
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

if ($httpCode === 202) {
    echo "邮件发送成功!";
} else {
    $error = json_decode($response, true);
    echo "失败原因:" . ($error['error']['message'] ?? '未知错误') . "\n";
}

四、关键前提(必须满足)

无论用哪种方式,都需要:

  1. Azure 应用已添加Mail.Send权限(应用权限,不是委派权限)

  2. 全局管理员已点击 "授予管理员同意"

  3. 发件人邮箱($fromEmail )属于该 Azure 租户

相关推荐
BingoGo2 天前
PHP 泛型之殇 泛型 RFC 提案被拒绝
后端·php
JaguarJack2 天前
PHP 泛型之殇 泛型 RFC 提案被拒绝
后端·php
用户3074596982073 天前
PHP 扩展——从入门到理解
php
鹏仔先生4 天前
拷贝漫画APP下载页PHP程序,后台带免费AI写作
php
LDR0064 天前
Type-C 快充全面升级!LDR6601 赋能个人护理便携电机,重塑剃须刀 / 理发器新体验
c语言·开发语言
雪碧聊技术4 天前
Tree.js是什么?一文讲透
开发语言·javascript·ecmascript
码云数智-园园4 天前
C++20 Modules 模块详解
java·开发语言·spring
swordbob4 天前
NIO的channel中什么是 fd(File Descriptor,文件描述符)
java·开发语言·nio
源分享4 天前
Java线程同步的多种实现方法(非常详细)
java·开发语言·jvm
Luminous.4 天前
C语言--day30
c语言·开发语言