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

Outlook加载项部分客户端fetch()调用无返回如何调试

Outlook加载项fetch请求无响应问题排查

问题背景

  • 基于TypeScript开发的现代风格Outlook加载项,核心逻辑为用户发送邮件时,从Azure Web函数拉取XML配置数据
  • 绝大多数客户环境运行正常,仅某客户组织内部分客户端调用fetch()时无返回结果,安装加载项后这类客户端会卡在邮件发送流程,无法正常发信
  • 经Application Insights链路排查确认:异常客户端正常发起了fetch()请求,服务端Azure Web函数也已收到请求并正常返回对应XML数据,但异常机器上的fetch()调用始终处于pending状态,无任何异常、错误信息抛出
  • 已对比正常/异常客户端表层环境参数:操作系统均为Windows 10、Edge浏览器版本均为103.0、Outlook JavaScript SDK版本均为2.5.9,无明显差异

问题相关代码

let myXMLData: string = "";
try {
    debug.Log("Rules.FetchConfigurationFile", "Using fetch");

    const response = await fetch(configurationURL, {
        method: "POST",
        mode: "cors",
        //headers: { "Content-Type": "application/json"},
        body: encodeURIComponent(emailAddress)
    });
    if (!response.ok) {
        myXMLData = "Not found";
        debug.Log("Rules.fetchConfigurationFile", "Rules not found. Response: " + response.status);
        throw response.statusText;
    } else {
        myXMLData = await response.text();
        debug.Log("Rules.fetchConfigurationFile", "Loaded Rules: " + myXMLData);
    }
} catch (ex) {
  debug.LogException("Error occurred in Rules.FetchConfigurationFile", ex);
}
//
// And decode any encoded XMLData.
//
let decodedXMLData: string = decodeURIComponent(myXMLData);
return decodedXMLData;

注:debug.Log()为Application Insights日志上报方法

日志对比

正常客户端日志(UTC时间)

7/6/2022, 10:53:23.946 PM Rules.FetchConfigurationFile: Using fetch
7/6/2022, 10:53:25.076 PM Rules.fetchConfigurationFile: Loaded Rules: [内容省略]

异常客户端日志(UTC时间)

7/6/2022, 10:48:59.829 PM Rules.FetchConfigurationFile: Using fetch

  • 异常客户端无后续执行日志、无异常/错误上报,服务端侧可确认已正常返回所需XML数据

排查调试步骤

  • 第一步先加超时兜底,避免阻塞用户发信
    现有代码无超时控制,请求挂起会直接卡死整个邮件发送流程,先通过AbortController增加超时逻辑,超时后走降级流程,不阻塞用户正常发信,同时增加超时场景的日志标记:
    const controller = new AbortController();
    // 10秒超时兜底
    const timeoutId = setTimeout(() => controller.abort(), 10000);
    try {
        const response = await fetch(configurationURL, {
            signal: controller.signal,
            method: "POST",
            mode: "cors",
            // 显式声明urlencoded请求体类型,避免代理拦截
            headers: { "Content-Type": "application/x-www-form-urlencoded" },
            body: encodeURIComponent(emailAddress)
        });
        // 原有响应处理逻辑保持不变
    } catch (ex) {
        if (ex.name === 'AbortError') {
            debug.Log("Rules.FetchConfigurationFile", "Fetch request timed out after 10s");
        }
        debug.LogException("Error occurred in Rules.FetchConfigurationFile", ex);
    } finally {
        clearTimeout(timeoutId);
    }
    
  • 第二步拆分日志点位,定位挂死阶段
    现有日志只在请求发起前打了点,无法判断是请求阶段挂死还是读响应体阶段挂死,把两个阶段拆开打点:
    debug.Log("Rules.FetchConfigurationFile", "Start send fetch request");
    const response = await fetch(/* 配置参数 */);
    // 能打印下面这条日志,说明已经拿到响应头,挂死发生在读取响应体阶段
    debug.Log("Rules.FetchConfigurationFile", `Got response header, status code: ${response.status}`);
    const responseText = await response.text();
    // 能打印下面这条日志,说明响应体读取完成
    debug.Log("Rules.FetchConfigurationFile", "Got full response body");
    
    如果拿不到响应头日志,说明请求在网络层被拦截挂死;如果能拿到响应头日志但拿不到响应体日志,说明响应体在传输过程中被本地拦截层丢弃。
  • 第三步排查本地流量拦截层
    这类服务端已正常返回、客户端无报错永久pending的场景,90%以上是本地企业安全软件吞包导致:
    • 排查异常机器是否安装了端点防护、SSL流量审计、上网行为代理类工具(常见的企业级工具包括Zscaler、Symantec、国内的天擎、深信服EDR等),这类工具会注入系统网络栈,对HTTPS流量做中间人解密检测,当请求格式、响应内容不符合其内置规则时,会直接丢弃响应包,既不返回给上层应用,也不抛出网络错误
    • 临时退出上述安全软件/代理做验证,或者将Azure函数的域名加到这类工具的SSL解密白名单、流量拦截白名单中测试
    • 在异常机器上用Fiddler/Charles抓加载项的请求流量,看抓包工具能否正常收到服务端返回的XML响应,如果抓包工具能收到响应但加载项内拿不到,即可确认是本地拦截层的问题
  • 第四步排查Webview运行时与组策略限制
    现代Outlook加载项运行在嵌入式Webview中,即使表层Edge版本号一致,企业组策略也可能给Webview配置不同的安全限制:
    • 确认异常机器上Outlook使用的Webview runtime版本,是否和正常机器一致,有没有被组策略强制使用旧内核
    • 检查异常机器的Windows安全区域设置、Edge组策略,有没有将Azure函数域名划入高安全等级区域,限制跨域POST请求、限制特定大小的响应体接收
    • 检查Azure函数返回的CORS响应头,确保Access-Control-Allow-Origin值和加载项域名精准匹配,不要在带身份认证的场景下使用通配符*,避免Webview跨域校验时静默拦截响应

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 20:45:37