Search code examples
office-jsoutlook-web-addins

Exception in getAttachmentContentAsync due to inactivity, unable to catch


Using office-js I am developing an Outlook add-in, consisting in a taskpane where I need to get all the information (basic info, body and attachments) about the current item (email) to send it to a web service. I am using Angular 8 and referencing the API with: <script type="text/javascript" src="https://appsforoffice.microsoft.com/lib/1/hosted/office.js"></script>

I have no problem getting the body using the function Office.item.body.getAsync(options, callbackFunction) and I am able to get the attachments using Office.item.getAttachmentContentAsync(item.attachments[i], options, callbackFunction).

The problem comes when I leave the Outlook Web opened in the same message for a few minutes. After that, when I execute my add-in, calls to Office.item.getAttachmentContentAsyncstart to fail, writing in the console the error: Uncaught (in promise) TypeError: Failed to fetch. The main problem is that I am not able to catch the exception, so my add-in gets stuck waiting forever, because the callbackFunction is never called, and adding a surrounding try catch doesn't work, because the error seems to be in an internal promise of the office-js library. Note that even in this situation, calls to get the body still work without problem.

As I can see using the Chrome tools, the normal behaviour of the call to Office.item.getAttachmentContentAsync is one request to: https://attachment.outlook.live.net/owa/MSA:[...]/service.svc/s/GetFileAttachment?id=[...] returning a 200 status code.

But when the session is "expired", the request to https://attachment.outlook.live.net/owa/MSA:[...]/service.svc/s/GetFileAttachment?id=[...] returns a 302 to https://outlook.live.com/owa/MSA:[...]/service.svc/s/GetAttachmentDownloadToken?redirect=[...] that returns a 440 Login Timeout.

I would like to know if there is any way I can avoid the error (check if the session is already expired, force to refresh the session, etc.) or if there is any way to catch the error (avoiding the add-in to be get stuck), in order to notify the user about the problem.

The callbackFunction is quite simple:

private static callbackFunction(asyncResult: Office.AsyncResult<any>){
    if (asyncResult.status == Office.AsyncResultStatus.Succeeded){
        [...]
    }
    else{
        //Never called
    }
}

Edit: I just realized that using the add-in in the Outlook for Android, with the same code there is no way to get a response from Office.item.getAttachmentContentAsync, but I do get the body content of the email. In Outlook Web refreshing the page temporary fixes the problem, but in Outlook for Android restarting the app doesn't help. I am not sure if the error is the same 440 Login timeout in Android, as I am not able to debug the add-in there.

Edit2: In Outlook Desktop for Windows I am unable to reproduce the issue, it works fine.


Solution

  • As an alternative, I changed my code to start using the REST API instead of Office.context.mailbox.item.getAttachmentContentAsync.

    This code, adapted from the example in https://learn.microsoft.com/en-us/javascript/api/outlook/office.mailbox?view=outlook-js-preview#resturl, always works, even in Android/iOS, that don't support the RequerimentSet 1.8 (needed to use getAttachmentContentAsync).

    Office.context.mailbox.getCallbackTokenAsync({ isRest: true }, function (result) {
        var ewsId = Office.context.mailbox.item.itemId;
        var token = result.value;
        var restId = Office.context.mailbox.convertToRestId(ewsId, Office.MailboxEnums.RestVersion.v2_0);
        var getAttachmentsUrl = Office.context.mailbox.restUrl + '/v2.0/me/messages/' + restId + '/attachments';
    
        var headers = { 'Authorization' : 'Bearer ' + token };
        var options = { headers: headers };
        myContext.httpClient.get<AttachmentsResponse>(getAttachmentsUrl, options)
            .subscribe(...);
    });