3

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
kjack51
  • 31
  • 5

1 Answers1

1

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.

  • I understand the XMLHttpRequest issue which is consistent in both retail (office 365) and VL versions but why is it failing on Outlook 2019 build 1808 when trying to set the internet header using **makeEwsRequestAsync()** ? Whith makeEwsRequestAsync(), outlook is aware of the updateitem operation and should update the draft as it does in build 2108, isn't it ? The **updateEwsHeader** function of https://github.com/davecra/easyEWS/blob/master/easyEws.js is used for the test – kjack51 Oct 12 '21 at 04:26
  • Depending on the answer to the previous question, is there any plan to backport API 1.8 support in Office 2019 VL build 1808 ? – kjack51 Oct 13 '21 at 05:53
  • There currently no plans for 1.8 to be backported to 2019 VL. Office 2021 is the VL version with that support. – Outlook Add-ins Team - MSFT Oct 13 '21 at 19:28
  • makeEwsRequestAsync() requests go directly to the server. (the client is not aware of the contents of that request, it just forwards them to the server). I'm not sure why in build 2108 it works. It may be an intermittent success due to timing/server issues. The supported way to do this is with the 1.8 APIs. – Outlook Add-ins Team - MSFT Oct 13 '21 at 19:31