From 7cfc12c6ef817360bf36eb48a18adf8d947415e5 Mon Sep 17 00:00:00 2001 From: Flavio Fois Date: Thu, 5 Feb 2026 12:39:43 +0100 Subject: [PATCH] feat: add support for embedded files in email attachments and enhance logging in MailViewer --- backend/utils/mail/eml_reader.go | 61 ++++++++++++++++++- frontend/src/lib/components/MailViewer.svelte | 7 ++- 2 files changed, 65 insertions(+), 3 deletions(-) diff --git a/backend/utils/mail/eml_reader.go b/backend/utils/mail/eml_reader.go index f6b8167..8cf0ebe 100644 --- a/backend/utils/mail/eml_reader.go +++ b/backend/utils/mail/eml_reader.go @@ -2,6 +2,7 @@ package internal import ( "bytes" + "encoding/base64" "fmt" "io" "net/mail" @@ -58,10 +59,68 @@ func ReadEmlFile(filePath string) (*EmailData, error) { body = email.TextBody } - // Process attachments and detect PEC + // Process attachments list and PEC detection var attachments []EmailAttachment var hasDatiCert, hasSmime, hasInnerEmail bool + // Process embedded files (inline images) -> add to body AND add as attachments + for _, ef := range email.EmbeddedFiles { + data, err := io.ReadAll(ef.Data) + if err != nil { + continue + } + + // Convert to base64 + b64 := base64.StdEncoding.EncodeToString(data) + mimeType := ef.ContentType + if parts := strings.Split(mimeType, ";"); len(parts) > 0 { + mimeType = strings.TrimSpace(parts[0]) + } + if mimeType == "" { + mimeType = "application/octet-stream" + } + + // Create data URI + dataURI := fmt.Sprintf("data:%s;base64,%s", mimeType, b64) + + // Replace cid:reference with data URI in HTML body + // ef.CID is already trimmed of <> + target := "cid:" + ef.CID + body = strings.ReplaceAll(body, target, dataURI) + + // ALSO ADD AS ATTACHMENTS for the viewer + filename := ef.CID + if filename == "" { + filename = "embedded_image" + } + // If no extension, try to infer from mimetype + if !strings.Contains(filename, ".") { + ext := "dat" + switch mimeType { + case "image/jpeg": + ext = "jpg" + case "image/png": + ext = "png" + case "image/gif": + ext = "gif" + case "application/pdf": + ext = "pdf" + default: + if parts := strings.Split(mimeType, "/"); len(parts) > 1 { + ext = parts[1] + } + } + filename = fmt.Sprintf("%s.%s", filename, ext) + } + + attachments = append(attachments, EmailAttachment{ + Filename: filename, + ContentType: mimeType, + Data: data, + }) + } + + // Process standard attachments for _, att := range email.Attachments { data, err := io.ReadAll(att.Data) if err != nil { diff --git a/frontend/src/lib/components/MailViewer.svelte b/frontend/src/lib/components/MailViewer.svelte index e1f018d..6114349 100644 --- a/frontend/src/lib/components/MailViewer.svelte +++ b/frontend/src/lib/components/MailViewer.svelte @@ -9,6 +9,7 @@ import { mailState } from "$lib/stores/mail-state.svelte"; import { settingsStore } from "$lib/stores/settings.svelte"; import * as m from "$lib/paraglide/messages"; + import { dev } from "$app/environment"; let unregisterEvents = () => {}; let isLoading = $state(false); @@ -22,11 +23,13 @@ } $effect(() => { - console.log("Current email changed:", mailState.currentEmail); + if(dev) { + console.log(mailState.currentEmail) + } + console.info("Current email changed:", mailState.currentEmail?.subject); if(mailState.currentEmail !== null) { sidebarOpen.set(false); } - console.log(mailState.currentEmail?.attachments) }) onDestroy(() => {