mirror of
https://github.com/bulwarkmail/native.git
synced 2026-10-31 08:06:36 +00:00
fix: send the quoted inline images along with replies and forwards
This commit is contained in:
@@ -27,3 +27,25 @@ describe('replyComposeParams', () => {
|
||||
expect(replyComposeParams('reply', source, undefined, ' ')?.prefillBody).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('replyComposeParams: quoted inline images', () => {
|
||||
const quotedImage = { blobId: 'b-img', type: 'image/png', name: 'logo.png', disposition: 'inline', cid: '<logo@x>' };
|
||||
const unusedInline = { blobId: 'b-sig', type: 'image/png', name: 'sig.png', disposition: 'inline', cid: 'sig@x' };
|
||||
const file = { blobId: 'b-pdf', type: 'application/pdf', name: 'report.pdf', disposition: 'attachment' };
|
||||
const withImage = {
|
||||
...source,
|
||||
htmlBody: [{ partId: '2', type: 'text/html' }],
|
||||
textBody: [{ partId: '1', type: 'text/plain' }],
|
||||
bodyValues: { 1: { value: 'Hi' }, 2: { value: '<p>Hi <img src="cid:logo@x"></p>' } },
|
||||
attachments: [quotedImage, unusedInline, file],
|
||||
} as unknown as Email;
|
||||
|
||||
it('hands a reply the image its quote embeds and nothing else', () => {
|
||||
expect(replyComposeParams('reply', withImage)?.replyTo?.attachments).toEqual([quotedImage]);
|
||||
expect(replyComposeParams('reply', source)?.replyTo?.attachments).toBeUndefined();
|
||||
});
|
||||
|
||||
it('hands a forward the quoted image and the files, not unused inline parts', () => {
|
||||
expect(replyComposeParams('forward', withImage)?.replyTo?.attachments).toEqual([quotedImage, file]);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,6 +1,23 @@
|
||||
import type { Email } from '../api/types';
|
||||
import type { Attachment, Email } from '../api/types';
|
||||
import type { RootStackParamList } from '../navigation/types';
|
||||
import { pickEmailBody, plainTextBody } from './email-body';
|
||||
import { extractCidRefs } from './email-html';
|
||||
import { stripMessageIdBrackets } from './email-threading';
|
||||
|
||||
/**
|
||||
* The parts a reply or forward hands the composer. The inline images the
|
||||
* quoted HTML embeds go along in both modes: the composer fetches them into
|
||||
* the quote and attaches them again on send (it never shows them as chips).
|
||||
* Without them a quoted `cid:` image went out pointing at a part the new
|
||||
* message did not have. A forward also carries the real attachments.
|
||||
*/
|
||||
function carriedParts(mode: 'reply' | 'replyAll' | 'forward', source: Email, quoteHtml?: string): Attachment[] | undefined {
|
||||
const quoted = new Set(quoteHtml ? extractCidRefs(quoteHtml) : []);
|
||||
const isQuoted = (a: Attachment) => !!a.cid && quoted.has(stripMessageIdBrackets(a.cid));
|
||||
const parts = (source.attachments ?? []).filter((a) =>
|
||||
isQuoted(a) || (mode === 'forward' && !(a.disposition === 'inline' && a.cid)));
|
||||
return parts.length > 0 || mode === 'forward' ? parts : undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Composer params for a reply / reply-all / forward of `source`. Shared by
|
||||
@@ -42,11 +59,7 @@ export function replyComposeParams(
|
||||
// Threading needs the RFC Message-ID, never the JMAP object id (#234).
|
||||
messageId: source.messageId ?? undefined,
|
||||
references: source.references ?? undefined,
|
||||
// Forward carries the original attachments as blob refs; cid-embedded
|
||||
// inline images are already part of the quoted HTML.
|
||||
attachments: mode === 'forward'
|
||||
? (source.attachments ?? []).filter((a) => !(a.disposition === 'inline' && a.cid))
|
||||
: undefined,
|
||||
attachments: carriedParts(mode, source, quoteHtml),
|
||||
originalEmailId: source.id,
|
||||
jmapAccountId: ownerAccountId,
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user