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:
Open Outlook, and verify that your web add-in customization has loaded.
Go to File, Options, Customize Ribbon:
At the bottom, click Import/Export and select Export all customizations.
Save the “customui” file to the desktop and then open it in Notepad.
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.
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:
Open your manifest file in your Web Add-in and locate the ID:
5febe0ec-e536-4275-bd02-66818bf9e191
Next, locate what you called the group in your manifest:
< Group id=”msgEditGroup” >
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:
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”>
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:
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 to remove a tab:
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 item by item. And it is important to note that your item may appear on multiple tabs. For example, if your manifest is putting your custom group on TabDefault, that could end up in two places for a Compose message:
TabMail
TabComposeTools\TabMessage
The latter is a context tab and you have to specify the context tab name first, then the tab name. The tab name alone will not help. Finding the context tab is a bit more complex, but you can get those identifiers from here.
So in the end you might end up with a RemoveCustomizations.txt file that looks like this:
Overall, 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.
I am not certain how prevalent this issue is in the wild and/or if anyone else has encountered it or had to workaround it, but there is a documentation bug that had me pulling my hair our for nearly a week.
If you have a need to get the members of an Exchange public distribution group using Exchange Web Services (EWS) ExpandDL operation via SOAP, and you followed this documentation, you will have encountered this super unhelpful error:
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
The problem is that the documentation is wrong. The namespaces used and the namespace prefixes are wrong. Here is what is on the documentation site:
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
What I ended up doing was to use the EwsEditor tool and Fiddler (per the guidance of an awesome Exchange guru I work with – thanks Dan!), and I captured the proper soap coming from the Managed API. To get ExpandDL to work properly, you need this SOAP:
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
The EWSEditor tool has been around a while and is managed/developed by some of my co-workers that sit on the Outlook Developer Support Team. As I have been developing more and more Office Web Add-ins for Outlook, I have found knowing and using EWS to be a very important skill.
EWSEditor helps in this regard. It is a very powerful, full featured EWS test bed. To get started you download this and extract the contents of the ZIP to a folder. From there you launch it and from the File menu, click Next Exchange Service enter in your email address and then select password and click Ok. Then viola, you are connected:
Once connected, you can start browsing your mailbox using EWS. To get to your Inbox, for example, you select TopOfInformationStore and then select Inbox:
From there you can go to different folders and look at the items, properties, and values stored in your mailbox. It is quite handy to understand how these things are structured and stored.
Next, you can click Tools, EWS Post and test your EWS skills. What I did was entered in my information to connect to my server and filled it in as such:
And when I hit run, I got a response you see above. It is that simple. And there are also lots of examples as well. If you click Load Example you will see a lot of XML SOAP requests you can test with:
A requirement in an Outlook Web Add-in I am working on required the ability to send an email to an alias with another email as an attachment. I found this a bit challenging as the makeEwsRequestAsync() function limits us to only a handful of EWS functions (EWS operations that add-ins support). This means I was unable to use a lot of the samples I found on the web. However, with the UpdateItem method, I found a way.
First, let me say, I have been asked – why is easyEWS.js not on GitHub. Well, now it is:
Next, so I updated the functionality in easeEws via two function:
easyEws.getMailItemMimeContent – we use this function to get the MIME content of a specified mail item by the ID.
easyEws.sendPlainTextEmailWithAttachment – this function, although a tad more complicated, will create a very simple plain text email and add an attachment send it and save it to the drafts folder.
Here are the two new updates:
[code lang=”javascript” collapse=”true” title=”click to expand if the docs.com embedding below is not visible.”]
// PUBLIC: creates a new emails message with a single attachment and sends it
// RETURNS: ‘success’ is compelted successfully
easyEws.sendPlainTextEmailWithAttachment = function (subject, body, to, attachmentName, attachmentMime, successCallback, errorCallback) {
var soap = ‘<m:CreateItem MessageDisposition="SendAndSaveCopy">’ +
‘ <m:Items>’ +
‘ <t:Message>’ +
‘ <t:Subject>’ + subject + ‘</t:Subject>’ +
‘ <t:Body BodyType="Text">’ + body + ‘</t:Body>’ +
‘ <t:Attachments>’ +
‘ <t:ItemAttachment>’ +
‘ <t:Name>’ + attachmentName + ‘</t:Name>’ +
‘ <t:IsInline>false</t:IsInline>’ +
‘ <t:Message>’ +
‘ <t:MimeContent CharacterSet="UTF-8">’ + attachmentMime + ‘</t:MimeContent>’ +
‘ </t:Message>’ +
‘ </t:ItemAttachment>’ +
‘ </t:Attachments>’ +
‘ <t:ToRecipients><t:Mailbox><t:EmailAddress>’ + to + ‘</t:EmailAddress></t:Mailbox></t:ToRecipients>’ +
‘ </t:Message>’ +
‘ </m:Items>’ +
‘</m:CreateItem>’;
soap = getSoapHeader(soap);
// make the EWS call
asyncEws(soap, function (xmlDoc) {
// Get the required response, and if it’s NoError then all has succeeded, so tell the user.
// Otherwise, tell them what the problem was. (E.G. Recipient email addresses might have been
// entered incorrectly — try it and see for yourself what happens!!)
var result = xmlDoc.getElementsByTagName("ResponseCode")[0].textContent;
if (result == "NoError") {
successCallback(result);
}
else {
successCallback("The following error code was recieved: " + result);
}
}, function (errorDetails) {
if (errorCallback != null)
errorCallback(errorDetails);
});
};
// PUBLIC: gets the mail item as raw MIME data
// RETURNS: the entire email message as a MIME Base64 string
easyEws.getMailItemMimeContent = function (mailItemId, successCallback, errorCallback) {
var soap =
‘<m:GetItem>’ +
‘ <m:ItemShape>’ +
‘ <t:BaseShape>IdOnly</t:BaseShape>’ +
‘ <t:IncludeMimeContent>true</t:IncludeMimeContent>’ +
‘ </m:ItemShape>’ +
‘ <m:ItemIds>’ +
‘ <t:ItemId Id="’ + mailItemId + ‘"/>’ +
‘ </m:ItemIds>’ +
‘</m:GetItem>’;
soap = getSoapHeader(soap);
// make the EWS call
asyncEws(soap, function (xmlDoc) {
//var content = xmlDoc.getElementsByTagName("MimeContent")[0].textContent;
successCallback(xmlDoc);
}, function (errorDetails) {
if (errorCallback != null)
errorCallback(errorDetails);
});
};
[/code]
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Once added, you can use EasyEWS.js on your projects. In my particular project, I used the following code, which does the following:
Gets the current mail item (entirely) as a base64 encoded string. This is the full MIME representation of the message.
It then creates a new mail item and sends it with a comment from the user to the email address specified with an attachment (which is the base64 string we got in the first step).
This is all done with EWS and because of easyEWS.js, it is done in very few lines of code:
[code lang=”javascript” collapse=”true” title=”click to expand if the docs.com embedding below is not visible.”]
// Loads the form items to attach to events
function loadForm() {
$("#forward-button").click(function () {
getCurrentMessage();
});
}
// This function handles the click event of the sendNow button.
// It retrieves the current mail item, so that we can get its itemId property
// ans also get the MIME content
// It also retrieves the mailbox, so that we can make an EWS request
// to get more properties of the item.
function getCurrentMessage() {
var item = Office.context.mailbox.item;
itemId = item.itemId;
mailbox = Office.context.mailbox;
try{
easyEws.getMailItemMimeContent(itemId, sendMessageCallback, showErrorCallback);
} catch (error) {
showNotification("Unspecified error.", err.Message);
}
}
// This function is the callback for the getMailItemMimeContent method
// in the getCurrentMessage function.
// In brief, it first checks for an error repsonse, but if all is OK
// t:ItemId element.
// Recieves: mail message content as a Base64 MIME string
function sendMessageCallback(content) {
var toAddress = "bob@contoso.com";
var comment = $("#forward-comment").val();
if (comment == null || comment == ”) {
comment = "[user provided no comment]";
}
try{
easyEws.sendPlainTextEmailWithAttachment("Message with Item Attachment",
comment,
toAddress,
"Email Attachment",
content,
successCallback,
showErrorCallback);
}
catch (error) {
showNotification("Unspecified error.", err.Message);
}
}
// This function is the callback for the easyEws sendPlainTextEmailWithAttachment
// Recieves: a message that the result was successful.
function successCallback(result) {
showNotification("Success", result);
}
// This function will display errors that occur
// we use this as a callback for errors in easyEws
function showErrorCallback(error) {
showNotification("Error", error);// .error.message);
}
[/code]
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
If you have done any work with Outlook Add-ins using the Office JavaScript API’s, you might have found a nifty function that allows you to poll the Exchange Server using EWS calls. The function: makeEwsRequestAsync(). However, this function is not the easiest thing to use. You have to formulate an EWS SOAP message that you send to the service. Getting those correct, writing the code for them, and processing the results are a real beast. But, even worse is finding exactly how to formulate the SOAP message from the existing documentation. It is something I personally did NOT look forward to as I was working on my customers solutions.
My frustration is your benefit (I hope). I created a JavaScript class called easyEws, that makes certain calls very easy. I posted the project on GitHub (previously, I had posted this on CodePlex):