Skip to content

Option to clean up old attachments on a schedule#11061

Open
harshad1 wants to merge 6 commits into
thunderbird:mainfrom
harshad1:feat/old-attachment-cleanup
Open

Option to clean up old attachments on a schedule#11061
harshad1 wants to merge 6 commits into
thunderbird:mainfrom
harshad1:feat/old-attachment-cleanup

Conversation

@harshad1
Copy link
Copy Markdown
Contributor

@harshad1 harshad1 commented May 28, 2026

Summary

Adds an account-level setting to remove locally downloaded attachments from IMAP messages older than a selected age. Intention is to save local space.

Message and attachment metadata are preserved so attachments can still be fetched again from the server when requested.

I wired this into the existing legacy account settings/storage path because account settings are still mostly there.

Notes

  • Adds configurable attachment cleanup age with a default of disabled.
  • Schedules periodic WorkManager cleanup for eligible IMAP accounts.
  • Runs a one-time cleanup when the setting changes.
  • Removes only local attachment payloads for old messages; message records and attachment parts remain.
  • Does not automatically re-download attachments when the retention window is changed or disabled.
  • Keeps cleanup scoped to explicit attachments, with tests covering inline/folded disposition cases.
  • I used GPT codex to help me explore the codebase and draft things. Also had it add more tests.

@github-actions
Copy link
Copy Markdown
Contributor

Missing report label. Set exactly one of: report: include, report: exclude OR report: highlight.

@harshad1 harshad1 changed the title WIP: add old attachment cleanup setting Option to clean up old attachments on a schedule May 31, 2026
android:key="account_attachment_cleanup"
android:summary="@string/account_settings_attachment_cleanup_summary"
android:title="@string/account_settings_attachment_cleanup_label"
/>
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Intentionally wired into the existing legacy account settings screen because account settings still use this

import net.thunderbird.core.common.mail.Protocols
import net.thunderbird.core.logging.legacy.Log

class AttachmentCleanupWorkerManager(
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cleanup work is scheduled only for IMAP accounts with a non-zero retention value. Disabling the setting or switching to a non-IMAP account cancels both periodic and pending one-time cleanup work.

BackgroundOps.NEVER -> true
BackgroundOps.ALWAYS -> false
BackgroundOps.WHEN_CHECKED_AUTO_SYNC -> !ContentResolver.getMasterSyncAutomatically()
}
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Attachment cleanup follows the existing background-work policy, including WHEN_CHECKED_AUTO_SYNC via Android master sync, so it should not run when the user has disabled background account work.

import com.fsck.k9.mailstore.LockableDatabase
import net.thunderbird.core.common.mail.Flag

internal class AttachmentCleanupOperations(
Copy link
Copy Markdown
Contributor Author

@harshad1 harshad1 May 31, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The SQL query only pre-filters candidate parts; attachment detection is done by parsing disposition so inline parts with filenames like 'attachment.png' are not removed.

}
}

private fun SQLiteDatabase.markPartsAsMissing(messagePartIds: List<Long>) {
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cleanup removes only the local payload and marks the part as missing. It preserves message part metadata such as filename/server reference so the attachment can be fetched again on demand.

@harshad1
Copy link
Copy Markdown
Contributor Author

harshad1 commented Jun 1, 2026

IMO this is ready for review.

The jankiest part is the attachment detection - we finds candidates by doing a SQL LIKE over raw headers, then parse in code to decide whether the part is really an attachment. This is kinda fragile and expensive - lots of redundant work on every run.

The cleaner version would store attachment-ness as structured data when saving the message part, then the cleanup can query an indexed column instead of interpreting MIME headers.

But I did not want to introduce a schema change and a migration rn

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants