何时在 Outlook 加载项中使用 EWS 与其他 API 的持久传奇

The enduring saga of when to use EWS vs the Rest API in an Outlook Add-in

这个问题是基于 我问的,但从那以后有了更多的细节和经验。

首先是一些背景知识,我有一个 Outlook 插件,它应该转发用户消息,然后将消息移动到特定文件夹。这需要在 OWA 和 Outlook 2016 环境中为 on Prem Exchange 工作。它也应该适用于这两个以前的客户端,以及适用于 O365 用户的 Outlook 移动应用程序。

我的具体问题归结为检测何时使用 EWS 与其他 API(甚至 MS Graph API)。

这是我的代码片段:

Office.initialize = function() {
    $(document).ready(function() {
        $('#forward').click(forwardMessage);
    });
}; 

function forwardMessage() {
    if(Office.context.mailbox.restUrl) { // The problem child
        forwardEWS(); // Works like a charm
    } else {
        forwardRest(); // Works fine for O365 users
    }
}

function forwardRest() {
    var restHost = Office.context.mailbox.restUrl;
    var restId = getItemRestId();

    Office.context.mailbox.getCallbackTokenAsync({isRest: true}, function(result){
        if (result.status === "succeeded") {
            var accessToken = result.value;

            $.ajax({
                url: restHost + '/v2.0/me/messages/' + restId + '/forward',
                type: 'post',
                headers: {'Authorization': 'Bearer ' + accessToken},
                contentType: 'application/json',
                data: JSON.stringify({
                    'ToRecipients': [
                        {'EmailAddress': { 'Address': 'user@outlook.com' }}
                    ]
                })
            }).done(function (response) {
                sidepane_status('success', 'Message forwarded.');

                moveRest(restHost, accessToken, restId);

            }).fail(function(err) {
                sidepane_status('error', 'Could not forward message');
            });
        } else {
            sidepane_status('error', 'Could not get token');
        }
    });
}

function moveRest(restHost, accessToken, restId) {
    var folder = $('#ews_folder').val();
    $.ajax({
        url: restHost + '/v2.0/me/messages/' + restId + '/move',
        type: 'post',
        headers: {'Authorization': 'Bearer ' + accessToken},
        contentType: 'application/json',
        data: JSON.stringify({ 'DestinationId': folder })
    }).fail(function(err) {
        sidepane_status('error', 'Could not move message to ' + folder);
    });
}

function getItemRestId() {
    if (Office.context.mailbox.diagnostics.hostName === 'OutlookIOS') {
        return Office.context.mailbox.item.itemId;
    } else {
        return Office.context.mailbox.convertToRestId(
            Office.context.mailbox.item.itemId,
            Office.MailboxEnums.RestVersion.v2_0
        );
    }
}

在我之前的问题中,有人告诉我检查 Office.context.mailbox.restUrl 的 return。如果它 returned a URL 则可以使用 Rest API,如果不使用 EWS。这里的问题与我的 Prem Exchange 用户有关,在 OWA Office.context.mailbox.restUrl return 中没什么,很好,然后我只使用 EWS。但是在 Outlook 2016 Office.context.mailbox.restUrl returns https://exch1.mailhost.com/api 上。这会导致一些问题。

第一个是 Outlook 2016 中的 On Prem Exchange 用户 return 休息 URL 的情况。在此 article 之后,在 OfficeJS 的帮助下与 Rest API 进行交互,使用 On Prem 用户不可能通过 OfficeJS 使用 Office.context.mailbox.getCallbackTokenAsync({isRest: true}, function(result){ ... }); 依次获取访问令牌剩下的 API 就不能用了。

正如我最初问题中的评论所建议的那样,我会只使用 EWS。然而,这带来了移动的另一个问题。由此article,移动端不支持EWS,必须使用Rest。我确实了解 Prem 用户无法使用 Outlook 移动应用程序。

问题出现了,我无法找到一种方法来确定要使用什么 API 以及在什么情况下使用。如果我关闭 Office.context.mailbox.restUrl,那么 OWA 中的 On Prem 和 O365 用户将正确使用他们各自的 API,一切都是独角兽和彩虹。但是,对于 Outlook 2016 中的 On Prem 用户,它会在应该使用 EWS 时尝试使用 Rest API。最后,如果我完全依赖 EWS,那么 Addin 将不适用于 Outlook 移动客户端中的 O365 用户。

经过一个月的试验、错误和在 Microsoft 文档中畅游之后,我有点不知所措。任何帮助将不胜感激

是的,这是 restUrl 的一个已知问题,来自 docs:

Note: Outlook clients connected to on-premises installations of Exchange 2016 with a custom REST URL configured will return an invalid value for restUrl.

我知道这让事情变得有点复杂。我会说在目前的情况下,我会这样打电话:

  • 首先检查restUrl。如果未定义,则 EWS 是最佳选择。
  • 如果 restUrl 有值,则尝试 getCallbackTokenAsyncisRest: true。如果没有获得令牌,则回退到 EWS。

然后我会将此设置保存在用户的邮箱中(通过 Office.context.roamingSettings),这样在以后的运行中加载项可以跳过这个 "discovery" 阶段并只使用正确的 API 从头开始​​。

关于自我服务的旁注,我正在进行一个正在进行的副项目,以修改 https://docs.microsoft.com/en-us/outlook/add-ins/, so hopefully that will help with the whole "swimming in the sea" feeling. I'd love to get your feedback on what specifically is casting you adrift though, if you could contact me on Twitter 上的 Outlook 加载项文档,我们将不胜感激。