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

如何让Outlook Add-In切换邮件项时不重新加载?

针对OWA中Outlook Add-In会话丢失问题的解决方案

这个问题确实是OWA下Outlook插件开发的常见痛点——毕竟桌面版和网页版的任务窗格运行机制差异很大,OWA切换邮件时会销毁并重建任务窗格的iframe,直接导致会话Cookie重置。我整理了几个经过验证的解决方案,你可以根据自己的场景选择:


方案一:用Office.js的RoamingSettings存储会话信息

RoamingSettings是Office提供的官方跨会话存储机制,数据会绑定到用户的Office账户,不仅能在OWA的不同插件实例间共享,甚至跨设备也能同步(比如用户换电脑登录OWA也能读取到)。适合存储轻量化的会话令牌或用户标识。

代码示例:

// 登录成功后保存会话信息
function saveSession(token, userId) {
  const sessionData = { token: token, userId: userId };
  Office.context.roamingSettings.set('crm_session', sessionData);
  Office.context.roamingSettings.saveAsync(function(result) {
    if (result.status === Office.AsyncResultStatus.Succeeded) {
      console.log('会话已保存');
    }
  });
}

// 插件初始化时自动读取会话并登录
Office.initialize = function() {
  const savedSession = Office.context.roamingSettings.get('crm_session');
  if (savedSession && savedSession.token) {
    // 调用第三方CRM的自动登录接口
    autoLoginToCRM(savedSession.token);
  } else {
    // 显示登录界面
    renderLoginUI();
  }
};

// 登出时清除会话
function handleLogout() {
  Office.context.roamingSettings.remove('crm_session');
  Office.context.roamingSettings.saveAsync();
  // 同时清除CRM侧的会话
  logoutFromCRM();
}

⚠️ 注意:RoamingSettings有1MB左右的存储上限,不要存敏感明文数据,建议对令牌做加密处理后再存储。


方案二:结合浏览器localStorage实现同标签页会话保持

如果你的用户主要在同一个OWA标签页内操作,localStorage也是可行的选择——同一个浏览器标签页下,即使iframe被重建,localStorage的数据依然会保留。缺点是跨标签页或跨设备无法同步,但胜在实现简单。

代码示例:

// 登录成功后写入localStorage
function onLoginSuccess(token) {
  localStorage.setItem('crm_addin_session', JSON.stringify({ token: token }));
}

// 初始化时读取并自动登录
Office.initialize = function() {
  const sessionStr = localStorage.getItem('crm_addin_session');
  if (sessionStr) {
    const { token } = JSON.parse(sessionStr);
    autoLoginToCRM(token);
  }
};

// 登出时清除
function handleLogout() {
  localStorage.removeItem('crm_addin_session');
  logoutFromCRM();
}

方案三:集成Single Sign-On (SSO) 实现无感知登录

如果你的第三方CRM应用支持Azure AD认证,优先推荐这个方案——利用Office.js的SSO能力,让用户通过Outlook的已登录身份自动完成CRM的登录,完全不需要手动输入账号密码,体验最优。

代码示例:

Office.initialize = function() {
  // 初始化时尝试获取Azure AD令牌
  getOfficeAccessToken();
};

function getOfficeAccessToken() {
  Office.context.auth.getAccessTokenAsync({
    allowSignInPrompt: true,
    allowConsentPrompt: true,
    forMSGraphAccess: false // 如果CRM用自己的AD租户,设为false
  }, function(result) {
    if (result.status === Office.AsyncResultStatus.Succeeded) {
      const accessToken = result.value;
      // 将令牌传给CRM的认证接口完成自动登录
      loginToCRMWithSSO(accessToken);
    } else {
      console.error('获取令牌失败:', result.error.message);
      renderLoginUI();
    }
  });
}

这个方案需要在插件manifest中配置对应的权限和认证域名,安全性和用户体验都是最好的。


方案四:用Dialog API保持登录会话

如果第三方CRM的登录流程必须在独立窗口完成,可以用Office.js的Dialog API打开登录弹窗,登录成功后将令牌传回任务窗格并存储,后续插件重建时读取令牌自动登录。

代码示例:

function openLoginDialog() {
  Office.context.ui.displayDialogAsync('https://your-crm-domain.com/login', {
    height: 60,
    width: 50,
    displayInIframe: false
  }, function(result) {
    const dialog = result.value;
    // 监听登录窗口传回的消息
    dialog.addEventHandler(Office.EventType.DialogMessageReceived, function(args) {
      const sessionToken = args.message;
      // 保存令牌到RoamingSettings
      saveSession(sessionToken, 'user-id-from-crm');
      dialog.close();
      autoLoginToCRM(sessionToken);
    });
  });
}

⚠️ 注意:需要在插件manifest的AppDomains节点中添加CRM的域名,否则会被Office阻止弹窗。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 08:50:07