compose: bcc field, inline pasted/dropped images, attach button stays regular
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -35,12 +35,23 @@ emailRouter.post('/send', async (ctx) => {
|
||||
const to = str(form.to).trim();
|
||||
if (!to) throw errors.BAD_REQUEST('At least one recipient is required');
|
||||
|
||||
const rawFiles = form.files;
|
||||
const files = (Array.isArray(rawFiles) ? rawFiles : rawFiles ? [rawFiles] : []).filter((f): f is File => f instanceof File);
|
||||
const toFiles = (raw: unknown) => (Array.isArray(raw) ? raw : raw ? [raw] : []).filter((f): f is File => f instanceof File);
|
||||
const attachments = await Promise.all(
|
||||
files.map(async (f) => ({ filename: f.name, content: Buffer.from(await f.arrayBuffer()), contentType: f.type || undefined })),
|
||||
toFiles(form.files).map(async (f) => ({ filename: f.name, content: Buffer.from(await f.arrayBuffer()), contentType: f.type || undefined })),
|
||||
);
|
||||
// Inline images: cid `inline-<i>` matches the `<img src="cid:inline-i">` the composer put in the html.
|
||||
const inline = await Promise.all(
|
||||
toFiles(form.inline).map(async (f, i) => ({
|
||||
filename: f.name,
|
||||
content: Buffer.from(await f.arrayBuffer()),
|
||||
contentType: f.type || undefined,
|
||||
cid: `inline-${i}`,
|
||||
contentDisposition: 'inline' as const,
|
||||
})),
|
||||
);
|
||||
const allAttachments = [...attachments, ...inline];
|
||||
|
||||
const html = str(form.html).trim();
|
||||
const inReplyTo = str(form.inReplyTo).trim();
|
||||
const { transport, from } = await getSmtpTransport(user.id);
|
||||
await transport.sendMail({
|
||||
@@ -50,7 +61,8 @@ emailRouter.post('/send', async (ctx) => {
|
||||
bcc: str(form.bcc).trim() || undefined,
|
||||
subject: str(form.subject).trim() || '(no subject)',
|
||||
text: str(form.body),
|
||||
...(attachments.length ? { attachments } : {}),
|
||||
...(html ? { html } : {}),
|
||||
...(allAttachments.length ? { attachments: allAttachments } : {}),
|
||||
...(inReplyTo ? { headers: { 'In-Reply-To': inReplyTo, References: inReplyTo } } : {}),
|
||||
});
|
||||
return ctx.json({ ok: true });
|
||||
|
||||
Reference in New Issue
Block a user