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 租户

相关推荐
LOVE️YOU1 小时前
Python 中 Tuple 为什么有时可 Hash,有时不可 Hash?
开发语言·python·哈希算法
李永奉1 小时前
C语言-指针函数与函数指针及回调函数的使用
c语言·开发语言
小oo呆1 小时前
【学习心得】迭代器和可迭代对象
开发语言·python
AC赳赳老秦1 小时前
采集行为合规自检:OpenClaw 自动校验 robots 协议与采集频率,规避违规采集风险
java·开发语言·c++·python·php·deepseek·openclaw
钱栈up1 小时前
mvn compile 卡死在 javac 阶段:一次类型不匹配的排查与修复
java·开发语言
迅猛龙办公室1 小时前
Python输出当前计算机的系统日期和时间
开发语言·前端·python
杨丰玮4182 小时前
C语言基础知识(一)————各类符号的含义与输入输出库(stdio)
c语言·开发语言
程序猿编码2 小时前
工业视觉多任务方案:可编程梯度信息视觉框架,训练评估 + C++ 部署完整实战
开发语言·c++·视觉·推理引擎
言乐63 小时前
Python实现语音审核模型
开发语言·python·django·virtualenv·pygame
朝朝辞暮i4 小时前
C++ 第 21 课:struct —— 把一组相关数据打包在一起
开发语言·c++·算法