From e205a0d3e0a41deb8f8e1c79581460146076c222 Mon Sep 17 00:00:00 2001 From: the-djmaze <> Date: Wed, 11 May 2022 23:13:24 +0200 Subject: [PATCH] Resolve #248 View eml attachments --- dev/Common/Html.js | 44 +++++++++++++++--------- dev/Mime/Utils.js | 12 +++++++ dev/Model/Message.js | 50 ++-------------------------- dev/View/User/MailBox/MessageView.js | 20 ++++++++++- 4 files changed, 62 insertions(+), 64 deletions(-) diff --git a/dev/Common/Html.js b/dev/Common/Html.js index 940731ec3..3fbbf4064 100644 --- a/dev/Common/Html.js +++ b/dev/Common/Html.js @@ -35,16 +35,20 @@ export const * @param {string} text * @returns {string} */ - cleanHtml = (html, contentLocationUrls, removeColors) => { + cleanHtml = (html, oAttachments, removeColors) => { const debug = false, // Config()->Get('debug', 'enable', false); useProxy = !!SettingsGet('UseLocalProxyForExternalImages'), detectHiddenImages = true, // !!SettingsGet('try_to_detect_hidden_images'), result = { - hasExternals: false, - foundCIDs: [], - foundContentLocationUrls: [] + hasExternals: false + }, + + findAttachmentByCid = cid => oAttachments.findByCid(cid), + findLocationByCid = cid => { + const attachment = findAttachmentByCid(cid); + return attachment && attachment.contentLocation ? attachment : 0; }, // convert body attributes to CSS @@ -223,6 +227,8 @@ export const value = getAttribute('src'); delAttribute('src'); + let attachment; + if (detectHiddenImages && 'IMG' === name && (('' != getAttribute('height') && 3 > pInt(getAttribute('height'))) @@ -238,15 +244,22 @@ export const setAttribute('style', 'display:none'); setAttribute('data-x-hidden-src', value); } - else if (contentLocationUrls[value]) + else if ((attachment = findLocationByCid(value))) { - setAttribute('data-x-src-location', value); - result.foundContentLocationUrls.push(value); + if (attachment.download) { + oElement.loading = 'lazy'; + oElement.src = attachment.linkPreview(); + attachment.isLinked(true); + } } else if ('cid:' === value.slice(0, 4)) { - setAttribute('data-x-src-cid', value.slice(4)); - result.foundCIDs.push(value.slice(4)); + attachment = findAttachmentByCid(value.slice(4)); + if (attachment && attachment.download) { + oElement.src = attachment.linkPreview(); + attachment.isInline(true); + attachment.isLinked(true); + } } else if (/^(https?:)?\/\//i.test(value)) { @@ -289,7 +302,6 @@ export const oStyle.removeProperty('min-width'); const urls = { - cid: [], // 'data-x-style-cid' remote: [], // 'data-x-style-url' broken: [] // 'data-x-broken-style-src' }; @@ -302,9 +314,12 @@ export const found = found[0].replace(/^["'\s]+|["'\s]+$/g, ''); let lowerUrl = found.toLowerCase(); if ('cid:' === lowerUrl.slice(0, 4)) { - found = found.slice(4); - urls.cid[property] = found - result.foundCIDs.push(found); + const attachment = findAttachmentByCid(found); + if (attachment && attachment.linkPreview && name) { + oStyle[property] = "url('" + attachment.linkPreview() + "')"; + attachment.isInline(true); + attachment.isLinked(true); + } } else if (/http[s]?:\/\//.test(lowerUrl) || '//' === found.slice(0, 2)) { result.hasExternals = true; urls.remote[property] = useProxy ? proxy(found) : found; @@ -319,9 +334,6 @@ export const // oStyle.removeProperty('background-image'); // oStyle.removeProperty('list-style-image'); - if (urls.cid.length) { - setAttribute('data-x-style-cid', JSON.stringify(urls.cid)); - } if (urls.remote.length) { setAttribute('data-x-style-url', JSON.stringify(urls.remote)); } diff --git a/dev/Mime/Utils.js b/dev/Mime/Utils.js index 07d836c63..e09ef5222 100644 --- a/dev/Mime/Utils.js +++ b/dev/Mime/Utils.js @@ -1,6 +1,7 @@ import { ParseMime } from 'Mime/Parser'; import { AttachmentModel } from 'Model/Attachment'; +import { EmailModel } from 'Model/Email'; import { FileInfo } from 'Common/File'; import { BEGIN_PGP_MESSAGE } from 'Stores/User/Pgp'; @@ -16,6 +17,17 @@ export function MimeToMessage(data, message) let html = struct.getByContentType('text/html'); html = html ? html.body : ''; + if (struct.headers.subject) { + message.subject(struct.headers.subject.value); + } + ['from','to'].forEach(name => { + if (struct.headers[name]) { + let mail = new EmailModel; + mail.parse(struct.headers[name].value); + message[name].push(mail); + } + }); + struct.forEach(part => { let cd = part.header('content-disposition'), cid = part.header('content-id'), diff --git a/dev/Model/Message.js b/dev/Model/Message.js index 094599373..276adf7a8 100644 --- a/dev/Model/Message.js +++ b/dev/Model/Message.js @@ -381,60 +381,15 @@ export class MessageModel extends AbstractModel { viewHtml() { const body = this.body; if (body && this.html()) { - const contentLocationUrls = {}, - oAttachments = this.attachments(); - - // Get contentLocationUrls - oAttachments.forEach(oAttachment => { - if (oAttachment.cid && oAttachment.contentLocation) { - contentLocationUrls[oAttachment.contentId()] = oAttachment.contentLocation; - } - }); - - let result = cleanHtml(this.html(), contentLocationUrls, SettingsUserStore.removeColors()); + let result = cleanHtml(this.html(), this.attachments(), SettingsUserStore.removeColors()); this.hasExternals(result.hasExternals); -// this.hasInternals = result.foundCIDs.length || result.foundContentLocationUrls.length; this.hasImages(body.rlHasImages = !!result.hasExternals); - // Hide valid inline attachments in message view 'attachments' section - oAttachments.forEach(oAttachment => { - let cid = oAttachment.contentId(), - found = result.foundCIDs.includes(cid); - oAttachment.isInline(found); - oAttachment.isLinked(found || result.foundContentLocationUrls.includes(oAttachment.contentLocation)); - }); - body.innerHTML = result.html; body.classList.toggle('html', 1); body.classList.toggle('plain', 0); - // showInternalImages - const findAttachmentByCid = cid => this.attachments().findByCid(cid); - body.querySelectorAll('[data-x-src-cid],[data-x-src-location],[data-x-style-cid]').forEach(el => { - const data = el.dataset; - if (data.xSrcCid) { - const attachment = findAttachmentByCid(data.xSrcCid); - if (attachment && attachment.download) { - el.src = attachment.linkPreview(); - } - } else if (data.xSrcLocation) { - const attachment = this.attachments.find(item => data.xSrcLocation === item.contentLocation) - || findAttachmentByCid(data.xSrcLocation); - if (attachment && attachment.download) { - el.loading = 'lazy'; - el.src = attachment.linkPreview(); - } - } else if (data.xStyleCid) { - forEachObjectEntry(JSON.parse(data.xStyleCid), (name, cid) => { - const attachment = findAttachmentByCid(cid); - if (attachment && attachment.linkPreview && name) { - el.style[name] = "url('" + attachment.linkPreview() + "')"; - } - }); - } - }); - if (SettingsUserStore.showImages()) { this.showExternalImages(); } @@ -608,7 +563,8 @@ export class MessageModel extends AbstractModel { ); return clone.innerHTML; } - return this.html() || plainToHtml(this.plain()); + let result = cleanHtml(this.html(), this.attachments(), SettingsUserStore.removeColors()) + return result.html || plainToHtml(this.plain()); } /** diff --git a/dev/View/User/MailBox/MessageView.js b/dev/View/User/MailBox/MessageView.js index 70755189f..d66b06254 100644 --- a/dev/View/User/MailBox/MessageView.js +++ b/dev/View/User/MailBox/MessageView.js @@ -56,6 +56,8 @@ import { PgpUserStore } from 'Stores/User/Pgp'; import { MimeToMessage } from 'Mime/Utils'; +import { MessageModel } from 'Model/Message'; + const oMessageScrollerDom = () => elementById('messageItem') || {}, @@ -296,7 +298,23 @@ export class MailMessageView extends AbstractViewRight { el = eqs(event, '.attachmentsPlace .attachmentItem .attachmentNameParent'); if (el) { const attachment = ko.dataFor(el); - attachment && attachment.linkDownload() && download(attachment.linkDownload(), attachment.fileName); + if (attachment && attachment.linkDownload()) { + if ('message/rfc822' == attachment.mimeType) { + // TODO + rl.fetch(attachment.linkDownload()).then(response => { + if (response.ok) { + response.text().then(text => { + const oMessage = new MessageModel(); + MimeToMessage(text, oMessage); + // cleanHTML + oMessage.viewPopupMessage(); + }); + } + }); + } else { + download(attachment.linkDownload(), attachment.fileName); + } + } } if (eqs(event, '.messageItemHeader .subjectParent .flagParent')) {