E-Mail Anhänge ohne Fetch herunterladen
KI-AGENT: Der E-Mail Anhang-Download nutzt jetzt einen nativen Browser-Link statt Cross-Origin-Fetch und erlaubt dafür den bestehenden JWT gezielt als Download-Token.
This commit is contained in:
@@ -68,6 +68,15 @@ export default fp(async (server: FastifyInstance) => {
|
||||
return
|
||||
}
|
||||
|
||||
const urlPath = req.url.split("?")[0]
|
||||
const queryToken = (req.query as any)?.downloadToken
|
||||
const downloadToken =
|
||||
typeof queryToken === "string"
|
||||
&& urlPath.startsWith("/api/email/attachments/")
|
||||
&& urlPath.endsWith("/download")
|
||||
? queryToken
|
||||
: null
|
||||
|
||||
// 1️⃣ Token aus Header oder Cookie lesen
|
||||
const cookieToken = req.cookies?.token
|
||||
const authHeader = req.headers.authorization
|
||||
@@ -78,7 +87,7 @@ export default fp(async (server: FastifyInstance) => {
|
||||
const token =
|
||||
headerToken && headerToken.length > 10
|
||||
? headerToken
|
||||
: cookieToken || null
|
||||
: cookieToken || downloadToken || null
|
||||
|
||||
if (!token) {
|
||||
return reply.code(401).send({ error: "Authentication required" })
|
||||
|
||||
@@ -55,6 +55,7 @@ type EmailMessage = {
|
||||
}
|
||||
|
||||
const { $api } = useNuxtApp()
|
||||
const runtimeConfig = useRuntimeConfig()
|
||||
const toast = useToast()
|
||||
|
||||
const accounts = ref<EmailAccount[]>([])
|
||||
@@ -456,24 +457,22 @@ async function moveSelectedMessage() {
|
||||
async function downloadAttachment(attachment: NonNullable<EmailMessage["attachments"]>[number]) {
|
||||
actionLoading.value = `attachment-${attachment.id}`
|
||||
try {
|
||||
const response = await $api.raw(`/api/email/attachments/${attachment.id}/download`, {
|
||||
responseType: "arrayBuffer",
|
||||
timeout: 60_000,
|
||||
})
|
||||
const contentType = response.headers.get("content-type") || attachment.contentType || "application/octet-stream"
|
||||
const blob = new Blob([response._data as ArrayBuffer], { type: contentType })
|
||||
const disposition = response.headers.get("content-disposition") || ""
|
||||
const dispositionFilename = disposition.match(/filename="([^"]+)"/)?.[1]
|
||||
const filename = dispositionFilename || attachment.filename || "anhang"
|
||||
const url = URL.createObjectURL(blob)
|
||||
const apiBase = String(runtimeConfig.public.apiBase || "").replace(/\/$/, "")
|
||||
const path = `/api/email/attachments/${attachment.id}/download`
|
||||
const downloadUrl = new URL(apiBase ? `${apiBase}${path}` : path, window.location.origin)
|
||||
const token = useCookie("token").value
|
||||
|
||||
if (token) {
|
||||
downloadUrl.searchParams.set("downloadToken", token)
|
||||
}
|
||||
|
||||
const link = document.createElement("a")
|
||||
|
||||
link.href = url
|
||||
link.download = filename
|
||||
link.href = downloadUrl.toString()
|
||||
link.download = attachment.filename || "anhang"
|
||||
document.body.appendChild(link)
|
||||
link.click()
|
||||
link.remove()
|
||||
URL.revokeObjectURL(url)
|
||||
} catch (err: any) {
|
||||
toast.add({
|
||||
title: "Download fehlgeschlagen",
|
||||
@@ -481,7 +480,9 @@ async function downloadAttachment(attachment: NonNullable<EmailMessage["attachme
|
||||
color: "error",
|
||||
})
|
||||
} finally {
|
||||
actionLoading.value = ""
|
||||
window.setTimeout(() => {
|
||||
actionLoading.value = ""
|
||||
}, 750)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user