From 4fd2eb9c405e095606747eb78630d48da394fb3a Mon Sep 17 00:00:00 2001 From: florianfederspiel Date: Sat, 23 May 2026 20:52:22 +0200 Subject: [PATCH] =?UTF-8?q?E-Mail=20PDF-Downloads=20als=20Bin=C3=A4rdaten?= =?UTF-8?q?=20stabilisieren?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit KI-AGENT: Attachment-Downloads werden im Backend explizit als Buffer mit Content-Length ausgeliefert und im Frontend aus einem ArrayBuffer als Blob erzeugt, damit PDF-Anhänge unverändert gespeichert werden. --- backend/src/modules/email/email.sync.service.ts | 4 +++- backend/src/routes/emailAsUser.ts | 13 ++++++++++--- frontend/pages/email/index.vue | 5 +++-- 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/backend/src/modules/email/email.sync.service.ts b/backend/src/modules/email/email.sync.service.ts index a8668b0..2172fb0 100644 --- a/backend/src/modules/email/email.sync.service.ts +++ b/backend/src/modules/email/email.sync.service.ts @@ -668,7 +668,9 @@ export function emailSyncService(server: FastifyInstance) { return { filename: attachment.filename || row.attachment.filename || "anhang", contentType: attachment.contentType || row.attachment.contentType || "application/octet-stream", - content: attachment.content, + content: Buffer.isBuffer(attachment.content) + ? attachment.content + : Buffer.from(attachment.content), } } } finally { diff --git a/backend/src/routes/emailAsUser.ts b/backend/src/routes/emailAsUser.ts index 7fd8d1e..6c9fdfd 100644 --- a/backend/src/routes/emailAsUser.ts +++ b/backend/src/routes/emailAsUser.ts @@ -466,9 +466,16 @@ export default async function emailAsUserRoutes(server: FastifyInstance) { if (!attachment) return reply.code(404).send({ error: "Anhang nicht gefunden" }) - reply.header("Content-Type", attachment.contentType) - reply.header("Content-Disposition", `attachment; filename="${attachment.filename.replace(/"/g, "")}"`) - return reply.send(attachment.content) + const buffer = Buffer.isBuffer(attachment.content) + ? attachment.content + : Buffer.from(attachment.content) + const filename = attachment.filename.replace(/["\r\n]/g, "") + + reply.header("Content-Type", attachment.contentType || "application/octet-stream") + reply.header("Content-Length", buffer.length) + reply.header("Cache-Control", "no-store") + reply.header("Content-Disposition", `attachment; filename="${filename}"`) + return reply.send(buffer) } catch (err: any) { req.log.error(err) return reply.code(500).send({ error: err.message || "Anhang konnte nicht geladen werden" }) diff --git a/frontend/pages/email/index.vue b/frontend/pages/email/index.vue index d943afb..d7930af 100644 --- a/frontend/pages/email/index.vue +++ b/frontend/pages/email/index.vue @@ -457,13 +457,14 @@ async function downloadAttachment(attachment: NonNullable