From f637a374779c1ac04b3c5d9685b62d0fca5a0182 Mon Sep 17 00:00:00 2001 From: Marvin Date: Tue, 18 Aug 2026 06:50:17 +0200 Subject: [PATCH 1/3] fix: clear attachments and headers in the email cleanup job The retention cleanup job only nulls text and html, but attachments (base64-encoded, typically the largest column) and headers survive it. Successful sends already clear both right after sending, so this mainly affects failed, cancelled and stuck emails, which keep their attachments forever even with EMAIL_CLEANUP_DAYS configured. Include both columns in the cleanup update and extend the filter so already-clean rows are still skipped. --- apps/web/src/server/jobs/cleanup-email-bodies.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/apps/web/src/server/jobs/cleanup-email-bodies.ts b/apps/web/src/server/jobs/cleanup-email-bodies.ts index a8020c96..cb000bc4 100644 --- a/apps/web/src/server/jobs/cleanup-email-bodies.ts +++ b/apps/web/src/server/jobs/cleanup-email-bodies.ts @@ -37,11 +37,15 @@ if (isSelfHosted() && isEmailCleanupEnabled()) { OR: [ {text: {not: null}}, {html: {not: null}}, + {attachments: {not: null}}, + {headers: {not: null}}, ], }, data: { text: null, html: null, + attachments: null, + headers: null, }, }); From d5346c1bbb7a4de7918357b27449819d4c756f49 Mon Sep 17 00:00:00 2001 From: Marvin Date: Tue, 18 Aug 2026 07:09:44 +0200 Subject: [PATCH 2/3] docs: document the EMAIL_CLEANUP_DAYS retention setting The setting existed in the env schema but was not mentioned in the self-hosting docs or the example env file. --- .env.selfhost.example | 5 +++++ apps/docs/self-hosting/overview.mdx | 10 ++++++++++ 2 files changed, 15 insertions(+) diff --git a/.env.selfhost.example b/.env.selfhost.example index 976d7782..dd6da812 100644 --- a/.env.selfhost.example +++ b/.env.selfhost.example @@ -41,5 +41,10 @@ AUTH_EMAIL_RATE_LIMIT=5 # Optional: prefix all Redis keys (useful for shared Redis with ACL isolation) # REDIS_KEY_PREFIX="" +# Optional: delete stored email content (text, html, attachments, headers) from +# the database after this many days. Runs daily at midnight UTC. Disabled if +# unset or not a positive number. +# EMAIL_CLEANUP_DAYS=30 + # used to send important error notification - optional DISCORD_WEBHOOK_URL="" diff --git a/apps/docs/self-hosting/overview.mdx b/apps/docs/self-hosting/overview.mdx index 0a44b56d..cbe5bb4f 100644 --- a/apps/docs/self-hosting/overview.mdx +++ b/apps/docs/self-hosting/overview.mdx @@ -80,6 +80,16 @@ Add the following environment variables. NEXTAUTH_SECRET="" ``` + + + By default, stored email content stays in the database forever. To bound database growth, set `EMAIL_CLEANUP_DAYS` to a positive number of days. A daily job (midnight UTC) then deletes the `text`, `html`, `attachments` and `headers` columns of emails older than the cutoff. Delivery status and event history are kept. + +```env +EMAIL_CLEANUP_DAYS=30 +``` + +Leave it unset to keep email content indefinitely. + From e18522b6e1a954caa423342aaaa6a29299bcd136 Mon Sep 17 00:00:00 2001 From: Marvin Date: Tue, 18 Aug 2026 09:21:39 +0200 Subject: [PATCH 3/3] docs: clarify cleanup wording Clears values, does not delete columns. Drop the claim about non-numeric values, since the setting is parsed leniently. --- .env.selfhost.example | 6 +++--- apps/docs/self-hosting/overview.mdx | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.env.selfhost.example b/.env.selfhost.example index dd6da812..2edfff36 100644 --- a/.env.selfhost.example +++ b/.env.selfhost.example @@ -41,9 +41,9 @@ AUTH_EMAIL_RATE_LIMIT=5 # Optional: prefix all Redis keys (useful for shared Redis with ACL isolation) # REDIS_KEY_PREFIX="" -# Optional: delete stored email content (text, html, attachments, headers) from -# the database after this many days. Runs daily at midnight UTC. Disabled if -# unset or not a positive number. +# Optional: clear stored email content (text, html, attachments, headers) from +# the database after this many days. Runs daily at midnight UTC. Leave unset to +# keep email content indefinitely. # EMAIL_CLEANUP_DAYS=30 # used to send important error notification - optional diff --git a/apps/docs/self-hosting/overview.mdx b/apps/docs/self-hosting/overview.mdx index cbe5bb4f..cadffa87 100644 --- a/apps/docs/self-hosting/overview.mdx +++ b/apps/docs/self-hosting/overview.mdx @@ -82,7 +82,7 @@ Add the following environment variables. - By default, stored email content stays in the database forever. To bound database growth, set `EMAIL_CLEANUP_DAYS` to a positive number of days. A daily job (midnight UTC) then deletes the `text`, `html`, `attachments` and `headers` columns of emails older than the cutoff. Delivery status and event history are kept. + By default, stored email content stays in the database forever. To bound database growth, set `EMAIL_CLEANUP_DAYS` to a positive number of days. A daily job (midnight UTC) then clears the `text`, `html`, `attachments` and `headers` values for emails older than the cutoff. Delivery status and event history are kept. ```env EMAIL_CLEANUP_DAYS=30