feat(imap): add attachment type filter for IMAP ingestion

Add a configurable switch to control which attachment types are ingested
via IMAP. Images are excluded by default; office files and PDFs are ingested.

- Add global `IMAP_ATTACHMENT_FILTER` config setting (default: `documents_only`)
- Add `attachment_filter` column to `UserImapAccount` model for per-user override
- Migration 032 adds the column to `user_imap_accounts` table
- Update `fetch_attachments_and_enqueue()` to respect filter (documents_only/all)
- Update `pull_inbox()`, `_pull_user_imap_accounts()`, and
  `_pull_user_integration_imap()` to pass the resolved filter
- Update IMAP accounts API (schemas, create/update handlers, response serializer)
- Update IMAP accounts UI to show attachment filter dropdown in modal and
  display filter badges on account cards
- Add 6 new tests covering attachment filter behaviour
- Update ConfigurationGuide.md, EmailIngestion.md, and .env.demo

Co-authored-by: christianlouis <361235+christianlouis@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot]
2026-03-12 00:59:54 +00:00
parent 5e45b68cc1
commit 554bb21d32
11 changed files with 300 additions and 22 deletions
@@ -0,0 +1,28 @@
"""Add attachment_filter column to user_imap_accounts table.
Revision ID: 032_add_imap_attachment_filter
Revises: 031_add_compliance_templates
Create Date: 2026-03-12
"""
from typing import Union
import sqlalchemy as sa
from alembic import op
revision: str = "032_add_imap_attachment_filter"
down_revision: Union[str, None] = "031_add_compliance_templates"
depends_on: Union[str, None] = None
def upgrade() -> None:
"""Add attachment_filter column to user_imap_accounts."""
op.add_column(
"user_imap_accounts",
sa.Column("attachment_filter", sa.String(50), nullable=True),
)
def downgrade() -> None:
"""Remove attachment_filter column from user_imap_accounts."""
op.drop_column("user_imap_accounts", "attachment_filter")