Communication between OnMessageSend event and the add-in (Outlook) - outlook

The case concerns the Outlook add-in, namely the communication between the OnMessageSend event and the add-in.
Short description:
The user is authorized in an external service. After logging in, he receives a 'Token' that is used in communication between the add-in and the external service. The token is stored in the cookies.
Add-in is designed for Windows platform.
The use of the OnMessageSend event is described here
It looks like the OnMessageSend event handling is performed regardless of the environment in which the add-in is running. So I can't read the cookies that my add-on has saved (communication via localStorage also doesn't work). Unless I am wrong and it is otherwise.
Problem:
My problem is that in the handling of the OnMessageSend event I have to do a POST to an external service, to do this I need a 'Token' that has been saved in cookies by an add-in.
Is there a way to communicate between the add-in and the OnMessageSend event handler?
How can I pass a 'Token' from the add-in to the OnMessageSend event handler?
Thank you in advance for any hints

It is working for me. Use Office.context.mailbox.item.sessionData.setAsync in your Taskpane JS and then fetch using Office.context.mailbox.item.sessionData.getAsync in your launchevent.js
let oData = JSON.stringify(objData);
//console.log(oData);
Office.context.mailbox.item.sessionData.setAsync("bookingObject", oData, function (asyncResult) {
if (asyncResult.status === Office.AsyncResultStatus.Succeeded) {
//console.log("sessionData.setAsync succeeded");
}
else {
console.log("Failed to set sessionData. Error: " + JSON.stringify(asyncResult.error));
}
});
Office.context.mailbox.item.sessionData.getAsync("bookingObject", function (asyncResultBO) {
if (asyncResultBO.status !== Office.AsyncResultStatus.Succeeded) {
console.error(`BO Error:: ${asyncResultBO.error.message}`);
event.completed();
return;
}
const bookingObjectAllData = JSON.parse(asyncResultBO.value);
$.each(bookingObjectAllData["Office365AddInBookingItem"], function (index, item) { if (item.IsAddon == false) { ResourceIds = ResourceIds + item.ResourceId + ","; } });
originalAppointment.ResourceIds = ResourceIds;
result = checkRoomAvailabilityOutlook(originalAppointment.ResourceIds, originalAppointment.start, originalAppointment.end);

Related

Is there any way to get the files from some external source (API) and attach them in the new email through Outlook Add-in using OfficeJs

Is there any way to get the files from some external source (API) and attach them in the new email through Outlook Add-in using OfficeJs apart from Share point online (Office365) and OneDrive.
Solution approach for implementing attachments functionality from the add-in for external source files and emails
Yes, there is. You may be interested in the addFileAttachmentAsync method which adds a file to a message or appointment as an attachment. The addFileAttachmentAsync method downloads the file at the specified URI and attaches it to the item in the compose form.
Office.context.mailbox.item.addFileAttachmentAsync(
`https://webserver/picture.png`,
'picture.png',
{ asyncContext: null },
function (asyncResult) {
if (asyncResult.status === Office.AsyncResultStatus.Failed){
write(asyncResult.error.message);
} else {
// Get the ID of the attached file.
const attachmentID = asyncResult.value;
write('ID of added attachment: ' + attachmentID);
}
});
See Manage an item's attachments in a compose form in Outlook for more information.

How to create Action and Call action in MS Dynamics CRM?

How to create Action step by step and Call action in MS Dynamics CRM?
How many ways to call action in MS Dynamics CRM?
What the benefits of action instead of Workflow/plugin?
Actions
Actions are a type of process in Microsoft Dynamics 365. You can invoke actions, including custom actions, directly from a workflow or dialog, without writing code! More information: Invoke custom actions from a workflow or dialog
Actions can also be invoked by running custom code that uses the Microsoft Dynamics 365 Web services.
You can call actions:
It can be called from both client & server side, enabling the Single Point of Approach (Implement once, consume anywhere), for ex:- From code that executes within a plug-in, custom workflow and any C# code.
From a command that is placed in the application and executes the operation using JavaScript code.
Can receive input parameters and return output parameters in a straight forward manner, similar to an Organization level Web Service
From an integration with another system that uses the Microsoft Dynamics 365 web services.
From a custom client application that uses the Microsoft Dynamics 365 web services.
Why use actions?
Actions open a range of possibilities for composing business logic. Before Actions, the primary way to implement business processes was limited to plug-ins or custom workflow activities. With Actions, you can perform operations, such as Create, Update, Delete, Assign, or Perform Action. Internally, an action creates a custom Dynamics 365 message. With Actions you can create a custom message (for example: submitquote , leadtoax etc. Once an action is defined and activated, a developer can use that message like any of the other messages provided by the Microsoft Dynamics 365 platform.
Suppose you have button on Quote form which sends information from CRM to another platform (for ex another platform is AX).
Create and activate a Custom Action (Settings > Process)
Now you can call this Action(ofs_submitquotetoax) from JavaScript on some event (OnLoad, OnSave,etc). In this example I am calling the action from SUBMIT QUOTE button on Quote form which sending quote information to other system (AX).
// Call this below method from Button click event or from any event on the form
// For Alert.showLoding method you can see another Alert.js library
// For Process.callAction method you can see another Process.js library
// You can download Alert.js & Process.js from this Path: https://drive.google.com/drive/folders/0B2CUbevE8v9YMkZlMEhUZ3NJc1U
function submitquote() {
var actionName = "ofs_submitquoteax";
var entityName = Xrm.Page.data.entity.getEntityName();
var entityId = Xrm.Page.data.entity.getId();
Alert.showLoading("Submitting...", 400, 150);
var inputParams = [
{
key: "EntityRef", type: Process.Type.EntityReference,
value: new Process.EntityReference(entityName, entityId)
}
];
// call process callection method
Process.callAction(actionName, inputParams, cloneSuccessCallback, errorCallback);
}
function cloneSuccessCallback() {
Alert.hide();
Alert.show("Action Success", "", null, "SUCCESS");
Alert.hide();
var entityName = Xrm.Page.data.entity.getEntityName();
var entityId = Xrm.Page.data.entity.getId();
Xrm.Utility.openEntityForm(entityName, entityId);
//Xrm.Page.data.refresh();
}
function errorCallback(error, trace) {
alert(error);
alert(alert(error));
}
e, for this event you can register & trigger a Plugin and receive the input-parameter (in our case we sending input-parameter key as EntityRef in which we are sending entityName and entityId.
Parameters: Action Unique Name, Input Parameters (array), Success Callback (function), Error Callback (function), CRM Base URL (not required on forms/views)
Each Input Parameter object should contain key, value, and type. Types are defined by the Process.Type enum. EntityReference values should be an object containing id and entityType.
The Success Callback function should accept one argument which is an array of output parameters, each containing key, and value.
You can write plugin in below way and access input parameter
protected override void ExecuteCrmPlugin(LocalPluginContext localContext)
{ // Register the plugin in PreValidation stage as this plugin will trigger from Javascript (Action)
if (localContext == null)
{
throw new InvalidPluginExecutionException("localContext");
}
IPluginExecutionContext context = localContext.PluginExecutionContext;
if (context.Depth > 1) { return; }
IOrganizationService service = localContext.OrganizationService;
ITracingService trace = localContext.TracingService;
Entity quoteEntity = null;
EntityReference qEntity = null;
if (context.InputParameters.Contains("EntityRef") && context.InputParameters["EntityRef"] is EntityReference)
{
//if (context.PrimaryEntityName.ToLower() != "quote") { return; }
qEntity = context.InputParameters["EntityRef"] as EntityReference;
if (qEntity.LogicalName.ToLower().Equals("quote"))
{
try
{
quoteEntity = service.Retrieve("quote", qEntity.Id, new ColumnSet("ofs_parentaccountid", "quotenumber", "revisionnumber", "ofs_well"));
// Execute Your logic
}
catch (Exception ex)
{
trace.Trace(string.Format("Exception Quote_Create_AXIntegration Plugin: {0}", new[] { ex.ToString() }));
}
}
}
else { return; }
}
Register your plugin and then register the step in below way, you can notice your custom message name in below screen-shot "ofs_submitquoteax";
Ref:https://community.dynamics.com/crm/b/mylifemicrosoftdynamiccrm/archive/2017/04/17/microsoft-dynamics-crm-actions

addFileAttachmentAsync() is not functioning as expected on Outlook Desktop on Windows 10 machine

I am trying to add inline image to mail body through Outlook Add-in. It works fine in OWA but Desktop app fails to attach it inline, instead I get the image as a regular attachment, and broken image icon on email body.
I contacted Microsoft Devchat, they don't seem to able to repro it, I tried the code they sent me , and it behaves the same.
Here is the code:
function AttCallback(asyncResult) {
if (asyncResult.status == Office.AsyncResultStatus.Failed) {
console.log(asyncResult.error);
} else {
var szCID = asyncResult.asyncContext.UniqueName;
var szAddBodyData = "<p>Here's a cute bird!</p><br><div><img src='cid:" + szCID + "'></div><br>";
Office.context.mailbox.item.body.setSelectedDataAsync(
szAddBodyData,
{ coercionType: Office.CoercionType.Html });
console.log("Attachment added");
}
}
function insertAttachment() {
var szName = "cute_bird.png";
var options = { isInline: true, ContentId: szName, 'asyncContext': { UniqueName: szName } };
//var options = { asyncContext: null };
Office.context.mailbox.item.addFileAttachmentAsync(
"http://i.imgur.com/WJXklif.png",
szName,
options,
AttCallback);
}
Here is what is happening on my machine.
Note: As you can see from the code, by the time callback function gets hit, attachment was already added. However I do have inline property set to true.
Has anyone experienced it before? Any suggestions would be appreciated.
See from the documentation:
https://learn.microsoft.com/en-us/office/dev/add-ins/reference/objectmodel/requirement-set-1.5/outlook-requirement-set-1.5
that inline image addition support shipped with Outlook requirement set 1.5. You should specify this capability in your manifest.xml to ensure your add-in is only appearing in clients where it can work and not show up if it can't.

Microsoft BotFramework-WebChat is getting two welcome messages

I am using code based on https://github.com/Microsoft/BotFramework-WebChat/blob/master/samples/15.d.backchannel-send-welcome-event/index.html
When I load the web page I get two of the welcome messages. Looking at the console output of my bot I can see two conversation updates happening.
This doesn't happen with the Bot framework emulator, which only shows one welcome message.
The only place where my code differs from the sample is in rendering:
window.WebChat.renderWebChat({
directLine: window.WebChat.createDirectLine({ token }),
store,
styleOptions,
userID: guid(),
}, document.getElementById('webchat'));
Why is this hapening? Why is the web channel sending two "join" events for the user?
My code handling conversation updates looks like this:
} else if (turnContext.activity.type === ActivityTypes.ConversationUpdate) {
if (DEBUG) { console.log("ConversationUpdate"); }
// Do we have any new members added to the conversation?
if (turnContext.activity.membersAdded.length !== 0) {
// Iterate over all new members added to the conversation
for (var idx in turnContext.activity.membersAdded) {
console.log(turnContext.activity.membersAdded);
// Greet anyone that was not the target (recipient) of this message
// the 'bot' is the recipient for events from the channel,
// turnContext.activity.membersAdded == turnContext.activity.recipient.Id indicates the
// bot was added to the conversation.
if (turnContext.activity.membersAdded[idx].id != turnContext.activity.recipient.id) {
if (DEBUG) {console.log("Starting MASTER_DIALOG");}
const user = await this.userProfile.get(turnContext, {});
user.id = this.guid();
await this.userProfile.set(turnContext, user);
await this.userState.saveChanges(turnContext);
return await dialogContext.beginDialog(MASTER_DIALOG)
}
}
}
}
Using the ConversationUpdate event for sending a welcome message is not recommended. Read more about how to properly send a greeting message.
There will be two ConversationUpdate events per connection. One for when bot joins the conversation and one for when a (human) user joins the conversation. In your current code you are iterating over all new members, where you have to filter out the bot itself.
A better option would be to make use of a custom event sent using the backchannel. In the example you mention, you already have this functionality. It will sent a new event webchat/join to your bot, which even includes the browser language by default.

Office Outlook Add-in- Adding an attachment from a secure location

I'm adding an "Add attachment" command as part of an Office Outlook add-in.
I want to find a way to add file from a URL with authorization.
I thought downloading it with ajax and then saving it from a blob but looks like the command won't support it.
My code testing it that fails:
const text = 'attachment content';
const blob = new Blob([text], {type: 'text/plain'});
const attachmentURI = window.URL.createObjectURL(blob);
Office.context.mailbox.item.addFileAttachmentAsync(
attachmentURI,
'file.txt',
{ asyncContext: null },
function (asyncResult) {
if(asyncResult.status == Office.AsyncResultStatus.Failed){
console.log('error adding attachment: ' + asyncResult.error.message);
}
else {
const attachmentID = asyncResult.value;
console.log('added attachment: ' + attachmentID);
}
}
);
Any suggestions on saving an attachment from a URL with permissions?
Function documentation:
https://dev.office.com/docs/add-ins/outlook/add-and-remove-attachments-to-an-item-in-a-compose-form
If you are trying to attach a local file from the user's PC to the email then unfortunately you cannot do so since of course this is JavaScript. The attachment methods in the Outlook Add-in API can only deal with web-based files. You would need a web form or other mechanism to upload the file to your web service to an accessible URI location which you can then point to with the addFileAttachmentAsync method. The ASP.NET Web API would be one alternative to implement your web service in.
In addFileAttachmentAsync the attachmentURI parameter is sent to the Server (in OWA's case), or to the Outlook App (desktop Outlook). Then, either the Server or Outlook goes and downloads the file, and attaches it to the e-mail. If OWA/Outlook can't reach the URI that you provide, then it won't work.

Resources