You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP使用IMAP和OAuth访问Outlook邮箱遇连接超时问题求助

PHP-IMAP库连接Office365 IMAP(OAuth认证)多次运行后超时问题

问题重现

微软已移除IMAP连接的Basic Auth,我们正将PHP代码转换为使用微软OAuth API及第三方库php-imap。已成功通过API获取access_token并传入该库,脚本连续运行两次均正常,但后续运行时无法连接,返回操作超时错误。
错误信息:
stream_socket_client(): unable to connect to ssl://outlook.office365.com:993 (Operation timed out) in php-imap/src/Connection/Protocols/Protocol.php:204

相关代码:

$instance = new ClientManager();
$this->client = $instance->make([
    'host' => "outlook.office365.com",
    'port' => 993,
    'encryption' => 'ssl',
    'validate_cert' => false,
    'username' => $this->mailboxUsername,
    'password' => $access_token,
    'protocol' => 'imap',
    'authentication' => "oauth",
]);
try {
    //  Connect to the IMAP Server
    $this->client->connect();
}catch (Exception $e) {
    echo 'Exception : ',  $e->getMessage(), "\n";
}

private function getAccessTokenUsingRefreshToken()
{
    $CLIENT_ID      = $this->azure_settings['client_id'];
    $CLIENT_SECRET  = $this->azure_settings['secret_value'];
    $TENANT         = $this->azure_settings['tenant_id'];
    $REFRESH_TOKEN  = $this->azure_settings['refresh_token'];

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

    $param_post_curl = [
        'client_id'     => $CLIENT_ID,
        'client_secret' => $CLIENT_SECRET,
        'refresh_token' => $REFRESH_TOKEN,
        'grant_type'    => 'refresh_token'
    ];

    $ch = curl_init();

    curl_setopt($ch,CURLOPT_URL,$url);
    curl_setopt($ch,CURLOPT_POSTFIELDS, http_build_query($param_post_curl));
    curl_setopt($ch,CURLOPT_POST, 1);
    curl_setopt($ch,CURLOPT_RETURNTRANSFER, true);

    //  ONLY USE CURLOPT_SSL_VERIFYPEER AT FALSE IF YOU ARE IN LOCALHOST !!!
    //  NOT IN LOCALHOST ? ERASE IT !
    curl_setopt($ch,CURLOPT_SSL_VERIFYPEER, false);

    $result = curl_exec($ch);
    $access_token = json_decode($result)->access_token;

    return $access_token;
}

解决方案

1. 确保连接资源正确释放

php-imap的Client实例若未主动断开,会持续占用本地TCP连接资源,多次运行后可能达到连接上限导致超时。需在操作完成后强制断开连接:

try {
    $this->client->connect();
    // 执行邮件读取/处理逻辑...
    $this->client->disconnect(); // 用完立即释放连接
} catch (Exception $e) {
    echo 'Exception : ',  $e->getMessage(), "\n";
    // 异常场景也需清理连接资源
    if ($this->client->isConnected()) {
        $this->client->disconnect();
    }
}

2. 完善Access Token获取的错误处理

当前代码未处理OAuth刷新失败的情况,若返回无效的access_token,库的重试逻辑可能导致超时。添加错误校验:

$result = curl_exec($ch);
if (!$result) {
    throw new Exception('获取Access Token失败: ' . curl_error($ch));
}
$response = json_decode($result, true);
if (isset($response['error'])) {
    throw new Exception('OAuth认证错误: ' . $response['error_description']);
}
$access_token = $response['access_token'];
curl_close($ch); // 关闭curl资源避免泄漏
return $access_token;

3. 调整连接超时参数

php-imap默认超时较短,网络波动时易触发超时。在Client配置中显式设置超时:

$this->client = $instance->make([
    // 原有配置项...
    'timeout' => 30, // 设置30秒超时,可根据网络情况调整
]);

4. 排查网络与防火墙限制

  • 短时间内多次连接可能触发Office365的IP限流,可尝试降低连接频率或更换网络测试
  • 检查本地服务器防火墙/安全组是否限制了993端口的出站连接频率

5. 生产环境启用证书验证

当前validate_cert => false的配置会降低连接安全性,甚至导致服务器拒绝连接。生产环境建议开启:

'validate_cert' => true,

若开启后出现证书错误,需确保服务器安装了完整的CA证书包。

内容的提问来源于stack exchange,提问作者Parampal Pooni

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 17:45:49