Skip to content

Automatically recover stale mail IDs and retry once - #23

Merged
mrinc merged 1 commit into
masterfrom
fix/recover-stale-mail-actions
Sep 13, 2026
Merged

mrinc merged 1 commit into
masterfrom
fix/recover-stale-mail-actions

Conversation

@bcbetterninja

Copy link
Copy Markdown
Collaborator

A queued move can retain a server ID that changed when another client moved the message. Repeating the old ID never succeeds. Missing-object failures now automatically attempt identity recovery once, including existing paused actions, and retry a verified repair in the same Busy-processing pass.

  • Search requires a unique exact Internet Message-ID within the same mailbox and rejects capped/ambiguous results. Refetch the candidate before changing local state.
  • Atomically verify the queued action has not changed or started, update IDs throughout dependent move/state actions, preserve destination and failure history, and replace the obsolete cached ID. If the message is already at the destination, confirm the move without repeating it.
  • Persist the automatic-attempt marker across restart. Uncertain recovery or a failed repaired attempt pauses with visible details. Sends and drafts are excluded. Manual Recover and retry remains available, with equivalent permission-gated recover_mail_action MCP support.

Validation: Release build with zero warnings/errors and 522 passing tests. Regressions cover automatic old-ID/new-ID execution without a user command, failure pause, restart persistence, exact versus ambiguous matches, concurrent queue edits, dependent moves, destination confirmation, cancellation provenance, stale source sync and MCP permissions/discovery. Native Busy preview checked with fictional data in light/dark modes. No live mailbox content or queued action was changed during development.

@coderabbitai

coderabbitai Bot commented Sep 13, 2026

Copy link
Copy Markdown

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Advanced

Run ID: 5cfb4d68-1bc2-45dd-9722-15ffdd7e2362


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@mrinc
mrinc merged commit f7a9e88 into master Sep 13, 2026
9 checks passed
@mrinc
mrinc deleted the fix/recover-stale-mail-actions branch September 13, 2026 20:35

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e1f65e0a18

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

catch (HttpRequestException error) when (error.StatusCode == HttpStatusCode.NotFound) { }
if (verified is null)
{
var results = await provider.SearchMessagesAsync(account, mailbox, cached.Subject, 100, token);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Search by stable identity when the subject is empty

For a subjectless Microsoft 365 message whose saved provider ID now returns 404, this passes an empty query to Microsoft365MailProvider.SearchMessagesAsync, which immediately returns an empty result for whitespace queries. Consequently both automatic and manual recovery always report no unique match and leave the action paused even though a usable Internet Message-ID is cached. Use a nonempty identity-based query or otherwise support subjectless messages.

Useful? React with 👍 / 👎.

Comment on lines +64 to +65
if (verified.ProviderId != current.ProviderId)
await DeleteMessageAsync(connection, transaction, current.MailboxId, current.ProviderId!, token).ConfigureAwait(false);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Keep obsolete IDs suppressed after state recovery

When a standalone UpdateState action is recovered to a new provider ID, this deletes the old cached row but records no durable tombstone or alias. The repaired state action is deleted by CompleteMessageStateAsync, after which a delayed source-folder page containing the old ID passes through ApplySyncPageAsync and is blindly upserted, leaving both the valid and obsolete copies visible and allowing subsequent actions to target the dead ID again. Preserve enough recovery metadata to reject stale sync records for the replaced ID.

Useful? React with 👍 / 👎.

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