Expanding Personal Contact Lists in Outlook with OfficeJS

If you are developing an OfficeJS add-in for Outlook or Outlook Online (OWA) and your project requirements have a need to peek inside distribution lists, you might find that there are two kinds:

  • Distribution Lists – these are Exchange groups, or mail enabled Active Directory groups. These are managed by the enterprise IT and contain a list of email addresses and/or other distributions lists.
  • Contact Lists / Private Distribution Lists – these are personal lists created by the user that can contain similar objects.

For an Office Add-in, you must use the makeEwsRequestAsync() command to submit EWS to Exchange. And the specific command you will need to use is ExpandDL to get the members of a DL (or contact list). With regards to the first item in the list above, it is pretty straight forward. For the second item there is this blurb on the page:

Private distribution lists are located in the Contacts folder of a user’s mailbox. Private distribution lists do not have e-mail addresses so their store item identifiers are used in an ExpandDL request. Members of a private distribution list can be any mail-enabled user, contacts or distribution lists from Active Directory, or contacts or private distribution lists from a user’s Contacts folder.

The bold part is key. But where do you get this. When you request a to.getAsync() and receive “Bob’s Favorite People” as a recipient item what do you do with it?

The key is to call the EWS method ResolveNames. When you call this on “Bob’s Favorite People” you will get a return value with PrivateDL and an ItemID (the Exchange Store Item ID in the users Contact folder) that you will then send that ItemId to ExpandDL. Here is what the soap response would look like from ResolveNames:

You can then make your ExpandDL request like this:

The result will be a list of all the email addresses, like this:

NOTE: For now the ResolveNames operation is not supported in my library easyEws. I am working to add it in the coming weeks.

Please let me know if you have any suggestions or questions.

NOTE: I am not an Exchange Web Services (EWS) expert, but have some experience with it through the OfficeJS makeEwsRequestAsync() command. To get the answer for this blog entry, I had to go to a real EWS expert to figure this one out. Many thanks to Dan Bagley (EwsEditor) for his assistance.

Downloading the OfficeJS Preview API for Offline Testing

Recently, I had a need to download the preview of the OfficeJS API for testing in an offline environment. The primary (and preferred) way to access the preview beta library is to point to it on the CDN via your HTML, like this:

However, if you need to download this for use offline in testing, you can actually download it using Node Package Manager. All you need is this command:

npm install @microsoft/office-js@beta

I was able to do my testing as if I were online with the CDN, so all was good. Happy coding! wlEmoticon-hotsmile.png

EXCEL: Auto-Run Macros Disabled without Warning

This entry applies if your security settings in Excel are set to “Disable all macros except digitally signed macros” like this:

disabledmacros

In this scenario, when you open a workbook that is digitally signed, you will get a yellow bar across the top of the screen, that says: “SECURITY WARNING Macros have been disabled”, like this:

macrowarning

But if the workbook is NOT signed and you attempt to open the workbook with macros, you will not see anything, no warning at all. The workbook will appear to open, but all macros will be disabled. If you try to run a macro, you will get the following warning:

macrowarning2

However, the insidious thing is your AutoRun macros will also not execute and you will get no warning. If your code performs some type of data refresh of the spreadsheet, you might not realize this did not happen and what you will be left with is stale data. For many financial institutions this can be a scary prospect.

To workaround this problem, I have created an XLAM that can warn your users that they opened an untrusted workbook. You can access the source and the add-in both on GitHub: VBAProjectNotSignedWarning-Addin

What this add-in does is look for XLSM file to be opened, it then checks to see if the VBAProjectSigned property is false. If the workbook code is not signed, macros are assumed to be in the file, and the user will get the following warning:

certwarningaddin

The SOURCE is provided in the depot because for it to run properly in your environment, you might want to open the XLSM sign the VBA Project with your corporate code certificate, secure the project with a password, and then Save A Copy as an XLAM (Excel Add-in). Once created, you can then place the add-in in the XLSTART folder in Program Files for each user in your organization. Then when they try to open an unsigned macro workbook, they will get a handy warning message.

The code for this is fairly simple. I will not go into each module, just the main function that performs the check of each Workbook that is opened via the Application.Workbook_Open event:

Removing Web Add-in Ribbon Customization in Outlook for Windows

If you are following the latest updates the the OfficeJS API’s, you will see that PowerPoint, Excel and Word have this new feature that allows you to specify an equivalent COM add-in in place of the Web Add-in. Here is the link:  https://docs.microsoft.com/en-us/office/dev/add-ins/develop/make-office-add-in-compatible-with-existing-com-add-in

This is useful for when you have created a Web Add-in but it is not as feature rich as your COM add-in. So on the Windows clients, you still want your COM (or VSTO) solution to run there and not the web version of the add-in.

However, this feature has not yet arrived for Outlook. I am told that this is coming, but for now there really are only two workarounds.

If you are using Office 2016, you can set your manifest requirements to 1.5, like this:

    <Requirements>
      <bt:Sets DefaultMinVersion=”1.5″>
        <bt:Set Name=”Mailbox” />
      </bt:Sets>
    </Requirements>

If you are needing to support Outlook 2019 or Outlook for Office 365, then this easy trick will not work. So what you need to do is a bit more complicated. To start you need to collect some information first:

  1. Open Outlook, and verify that your web add-in customization has loaded.
  2. Go to File, Options, Customize Ribbon:options
  3. At the bottom, click Import/Export and select Export all customizations.
  4. Save the “customui” file to the desktop and then open it in Notepad.
  5. You will look for your customization and it will be in a group or a tab and contain an if like this: x1:Group_5febe0ec-e536-4275-bd02-66818bf9e191_msgEditGroup_TabNewMailMessage.
  6. Make note of this value, minus the namespace (x1:) and whether it is a customtab or a customgroup.

If this does not work for you a couple of other options are to add the Group to the Quick Access bar, by right-clicking on the group and selecting “Add to Quick Access.” This should help it appear in the customUI file. However, if this still does not work, you can make an “educated guess” at the name by using these steps:

  1. Open your manifest file in your Web Add-in and locate the ID:

    5febe0ec-e536-4275-bd02-66818bf9e191

  2.  Next, locate what you called the group in your manifest:

    < Group id=”msgEditGroup” >

  3. Finally, you need to determine which “Ribbon” it is on. This is a tad more complex, but since most following the “TabDefault” option, here are two defaults I know about, that could help you:
    • TabNewMailMessage
    • TabReadMailMessage
  4. From there you can build the Group identifier:

    Group_5febe0ec-e536-4275-bd02-66818bf9e191_msgEditGroup_TabNewMailMessage

  5. If you are working with a custom tab, you would look in your manifest and get the name of the custom tab:

    <CustomTab id=”myTab”>

  6. From there you can build your tab identifier:

    Tab_5febe0ec-e536-4275-bd02-66818bf9e191_myTab

The namespace is what makes this whole process a little harder than expected. This namespace is a UID for the Exchange Account to which the add-in was installed. And this ID is unique to every user and each email account in Outlook. What you will need to do is customize the Ribbon XML in your solution to then hide this group. I have created a solution here on github that shows how to do this end-to-end with a new add-in:

https://github.com/davecra/RemoveOfficeWebAddin

The primary functionality is found in the GetCustomUI function. Here is the function:

What this does is loads a file called RemovedCustomizations.txt from the install directory of the add-in. This file will contain entries like this:

5febe0ec-e536-4275-bd02-66818bf9e191
customgroup,TabNewMailMessage,Group_5febe0ec-e536-4275-bd02-66818bf9e191_msgEditGroup_TabNewMailMessage
customgroup,TabNewMailMessage,Group_5febe0ec-e536-4275-bd02-66818bf9e191_msgDesignGroup_TabNewMailMessage

Important to note, the first entry is the ID of your Web Add-in. This is used to create the namespace entry,

You will use the steps above, to build this list. This is a tad more complex than I had hoped it would be, so please let me know if you get stuck on any parts and/or if there are areas that you think I can elaborate more.

Simple Client-Side JavaScript MIME Parser

Today, I have been working on JavaScript for the first time in a while. I have spent a lot of time lately in VSTO and specifically targeting Outlook. It was good to get back to the OfficeJS side of the house.

A customer of mine requested if there was a way to easily parse the MIME content from the easyEws library call: getMailItemMimeContent

I found a number of server-side JavaScript libraries but nothing that would help me with parsing the data on the client-side. Here is the class I created and I am contemplating incorporating it into it’s own library at some point and expanding on it. But for now, here it is:

To use this, I am demonstrating from an On Send event in OfficeJS. I grab the mail item being composed, save it to make sure it is in the Drafts folder, grab the ID of the message, then use that to grab the MIME data. Here is the sample code:

Using Azure Functions in Excel

I have been delving more and more into Azure recently. In looking for a way to build an Excel User Defined Function (UDF) that did not require Visual Basic for Applications (VBA) or similar, I looked at what I could do with:

And to my surprise it was actually very easy to set this up. Here are the steps:

  1. Log into https://portal.azure.com
  2. Click “Create a Resource” in the upper left
  3. Type “Functions App” then “Create”
  4. Then follow the directions to create your own Functions App called “ExcelFunctions,” for example.
  5. You will want to create an HTTP Trigger function and I called mine “AddNumbers”
  6. You will be asked where you want to edit the function and I chose online in the browser, which is what makes this the coolest thing ever.
  7. Here is what my function looks like:

Once you have created your function, you can also test it right there in Azure. On the Right is a tab called “Test.” You can select it, and then add parameters like this:

azurefunctiontest

You can click “Save and Run” at the top of the page to run the function and verify the result: 42. Now, to get this to work in Excel, you need the URL. To do this click the “</> Get Function URL” button:

geturl

This will give you value like this:

https://xxx.azurewebsites.net/api/AddNumbers?code=123456…==

Now the fun part, getting this to work in Excel.

  1. Open Excel and create a new Workbook
  2. In  A1 type 100, in B1 type -58
  3. Select C1 and add the following function:

=WEBSERVICE("https://xxx.azurewebsites.net/api/AddNumbers?code=123456...==&value1=" & A1 & "&value2=" & B1)

Once you press enter and Excel updates you should see the value of 42 appear.

This is a very simple example of how you can implement an Azure Function in Excel as a User Defined Function. Imagine all the possibilities where you can collect data, analyze results, use Cognitive Services and vast stores of data from a Data Lake and much, much more. The possibilities are endless.

Visual Studio 2017: This is an invalid xsi:type… mailappversionoverrides/1.1:Event

If you have been using Visual Studio 2017 to create an Outlook Web Add-in and are trying to use the new ItemSend event, you will note per the documentation the you need to add the MailAppVersionOverrides 1.1 to your manifest:

<VersionOverrides xmlns="http://schemas.microsoft.com/office/mailappversionoverrides/1.1" xsi:type="VersionOverridesV1_1">

The problem is that when you try to build and run the project, you get this exception:

Severity Code Description
Warning This is an invalid xsi:type ‘http://schemas.microsoft.com/office/mailappversionoverrides/1.1:Events&#8217;.

a

Specifically, Visual Studio 2017 does not like this line:

<ExtensionPoint xsi:type="Events">

If you are like me you have been hoping for an update to Visual Studio 2017 to fix this, but I just got word today that it did not get into the last update to Visual Studio 2017, but will make it into Visual Studio 2019. However, you do not need to run off and install Visual Studio 2019 once it is available. There is a workaround, and here are the steps to follow:

  • If you have an updated Exchange 2016 Server CU9 or later, you can browse to this folder:
    C:\Program Files\Microsoft\Exchange Server\V15\Bin
  • Locate and copy the file MailAppVersionOverridesV1_1.xsd and copy it to a removable drive or a network share.
  • On your development machine, locate the existing MailAppVersionOverridesV1_1.xsd. It should be located here:
    C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\Xml\Schemas\1033
  • Rename the existing file to MailAppVersionOverridesV1_1.old.
  • Copy the version of the MailAppVersionOverridesV1_1.xsd you got from your Exchange Server here.

At this point you should be good to go.

But wait!?!?! You say you don’t have an Exchange Server? You use Office 365 and your instance of Exchange is up in the cloud? OK… Now this is not the “preferred” method, but it will get the job done. I created a GIST, and you can download it from here. wlEmoticon-hotsmile.png Simply view RAW, copy, open Notepad, paste, Save As: MailAppVersionOverridesV1_1.xsd, and then you have your file.