From 6de8d7f52e2c2c5844cd10c79757bae776708a7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fl=C3=A1vio=20Veloso=20Soares?= Date: Mon, 8 Jun 2026 16:04:39 -0700 Subject: [PATCH] feat(email): add postActionExpunge option to gate broad IMAP expunge --- docs/chat-apps.md | 2 ++ nanobot/channels/email.py | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/chat-apps.md b/docs/chat-apps.md index 7d63f4419..0d65b06f4 100644 --- a/docs/chat-apps.md +++ b/docs/chat-apps.md @@ -581,6 +581,7 @@ Give nanobot its own email account. It polls **IMAP** for incoming mail and repl > This runs only after an accepted email is successfully delivered to the AI pipeline. > - `postActionMoveMailbox`: Destination mailbox used when `postAction` is `"move"` (for example `"Processed"` or `"[Gmail]/Trash"`). > - `postActionIgnoreSkipped`: If `true` (default), skipped emails are ignored for post-action and not moved/deleted. +> - `postActionExpunge`: When `true`, the channel performs a full mailbox cleanup after processing emails (default `false`). Enable only on very old IMAP servers that lack modern UIDPLUS support. Note that this will expunge **all** messages marked as deleted in the mailbox, including ones not handled by the agent. Leaving this off is safe for all modern IMAP servers. > - `allowedAttachmentTypes`: Save inbound attachments matching these MIME types — `["*"]` for all, e.g. `["application/pdf", "image/*"]` (default `[]` = disabled). > - `maxAttachmentSize`: Max size per attachment in bytes (default `2000000` / 2MB). > - `maxAttachmentsPerEmail`: Max attachments to save per email (default `5`). @@ -604,6 +605,7 @@ Give nanobot its own email account. It polls **IMAP** for incoming mail and repl "postAction": "move", "postActionMoveMailbox": "[Gmail]/Trash", "postActionIgnoreSkipped": true, + "postActionExpunge": false, "allowedAttachmentTypes": ["application/pdf", "image/*"] } } diff --git a/nanobot/channels/email.py b/nanobot/channels/email.py index 984c000cd..7d1abf244 100644 --- a/nanobot/channels/email.py +++ b/nanobot/channels/email.py @@ -56,6 +56,7 @@ class EmailConfig(Base): mark_seen: bool = True post_action: Literal["delete", "move"] | None = None post_action_move_mailbox: str | None = None + post_action_expunge: bool = False post_action_ignore_skipped: bool = True max_body_chars: int = 12000 subject_prefix: str = "Re: " @@ -739,7 +740,8 @@ class EmailChannel(BaseChannel): if status == "OK": return self.logger.warning("UID EXPUNGE failed for UID {}, falling back to EXPUNGE", uid) - client.expunge() + if self.config.post_action_expunge: + client.expunge() @classmethod def _is_stale_imap_error(cls, exc: Exception) -> bool: