From 6e30432b62dfc2ba210a8022ad9c4ae56ec23581 Mon Sep 17 00:00:00 2001 From: Junqi Wu Date: Thu, 3 Jul 2025 16:50:30 -0400 Subject: [PATCH] [FIX] Outlook: fix crash when adding inline images Currently logging emails can crash if there are more inline image attachments than img tags. Steps to reproduce ----- 1. Reply to an email that has an inline image 2. From the reply, select "Log Email Into Contact" 3. No log is created and the button is stuck in the loading state Cause ----- Currently, we loop through `inlineAttachments` to match them one-to-one with the document's `img` tags. But the counter does not consider the case where there's a different number of `inlineAttachments` and `imageElements`. This usually happens when there's an img in the email history which is removed at the top of the function, but the attachment still exists. Some emails can also have embeded inline attachments that are unused. Fix ----- Use two counters so that we don't hit an index out of bounds error. Also filter by `img` elements using `cid:` in src, so we don't overwrite `img` elements using URL images. opw-4855422 --- .../src/taskpane/components/Log/Logger.tsx | 27 +++++++++++-------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/outlook/src/taskpane/components/Log/Logger.tsx b/outlook/src/taskpane/components/Log/Logger.tsx index c583dc06c..522d295cc 100644 --- a/outlook/src/taskpane/components/Log/Logger.tsx +++ b/outlook/src/taskpane/components/Log/Logger.tsx @@ -120,30 +120,35 @@ class Logger extends React.Component { } } }); - // a counter is needed to map img tags with attachments, as outlook does not provide + // attempt to map img tags with attachments by index, as outlook does not provide // an id that enables us to match an img with an attachment. - let j = 0; - const imageElements = doc.getElementsByTagName('img'); + // iterate in reverse order since some attachments may be from the deleted history + const imageElements = Array.from(doc.getElementsByTagName('img')).filter((img) => + img.getAttribute('src')?.startsWith('cid:'), + ); - inlineAttachments.forEach((inlineAttachment) => { - if (inlineAttachment != null && inlineAttachment.error == undefined) { - if (inlineAttachment.oversize) { + let j = imageElements.length - 1; + let k = inlineAttachments.length - 1; + while (j >= 0 && k >= 0) { + if (inlineAttachments[k] != null && inlineAttachments[k].error == undefined) { + if (inlineAttachments[k].oversize) { imageElements[j].setAttribute( 'alt', _t('Could not display image %(attachmentName)s, size is over limit', { - attachmentName: inlineAttachment.name, + attachmentName: inlineAttachments[k].name, }), ); } else { - const fileExtension = inlineAttachment.name.split('.')[1]; + const fileExtension = inlineAttachments[k].name.split('.')[1]; imageElements[j].setAttribute( 'src', - `data:image/${fileExtension};base64, ${inlineAttachment.content}`, + `data:image/${fileExtension};base64, ${inlineAttachments[k].content}`, ); } - j++; } - }); + j--; + k--; + } if (oversizeAttachments.length > 0) { const attachmentNames = oversizeAttachments.map((attachment) => `"${attachment.name}"`).join(', ');