根本原因是php-ews/php-ews库已废弃,packagist移除该包;应改用活跃维护的garethp/php-ews,安装命令为composer require garethp/php-ews,并严格使用oauth 2.0、完整wsdl地址及正确命名空间。

composer require php-ews/php-ews 报错找不到包
根本原因是这个库早已废弃,Packagist 上已移除 php-ews/php-ews,也不是官方维护项目。你搜到的 GitHub 仓库(如 jamesiarmes/php-ews)自 2019 年起停止更新,PHP 8.0+ 下大量函数废弃(如 mysql_connect 风格写法)、XML 解析逻辑与现代 EWS 接口不兼容,composer require 自然失败。
常见错误现象:Package php-ews/php-ews not found 或 Your requirements could not be resolved。别试 dev-master 或手动 clone —— 即使装上,运行时大概率报 Call to undefined function xml_parser_create()(PHP 8.4 已彻底移除该函数)或 SOAP 响应解析失败。
- 替代方案只有两个:用微软官方支持的 Graph API(推荐),或改用仍在维护的轻量封装库
garethp/php-ews -
garethp/php-ews是目前唯一活跃分支,支持 PHP 8.0–8.4,适配 Exchange Online 和本地 Exchange 2016+,但注意它不叫php-ews,包名是garethp/php-ews - 安装命令必须写全:
composer require garethp/php-ews;别漏掉garethp/前缀,否则还是 404
require garethp/php-ews 后 new ExchangeWebServices() 报 Class not found
不是没装成功,是自动加载路径或命名空间写错了。这个库不走 PSR-4 标准,类文件在 src/ 下但命名空间是 Garethp\ews,不是 PHP-EWS 或 PhpEws。
实操要点:
Outlook 日历 / Microsoft 365 日历 SECURE API CLI。当用户需要列出、搜索或读取 Outlook / Microsoft 365 日历事件,以及创建……
- 入口脚本开头必须包含:
require __DIR__ . '/vendor/autoload.php';(用__DIR__避免相对路径失效) - 实例化必须用完整命名空间:
new Garethp\ews\ExchangeWebServices(...),不能简写为new ExchangeWebServices() - 如果用了
use,得这样写:use Garethp\ews\ExchangeWebServices;,然后new ExchangeWebServices(...) - 别手动
require src/ExchangeWebServices.php—— 这会绕过 Composer autoloader,且类注册不完整
连接 Exchange Online 时 Authentication failed 或 SSL handshake failed
Exchange Online(Outlook.com / Office 365)已全面弃用 Basic Auth,强制要求 OAuth 2.0。你填用户名密码、开 IMAP/POP3 权限都没用,Authentication failed 是必然结果。
必须做的事:
- 在 Azure AD 应用注册门户创建应用,添加
https://outlook.office365.com/.default权限(Delegated 或 Application,看你是代理用户还是后台服务) - 获取
client_id、client_secret、tenant_id,用 Microsoft Identity Platform 获取 access token -
garethp/php-ews不内置 OAuth 流程,得自己调https://login.microsoftonline.com/{tenant}/oauth2/v2.0/token拿 token,再传给ExchangeWebServices构造函数的token参数 - 别设
$connection->setUsername()和$connection->setPassword()—— 这些字段在 OAuth 模式下被忽略,还可能触发额外鉴权失败
发邮件/读收件箱返回空数组或 401 Unauthorized
不是代码逻辑错,是 EWS URL 或权限配置不对。Exchange Online 的 EWS endpoint 不再是 https://outlook.office365.com/EWS/Exchange.asmx,而是动态解析的,且必须带 ?wsdl 后缀才能加载 WSDL。
关键参数:
- 构造
ExchangeWebServices时,$server必须是完整 WSDL 地址,例如:https://outlook.office365.com/EWS/Exchange.asmx?wsdl - OAuth token 必须通过
Authorization: Bearer {token}header 传递,garethp/php-ews默认支持,但需确认你传入的是有效、未过期的 token(有效期通常 1 小时) - 权限不足会导致静默返回空数据,不是报错。比如只申请了
Mail.Read却调用SendItem,API 直接返回 401,而非明确提示权限缺失 - 调试建议:开启
ExchangeWebServices::setTrace(true),然后echo $connection->__getLastRequest()和__getLastResponse()看原始 SOAP 请求和响应,比猜快得多
require __DIR__ . '/vendor/autoload.php';
use Garethp\ews\ExchangeWebServices;
$ews = new ExchangeWebServices([
'server' => 'https://outlook.office365.com/EWS/Exchange.asmx?wsdl',
'token' => 'your-access-token-here',
'version' => 'Exchange2016'
]);
try {
$response = $ews->getFolder([['FolderId' => ['DistinguishedFolderId' => ['Id' => 'inbox']]]]);
var_dump($response);
} catch (\Exception $e) {
echo $e->getMessage();
}
Exchange Online 的 EWS 调用链比 SMTP 复杂得多,OAuth、WSDL、SOAP 版本、权限粒度都得对齐。一个参数错,整个请求就静默失败,没有中间态。php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!










