-
$40{t("perYear")}
+
$40{t("perYear")}
{t("saveAnnual", { percent: 17 })}
From 7f34251fb96824b22ed783cb0f00f093bc51375a Mon Sep 17 00:00:00 2001
From: mqmalagris <63169613+mqmalagris@users.noreply.github.com>
Date: Sun, 26 Apr 2026 20:52:58 -0300
Subject: [PATCH 3/7] feat: email attachments with on-demand extraction
Processor now walks the MIME tree and stores attachment metadata (filename,
content type, size, sha256, index) alongside the message. The bytes stay in
the raw .eml that SES already drops in S3 with a 1-day lifecycle, so no
duplicate storage.
Adds GET /inbox/{addr}/messages/{id}/attachments/{idx} (and the admin twin)
which re-parses the .eml on demand, returns the indexed attachment with
Content-Disposition: attachment + Content-Type: application/octet-stream +
X-Content-Type-Options: nosniff so browsers always download (never render
inline).
Hard limits applied at parse time: 10MB per attachment, 25MB total per
message, plus an extension blocklist (exe/bat/scr/msi/dll/js/vbs/...).
API Lambda now base64-encodes binary responses for API Gateway v2; Terraform
gains the new routes.
Frontend lists attachments under the message body with per-file size and a
download button that calls the new endpoint.
---
apps/web/src/components/InboxView.svelte | 6 +-
apps/web/src/components/MessageDetail.svelte | 76 ++++++++-
packages/shared/src/api-client.ts | 28 ++++
packages/shared/src/i18n/locales/en.ts | 6 +
packages/shared/src/i18n/locales/es.ts | 6 +
packages/shared/src/i18n/locales/fr.ts | 6 +
packages/shared/src/i18n/locales/pt-BR.ts | 6 +
packages/shared/src/types.ts | 10 ++
services/cmd/api-local/main.go | 2 +-
services/cmd/api/main.go | 36 +++-
services/cmd/processor/main.go | 13 +-
services/internal/email/parser.go | 167 +++++++++++++++++--
services/internal/handler/api.go | 115 ++++++++++++-
services/internal/handler/api_test.go | 2 +-
services/internal/inbox/model.go | 31 +++-
services/internal/inbox/service.go | 3 +-
terraform/api_gateway.tf | 12 ++
17 files changed, 482 insertions(+), 43 deletions(-)
diff --git a/apps/web/src/components/InboxView.svelte b/apps/web/src/components/InboxView.svelte
index 9008d43..3bf37f9 100644
--- a/apps/web/src/components/InboxView.svelte
+++ b/apps/web/src/components/InboxView.svelte
@@ -403,7 +403,11 @@
{#if selectedMessage}
-
+
{:else}
diff --git a/apps/web/src/components/MessageDetail.svelte b/apps/web/src/components/MessageDetail.svelte
index 42d9403..ad6e06b 100644
--- a/apps/web/src/components/MessageDetail.svelte
+++ b/apps/web/src/components/MessageDetail.svelte
@@ -1,14 +1,23 @@