Search code examples
outlookoutlook-web-addinsoutlook-restapi

Office-JS - Outlook addin not setting x-headers in outlook 2019


Based on Set custom header (x-header) on Outlook compose mail with JS addin post, I used the following code to set a custom x-header when composing emails in OWA or Outlook 2019.

function addCustomHeadersAsync(classificationMarking) {
    return new Office.Promise(function (resolve, reject) {
        try {
            /* The itemId property is not available in compose mode. If an item identifier is required, 
            the saveAsync method can be used to save the item to the store, which will return the item identifier in the asyncResult.value parameter in the callback function.*/
            Office.context.mailbox.item.saveAsync(function (saveAsyncResult) {
                /* The getCallbackTokenAsync method makes an asynchronous call to get an opaque token from the Exchange Server that hosts the user's mailbox. 
                The lifetime of the callback token is 5 minutes. The token is returned as a string in the asyncResult.value property.*/
                Office.context.mailbox.getCallbackTokenAsync({ isRest: true }, function (getCallbackTokenAsyncResult) {
                    var ewsId = saveAsyncResult.value;
                    var token = getCallbackTokenAsyncResult.value;
                    var restId = Office.context.mailbox.convertToRestId(ewsId, Office.MailboxEnums.RestVersion.v2_0);
                    var getMessageUrl = Office.context.mailbox.restUrl + '/v2.0/me/messages/' + restId;
                    
                    // The PropertyId for PS_INTERNET_HEADERS is  {00020386-0000-0000-C000-000000000046}.
                    // https://learn.microsoft.com/en-us/office/client-developer/outlook/mapi/commonly-used-property-sets?redirectedfrom=MSDN
                    // https://stackoverflow.com/questions/38214197/set-a-custom-header-with-outlook-office-365-rest
                    var securityHeaders = JSON.stringify({
                        SingleValueExtendedProperties: [
                            {
                                PropertyId: "String {00020386-0000-0000-C000-000000000046} Name X-Custom-header",
                                Value: classificationMarking
                            }
                        ]
                    });

                    // https://learn.microsoft.com/en-us/previous-versions/office/office-365-api/api/version-2.0/extended-properties-rest-operations#ExtendedpropertyoperationsCreateextendedpropertyinanewitem
                    // PATCH request is required to create an extended property in an existing item
                    var xhr = new XMLHttpRequest();
                    xhr.open('PATCH', getMessageUrl);
                    xhr.setRequestHeader("Accept", "application/json");
                    xhr.setRequestHeader("Content-Type", "application/json");
                    xhr.setRequestHeader("Authorization", "Bearer " + token);
                    xhr.onload = function (e) {
                        //console.log(this.response);
                        resolve();
                    }
                    xhr.send(securityHeaders);
                });
            });
        }
        catch (error) {
            reject("Unable to set email custom security headers");
        }
    })
}

As on-premises Office 2019 + Exchange 2016 only supports API 1.5, I'm not able to use the new setCustomHeaders function which has been available since API 1.8 (https://learn.microsoft.com/en-us/office/dev/add-ins/outlook/internet-headers)

Everything works in https://outlook.office.com/mail/inbox & on-premises OWA (Exchange2016).

When using Outlook 2019 (online mode) :

  1. The saveAsync function saves the draft
  2. The XMLHttpRequest correctly sets the X-Custom-header : when calling the Exchange 2016 REST just after trying to set the XMLHttpRequest with a GET request, Exchange correctly reports the SingleValueExtendedProperties beeing set
  3. After this step, when manually saving or sending the email, the SingleValueExtendedProperties seems to be removed or overwritten by Outlook which doesnt seems to be aware of this SingleValueExtendedProperties having been added to the draft email.
  4. Same behavior noticed with Oulook 2019 on Office 365

Is this code correct to set custom email headers using SingleValueExtendedProperties with Outlook 2019 ?

How can I make Outlook 2019 aware of the new SingleValueExtendedProperties / x-header added to the draft message though the Exchange REST API ?

Edit 11/10/2021 : tested with makeEwsRequestAsync & test summary

Outlook 2019
build 2108 (Office 365)
Outlook
on the web
Outlook 2019
build 1808 (Exchange 2016)
OWA
Exchange 2016
Exchange REST API XMLHttpRequest X-Custom-header correctly set server side but removed when sending the draft email from Outlook. If opening and sending the draft from OWA after having set the X-header from the addin in Outlook, X-Custom-header is preserved OK X-Custom-header correctly set server side but removed when sending the draft email from Outlook. If opening and sending the draft from OWA after having set the X-header from the addin in Outlook, X-Custom-header is preserved OK
makeEwsRequestAsync() OK OK X-Custom-header correctly set server side but removed when sending the draft email from Outlook. If opening and sending the draft from OWA after having set the X-header from the addin in Outlook, X-Custom-header is preserved EWS request proxy error

Solution

  • What you are trying to do is not possible on Win32 Outlook Client. Your Step #2 (XMLHttpRequest) effectively creates two version of the item, one on the client and one on the server. When the item is eventually sent, one will overwrite the other (most likely the one sent from the client), and overrides the changes that you made.

    setCustomHeaders in 1.8 was created to address this problem. setCustomHeaders, actually does not rely on the server for it's functionality, so it should work as long as your client supports 1.8.

    Office 2019 (retail) does support 1.8. Office 2019 (volume-licensing) does not.

    https://learn.microsoft.com/en-us/office/dev/add-ins/reference/requirement-sets/outlook-api-requirement-sets

    Users on the volume licensed version will need to upgrade to get this support.