Open rbays opened 5 months ago
Thank you for sharing this issue @rbays! Connecting you @exextoc with who may be able to help.
@rbays We are unable to repro the issue locally. Can you please host your repro video and the har logs to a private repo, and grant permission to access it?
Hi @Swathy-Mothilal I have invited you as a collaborator to the private repo, is there anyone else I need to add too?
@rbays Thanks for sharing the repo. Could you please provide a video demonstrating the issue and logs? We need to understand the flow to be able to reproduce it.
@rbays Please provide a working manifest link also where you are able to repro the issue.
Hi, I don't have a manifest available to share, but I believe I have managed to isolate the issue. The below code will cause the issue on New Outlook for windows (there is no issue on old outlook or web)
the processMessageComposeEvent
event is in the manifest as a launch event as follows
<LaunchEvent FunctionName="processMessageComposeEvent" Type="OnNewMessageCompose"/>
Office.initialize = () => { };
type MailboxItem = Office.Item & Office.ItemCompose & Office.ItemRead &
Office.Message & Office.MessageCompose & Office.MessageRead &
Office.Appointment & Office.AppointmentCompose & Office.AppointmentRead;
function getContext() : Office.Context {
if (Office.context) {
return Office.context;
}
throw new Error();
}
function getMailbox() : Office.Mailbox {
const result = getContext().mailbox;
if (result) {
return Office.context.mailbox;
}
throw new Error();
}
function getMailboxItem() : MailboxItem {
const result = getMailbox().item;
if (result) {
return result;
}
throw new Error();
}
async function saveCustomProperties(customProps: Office.CustomProperties) : Promise<void> {
return new Promise((resolve, reject) => {
customProps.saveAsync((asyncResult) => {
if (asyncResult.status === Office.AsyncResultStatus.Failed) {
reject(asyncResult.error);
} else {
resolve();
}
});
});
}
function getItemCustomPropertiesAsync(): Promise<Office.CustomProperties> {
return new Promise((resolve, reject) => {
getMailboxItem().loadCustomPropertiesAsync((asyncResult) => {
if (asyncResult.status === Office.AsyncResultStatus.Failed) {
reject(asyncResult.error);
} else {
resolve(asyncResult.value);
}
});
});
}
async function setItemCustomPropertyAsync(key: string, value: string): Promise<void> {
const customProps = await getItemCustomPropertiesAsync();
customProps.set(key, value);
return saveCustomProperties(customProps);
}
async function processMessageComposeEvent(): Promise<void> {
let x = 0;
const intervalID = setInterval(() => {
x += 1;
if (x >= 40) {
window.clearInterval(intervalID);
} else {
setItemCustomPropertyAsync('test_key_iterator', x.toString());
}
}, 500);
}
export default processMessageComposeEvent;
The issue seems to be some kind of race condition between customProps.SaveAsync
and whatever is happening with the attachment being saved in office.
The code above just calls that method every half a second for the first 20 seconds when you start composing a new email.
By opening a new email, and then attaching some small attachments withing the first 5-10 seconds of having the message open I have been able to consistently reproduce the issue.
Please let me know if you need any more help to replicate the issue
@rbays , Thanks for sharing the code snippet. In your code, the processMessageComposeEvent function sets custom properties in a loop with a 500ms interval. If the attachments are being saved at the same time, there might be a conflict or timing issue that causes the attachments not to be removed properly. To avoid this race condition, could you please wait for Attachments to be Saved. Ensure that the attachments are fully saved before starting the custom property setting operations.
Here is a code snippet, that can help you.
async function waitForAttachmentsToBeSaved(): Promise
Please let me know if you have any queries.
Hi @Swathy-Mothilal ,
I don't have the isSaved
property available to me, I have upgraded the package https://www.npmjs.com/package/@types/office-js to 1.0.401 (which is currently the latest) and only have the following props available on the AttachmentDetails
interface that is returned.
Could you please advise if I should be using a different package to access this property?
Further, even if this does fix my issue, I believe that this will cause issues for others in the future, this is only an issue on New outlook (not OWA or old outlook) and means that every time someone saves a custom prop, they run the risk of breaking attachments. My example runs on a loop to ensure I can recreate the issue consistently, but when I initially encountered the issue, it was happening sporadically during the normal course of usage. As such I believe that this is a bug that should be fixed by the office-JS team
@rbays Few observations for your handler function in the code that you shared.
Can you create a repro script in script lab, to help repro this.
Hi @rkpathak ,
1) I have amended the process event to call the event.completed method below, though it doesn't make a difference and still has issues in the same way 2) I cannot see anything relevant in the section you linked, but do you mean that the function should not be asynchronous?
async function processMessageComposeEvent(event: any): Promise<void> {
let x = 0;
const intervalID = setInterval(() => {
x += 1;
if (x >= 40) {
window.clearInterval(intervalID);
} else {
setItemCustomPropertyAsync('test_key_iterator', x.toString());
if (x === 39) {
event.completed();
}
}
}, 500);
}
@rbays Can you create a repro script in script lab and share the link, to help repro this.
@rkpathak I have created a script in script lab, however I have not been able to repro the issue this way because as far as I can tell, script lab does not run on new outlook.
I took an existing template and replaced the main function with the exact code from the example that I provided earlier.
I hope this helps.
Here are the segments of the script:
$("#wreck-it").on("click", processMessageComposeEvent);
type MailboxItem = Office.Item &
Office.ItemCompose &
Office.ItemRead &
Office.Message &
Office.MessageCompose &
Office.MessageRead &
Office.Appointment &
Office.AppointmentCompose &
Office.AppointmentRead;
function getContext(): Office.Context {
if (Office.context) {
return Office.context;
}
throw new Error();
}
function getMailbox(): Office.Mailbox {
const result = getContext().mailbox;
if (result) {
return Office.context.mailbox;
}
throw new Error();
}
function getMailboxItem(): MailboxItem {
const result = getMailbox().item;
if (result) {
return result;
}
throw new Error();
}
async function saveCustomProperties(customProps: Office.CustomProperties): Promise<void> {
return new Promise((resolve, reject) => {
customProps.saveAsync((asyncResult) => {
if (asyncResult.status === Office.AsyncResultStatus.Failed) {
reject(asyncResult.error);
} else {
resolve();
}
});
});
}
function getItemCustomPropertiesAsync(): Promise<Office.CustomProperties> {
return new Promise((resolve, reject) => {
getMailboxItem().loadCustomPropertiesAsync((asyncResult) => {
if (asyncResult.status === Office.AsyncResultStatus.Failed) {
reject(asyncResult.error);
} else {
resolve(asyncResult.value);
}
});
});
}
async function setItemCustomPropertyAsync(key: string, value: string): Promise<void> {
const customProps = await getItemCustomPropertiesAsync();
customProps.set(key, value);
return saveCustomProperties(customProps);
}
async function processMessageComposeEvent(): Promise<void> {
let x = 0;
const intervalID = setInterval(() => {
x += 1;
if (x >= 40) {
window.clearInterval(intervalID);
} else {
setItemCustomPropertyAsync("test_key_iterator", x.toString());
console.log(x);
}
}, 500);
}
<section class="ms-font-m">
<p class="ms-font-m">This sample saves custom props a bunch to try to break attachments</p>
<p><b>Required mode</b>: Compose</p>
</section>
<section class="samples ms-font-m">
<h3>Try it out</h3>
<ol>
<li>click the button</li>
<br>
<li>add some attachments within 20 seconds</li>
<br>
<li>watch them break</li>
</ol>
<div class="ms-TextField">
<button id="wreck-it" class="ms-Button">
<span class="ms-Button-label">I'm gonna wreck it!</span>
</button>
</section>
section.samples {
margin-top: 20px;
}
section.samples .ms-Button, section.setup .ms-Button {
display: block;
margin-bottom: 5px;
margin-left: 20px;
min-width: 80px;
}
https://appsforoffice.microsoft.com/lib/1/hosted/office.js
@types/office-js
office-ui-fabric-js@1.4.0/dist/css/fabric.min.css
office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css
core-js@2.4.1/client/core.min.js
@types/core-js
jquery@3.1.1
@types/jquery@3.3.1
@rkpathak is there any update or timeline on this?
Hi @rbays, apologies for the delay. I was able to reproduce this issue on the New Outlook, however as you mentioned this is very intermittent. Can you briefly elaborate the use case you are trying to address? If your add-in depending on attachments being saved or removed so that you can subsequently save the custom properties, you can consider listening to the OnMessageAttachmentsChanged event instead of doing so after intervals of 500ms?
Hi @kumarshrey-msft, the example I gave here isn't my actual use case, it's an example I created to help to hit the problem with more consistency to help you debug the problem.
In our actual usage we are storing a custom property on the message customProps when the user clicks a button in our taskpane to signify how the message should be processed on send, and also we are saving another custom prop during the messagecompose event to keep reference to the message.
The problem we have is that if the user happens to add an attachment to the email close to either of these events happening, there is a chance of the attachments breaking, which our QA team found, and managed to replicate about 1/10 times when trying.
As far as I can tell at the moment in new outlook, if you ever want to save message customProps, and the user wants to add an attachment, there is a chance that these 2 actions will clash and break the attachments for the user.
@rbays Thanks for reporting this issue, we have been able to reproduce it and it has been put on our backlog. We unfortunately have no timelines to share at this point.
Internal tracking id: Office: [4694943]
Hi @rbays,
This issue is mostly happening because of the mail item is being saved by 2 entities (removeAttachments and setCustomProperties).S, sometimes there is a conflict at the server side. While we carry on the server side investigation, could you please implement the logic of retries while removing the attachments? Run a loop for 3 retries, if successful exit of the loop, else delay then next retry in 1 or 2 seconds. This should resolve the issue. Hope it helps. We will keep you updated with the server side investigation.
I checked with the server team as well. They suggested that the irresolvable conflicts need to be handled by add-ins only.
So, kindly implement the retry logic as I suggested and let me know if it solves/doesn't. Happy to assist further.
This should solve the issue. Thank you.
Hi @patilganesh-msft, I don't know what you want me to retry.
Could you please be more specific as to what I should retry where please?
@rbays Ok, understood your issue that the attachment is being removed from the UI and not via add-in code. So it looks similar to the issue of attachment id getting changed after save operation for which already a bug has been opened with the attachments team and currently, we do not have ETA for the resolution.
Provide required information needed to triage your issue
I believe that this issue may be to do with calling
customProps.saveAsync
inOffice.CustomProperties
, but have not been able to come to a concrete conclusionWe have experience an issue locally and in our dev environment where intermittently, after adding attachments to a new email, these attachments will become impossible to remove, only in new outlook.
Your Environment
Platform [PC desktop, Mac, iOS, Office on the web]: Pc
Host [Excel, Word, PowerPoint, etc.]:New outlook
Office version number:
Operating System: windows 11 (also happened on Windows 10 for another user)
Browser (if using Office on the web): __
Expected behavior
Attachments should be deleteable and previewable whenever added
Current behavior
We have experience an issue locally and in our dev environment where intermittently, after adding attachments to a new email, these attachments will become impossible to remove, only in new outlook.
Steps to reproduce
Link to live example(s)
Provide additional details
Context
our addin needs to delete existing attachments, but is unable to since outlook is convinced that they don't exist
Useful logs
I have a .har of the web request being made when I most recently replicated the issue, but cannot upload here I also have a video of the issue happening, but do not want to upload to a public repo as it contains sensitive data
Thank you for taking the time to report an issue. Our triage team will respond to you in less than 72 hours. Normally, response time is <10 hours Monday through Friday. We do not triage on weekends.