Skip to content

Import mail that is newer than a set date#2

Open
Cyriuz wants to merge 2 commits into
threehappypenguins:mainfrom
Cyriuz:main
Open

Import mail that is newer than a set date#2
Cyriuz wants to merge 2 commits into
threehappypenguins:mainfrom
Cyriuz:main

Conversation

@Cyriuz

@Cyriuz Cyriuz commented Mar 15, 2026

Copy link
Copy Markdown

Fixes #1. Included a small change to avoid calling gmail api when nothing is being imported.

@threehappypenguins

Copy link
Copy Markdown
Owner

Critical Bug — The Feature is a No-Op

TL;DR: The two missing since=imap_cfg.get("since_date") or None arguments in run.py are the only thing standing between this being a complete, well-structured implementation and a feature that silently does nothing.


The since_date config value is never actually read from the config or passed to fetch_messages in run.py. Both call sites are missing the since= argument:

run.py lines 82-90:

uid_validity, messages_iter = fetch_messages(
    host=imap_cfg["host"],
    port=int(imap_cfg.get("port", 993)),
    username=imap_cfg["username"],
    password=imap_cfg["password"],
    mailbox=mailbox,
    use_ssl=imap_cfg.get("use_ssl", True),
    last_processed_uid=last_uid,
    # ← since=imap_cfg.get("since_date") is missing
)

run.py lines 249-257:

uid_validity, messages_iter = fetch_messages(
    host=imap_cfg["host"],
    port=int(imap_cfg.get("port", 993)),
    username=imap_cfg["username"],
    password=imap_cfg["password"],
    mailbox=mailbox,
    use_ssl=imap_cfg.get("use_ssl", True),
    last_processed_uid=last_uid,
    # ← since=imap_cfg.get("since_date") is missing
)

The since parameter was added to fetch_messages in imap_client.py, the config field is stored and validated, the UI exposes it — but the bridge between the config and the IMAP search was never written. Setting since_date will have zero effect.

The fix is to add since=imap_cfg.get("since_date") or None to both calls (the or None matters, because the update handler can store an empty string "" when clearing the field, which would crash _format_imap_date if passed through).


Secondary Bug — Empty String since_date Can Crash

In api_config_update, clearing the date sets cfg["imap"]["since_date"] = "" (an empty string, not None). Once the since= wiring is in place, that empty string would reach _format_imap_datedatetime.date.fromisoformat("")ValueError. The fix is either to store None when the value is "", or to guard in run.py with or None.


The Rest of the IMAP Implementation is Correct

  • _format_imap_date correctly converts ISO date strings and datetime.date objects to IMAP's DD-MMM-YYYY format.
  • Using IMAP SINCE on INTERNALDATE (arrival date, not sent date) is the right choice for this use case — it matches the behavior users expect when migrating from a POP3 setup.
  • Combining UID X:* and SINCE date in a single search criteria string is valid per RFC 3501.
  • The since parameter defaults to None, making it fully backward-compatible.

The "Lazy Gmail Init" Change — Good Idea, One Concern

This restructures both run_once and run_copy_all so the Gmail API is only initialized on-demand when the first message that actually needs importing is encountered (not duplicate, not dry-run).

It's a good idea overall:

  • Avoids unnecessary OAuth token refreshes on idle polling cycles (no new mail → no API call).
  • Avoids hitting Gmail API quota on runs where everything is a hash-duplicate and just gets deleted from ISP.
  • The logic is correct in both functions: if dry_run: continue always fires before if not service:, so Gmail is never initialized during a dry run.

One behavioral change to be aware of: Previously, if your Gmail credentials were expired or revoked, run_once would fail immediately and loudly even on an idle cycle. Now you won't discover broken credentials until actual mail arrives. Whether that's acceptable depends on whether you rely on the polling loop as an implicit credential health check. It's not a bug, but worth knowing.

@Cyriuz

Cyriuz commented Mar 16, 2026

Copy link
Copy Markdown
Author

Sorry, missed staging run.py for the feature change!

@threehappypenguins

Copy link
Copy Markdown
Owner

Sorry, missed staging run.py for the feature change!

I also made some pretty big updates, so now there are merge conflicts. Sorry!

I do want to implement your feature though, and I like the idea of avoiding unnecessary API calls.

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.

Import only mail that is newer than a set date

2 participants