Skip to content

Various IMAP improvements#357

Open
vanboom wants to merge 2 commits into
abhinavxd:mainfrom
vanboom:imapdelete
Open

Various IMAP improvements#357
vanboom wants to merge 2 commits into
abhinavxd:mainfrom
vanboom:imapdelete

Conversation

@vanboom

@vanboom vanboom commented Jun 1, 2026

Copy link
Copy Markdown
Contributor
  1. Close [Possible Bug] IMAP is pulling deleted messages #355 by applying filter so deleted emails are not pulled.
  2. Close [Feature Request] Mark fetch emails as Read #354 by allowing Fetch to update the seen flag.
  3. Close [Feature Request] Leave messages on server option #352 by implementing an Expunge Inbox option on the IMAP channel configuration.

I am not sure I have the capability to update all of the language translations. How do you typically do that? AI?

Summary by CodeRabbit

Release Notes

  • New Features

    • Added IMAP expunge inbox setting to delete imported emails from the email server after import
  • Style

    • Message bubbles now display at full width instead of constrained width
    • Message collapse threshold reduced from 400px to 300px
    • Chat widget icon rendering improved with better contrast detection

vanboom added 2 commits June 1, 2026 09:27
Close abhinavxd#354 by allowing Fetch to update the seen flag.
Close abhinavxd#352 by implementing an Expunge Inbox option on the IMAP channel
configuration.
@coderabbitai

coderabbitai Bot commented Jun 1, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

This PR implements the IMAP inbox expunge feature—allowing emails to be deleted from the server after import—alongside message bubble styling refinements and widget icon updates. The IMAP changes include backend data model updates, OAuth provider defaults, server-side deletion/expunge logic with UID tracking, and corresponding frontend admin UI. Message bubble and widget updates adjust width, collapse behavior, CSS classes, and icon rendering.

Changes

IMAP Expunge Feature

Layer / File(s) Summary
IMAP model and provider defaults
internal/inbox/models/models.go, cmd/oauth.go
IMAPConfig gains ExpungeInbox boolean field; OAuth provider defaults set it to false for all new inboxes.
IMAP message fetching and expunge processing
internal/inbox/channel/email/imap.go
Mailbox opens in read-write mode; search filters deleted messages; fetch collects UIDs and flags; after successful processing, messages are batch-marked as \Deleted and expunged when enabled.
Admin UI for expunge configuration
frontend/apps/main/src/features/admin/inbox/formSchema.js, frontend/apps/main/src/features/admin/inbox/EmailInboxForm.vue, i18n/en-US.json
Form schema validates expunge_inbox boolean; inbox form adds toggle field with i18n labels and description text.

UI Styling and Development Tooling

Layer / File(s) Summary
Message bubble component and styling
frontend/apps/main/src/features/conversation/message/MessageBubble.vue, frontend/shared-ui/assets/styles/main.scss
Bubble renders at full width (w-full), collapse threshold lowered to 300px, directional CSS classes (message-outgoing, message-incoming) added; SCSS updates width behavior and introduces directional variants with dark theme overrides.
Widget icon and contrast styling
static/widget.js
Contrast color calculation uses updated luminance threshold; default launcher icon now renders as inline SVG chat-bubble with stroke color from contrast calculation.
Zed development environment tasks
.zed/tasks.json
Configuration adds "Make" task (make -j12) and "Libredesk" task (./libredesk) with terminal reveal/hide behavior and output settings.

Sequence Diagram

sequenceDiagram
  participant processMailbox
  participant client as IMAP Client
  participant fetchAndProcessMessages
  participant envelope as Envelope Handler
  client->>client: Select mailbox (ReadOnly: false)
  processMailbox->>fetchAndProcessMessages: ExpungeInbox flag
  client->>client: Search (NotFlag: [\\Deleted])
  fetchAndProcessMessages->>client: Fetch with UID and Flags
  fetchAndProcessMessages->>fetchAndProcessMessages: Collect message UID
  envelope->>envelope: Process message
  fetchAndProcessMessages->>fetchAndProcessMessages: Track successful UID
  fetchAndProcessMessages->>client: STORE +FLAGS (\\Deleted)
  client->>client: EXPUNGE
Loading

🎯 3 (Moderate) | ⏱️ ~25 minutes

🐰 Emails hop away from servers now,
When expunge says "go!"—deleted, how!
Bubbles bloom full-width with grace,
Widget icons find their place.
Tasks configure—Dev zen found.

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning Multiple out-of-scope changes detected: .zed/tasks.json (development tasks), MessageBubble.vue UI width changes, main.scss styling updates, widget.js chat icon rendering, and static asset modifications are unrelated to the three IMAP issues. Remove or isolate out-of-scope changes: revert .zed/tasks.json, MessageBubble.vue width/height changes, main.scss message styling, and widget.js icon logic to focus the PR solely on IMAP functionality and necessary forms/translations.
Title check ❓ Inconclusive The title 'Various IMAP improvements' is vague and generic, using non-descriptive terminology that doesn't convey the specific changes (IMAP expunge/delete, flag handling, and UI additions). Consider using a more specific title that highlights the primary change, such as 'Add IMAP expunge option and prevent pulling deleted messages' or 'Implement IMAP message deletion and server-side flag handling'.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues check ✅ Passed All three linked issues (#355, #354, #352) have their coding requirements met: deleted message filtering via NotFlag [#355], ReadOnly=false for Seen flag setting [#354], and ExpungeInbox configuration option [#352].
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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 and usage tips.

}

if _, err := client.Select(cfg.Mailbox, &imap.SelectOptions{ReadOnly: true}).Wait(); err != nil {
if _, err := client.Select(cfg.Mailbox, &imap.SelectOptions{ReadOnly: false}).Wait(); err != nil {

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.

Fetch will automatically mark the email as read, but needs the ReadOnly: true setting to do that.

}

return e.fetchAndProcessMessages(ctx, client, searchResults, e.Identifier())
return e.fetchAndProcessMessages(ctx, client, searchResults, e.Identifier(), cfg.ExpungeInbox)

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.

Passing in the user option for the expunge inbox setting.

func (e *Email) searchMessages(client *imapclient.Client, since time.Time) (*imap.SearchData, error) {
criteria := &imap.SearchCriteria{
Since: since,
NotFlag: []imap.Flag{imap.FlagDeleted},

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.

#355 don't pull deleted messages that have not been expunged. This should fix some issues with email reappearing after being deleted by external clients also.

// Fetch envelope and headers needed for auto-reply detection.
fetchOptions := &imap.FetchOptions{
Envelope: true,
UID: true,

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.

Getting the UID seemed very tricky. It works, but maybe an imap expert can review this?

}

}
fmt.Printf("UIDs to delete: %s\n", uidsToDelete.String())

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.

I forgot to remove this debugging statement.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🧹 Nitpick comments (6)
frontend/shared-ui/assets/styles/main.scss (1)

382-388: ⚡ Quick win

Use CSS variables instead of hardcoded colors.

The .message-incoming styles use hardcoded hex colors (#a0b8c8, #323a48) instead of the CSS variable pattern used consistently throughout this file (e.g., hsl(var(--border)), hsl(var(--background))). This makes the colors harder to theme and maintain.

Additionally, the 4px border is noticeably thicker than the standard 1px borders used elsewhere—verify this is intentional.

♻️ Refactor to use CSS variables
 .message-incoming{
-    border: 4px solid `#a0b8c8`;
+    border: 2px solid hsl(var(--border));
 }
 
 .dark .message-incoming{
-    background: `#323a48`;
+    background: hsl(var(--muted));
 }

Adjust the specific CSS variables (--border, --muted, etc.) and border width as needed to match your design intent.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/shared-ui/assets/styles/main.scss` around lines 382 - 388, Replace
the hardcoded colors and nonstandard border width in .message-incoming and .dark
.message-incoming with the project's CSS variable pattern: use
hsl(var(--border)) (or hsl(var(--muted)) if more appropriate) for the border
color and hsl(var(--background)) for the dark background; change the border from
4px to the standard 1px unless the 4px thickness is intentional, and ensure both
.message-incoming and .dark .message-incoming reference the same variables for
theming consistency.
.zed/tasks.json (1)

50-50: 💤 Low value

Consider save: "all" for the Make task.

With save: "none", unsaved buffer changes won't be included in the build, which might surprise developers who expect their edits to be compiled. Setting save: "all" would ensure all changes are persisted before building.

📝 Optional improvement
-    "save": "none",
+    "save": "all",
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.zed/tasks.json at line 50, Change the Make task's "save" setting from
"none" to "all" so unsaved buffers are persisted before running the build;
locate the Make task entry in .zed/tasks.json and update the "save" property to
"all" to ensure all open files are written prior to executing the make command.
internal/inbox/channel/email/imap.go (3)

337-337: ⚡ Quick win

Improve log message clarity.

The log message could be more informative by including the count of messages being expunged.

📝 Proposed improvement
-			e.lo.Info("EXPUNGE", "email", "Expunging email")
+			e.lo.Info("expunging messages from server", "count", len(uidsToDelete.String()), "inbox_id", e.Identifier())

Note: If len(uidsToDelete) doesn't work correctly (per the verification request above), consider tracking the count separately or using a different method to report it.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/inbox/channel/email/imap.go` at line 337, The log call
e.lo.Info("EXPUNGE", "email", "Expunging email") should include the number of
messages being expunged for clarity—update the message to append or include the
count (e.g., using len(uidsToDelete) or a tracked counter if len(uidsToDelete)
is not reliable) and reference the same context keys; modify the code around the
EXPUNGE log in imap.go (where uidsToDelete is built/used) to compute the count
and pass it into e.lo.Info so logs show "Expunging X emails" or similar.

254-258: 💤 Low value

Simplify comments.

The comments are overly verbose for straightforward type assertion and assignment.

♻️ Proposed simplification
-			// getting the UID for Expunge operation
 			if uidData, ok := item.(imapclient.FetchItemDataUID); ok {
-				// uidData.UID holds the exact ID you need!
-				// Save it to a local variable to append to your messages slice later
-				currentUID = uidData.UID 
+				currentUID = uidData.UID
 			}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/inbox/channel/email/imap.go` around lines 254 - 258, The block
performing the type assertion for imapclient.FetchItemDataUID and assignment to
currentUID is over-commented; replace the verbose comments inside that
if-statement with a single concise line like "Assign UID from fetched item"
(keep the if uidData, ok := item.(imapclient.FetchItemDataUID); ok { currentUID
= uidData.UID } structure) so the intent remains clear but comments are minimal.

330-331: UIDSet delete guard and NumSet conversion in imap.go

  • len(uidsToDelete) > 0 is valid: imap.UIDSet is a []UIDRange, so the zero/nil set has len == 0 (len counts ranges, but that’s enough to detect “non-empty” before calling STORE/EXPUNGE).
  • imap.NumSet(uidsToDelete) is redundant: imap.UIDSet already satisfies the imap.NumSet interface, so you can pass uidsToDelete directly (or assign numSet := uidsToDelete) without an explicit conversion.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/inbox/channel/email/imap.go` around lines 330 - 331, The current
code redundantly converts uidsToDelete with imap.NumSet and can be simplified:
keep the existing guard (if len(uidsToDelete) > 0 && expungeOption) but remove
the unnecessary imap.NumSet conversion since imap.UIDSet already implements
imap.NumSet; use uidsToDelete directly (or assign numSet := uidsToDelete) when
calling STORE/EXPUNGE so you pass the UID set without the extra conversion.
i18n/en-US.json (1)

273-274: 💤 Low value

Consider more user-friendly wording for the title.

The current title "Expunge Server after Importing" uses technical IMAP terminology ("expunge") that may not be immediately clear to all users. Consider a more descriptive alternative.

Optional alternative:

  "admin.inbox.expungeInbox": "Delete emails from server after import",

However, the current wording is acceptable and the description clarifies the behavior, so this is just a suggestion.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@i18n/en-US.json` around lines 273 - 274, The string value for the i18n key
"admin.inbox.expungeInbox" uses the technical term "Expunge" which may confuse
users; update the value in i18n/en-US.json to a more user-friendly phrase such
as "Delete emails from server after import" (or "Remove emails from server after
importing") while keeping "admin.inbox.expungeInbox.description" unchanged so
the description still clarifies the behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@frontend/apps/main/src/features/admin/inbox/EmailInboxForm.vue`:
- Around line 490-500: Add the missing expunge_inbox toggle to the OAuth IMAP
configuration block by inserting a FormField for name "imap.expunge_inbox"
inside the v-show="isOAuthInbox" (OAuth IMAP Configuration) section; use the
same SwitchField/FormItem pattern as the manual setup (refer to the existing
FormField usage around "imap.expunge_inbox" and the SwitchField component) so
the switch binds to componentField.modelValue and calls handleChange on
`@update`:checked.

In `@frontend/shared-ui/assets/styles/main.scss`:
- Around line 379-381: The .message-outgoing rule is overriding the Tailwind
bg-private utility (because it appears after `@tailwind` utilities with equal
specificity) and removing the private message visual indicator; remove the
background: inherit declaration from the .message-outgoing selector (or restrict
it to non-private messages only, e.g., target .message-outgoing elements that do
NOT also have the private class) so that the bg-private utility can apply;
update the styling around .message-outgoing (and any private marker class like
bg-private or .message--private) to preserve private message backgrounds.

In `@internal/inbox/channel/email/imap.go`:
- Line 322: Remove the debug fmt.Printf calls that print msgData.uid and replace
them with structured debug logging using the existing logger (e.lo.Debug), e.g.
log the UID via e.lo.Debug with a clear message and include msgData.uid as a
field or formatted value; update both occurrences that print the UID so no
fmt.Printf remains in the IMAP handling code (references: msgData.uid and logger
e.lo.Debug).
- Line 235: The declaration for the variable currentUID (currentUID imap.UID)
contains mixed tabs and spaces; fix it by normalizing the indentation to use
tabs only (align with surrounding var/const blocks and other variable
declarations in imap.go), replacing the spaces before "currentUID" with a single
tab so the variable aligns consistently with other entries in that declaration
block.

---

Nitpick comments:
In @.zed/tasks.json:
- Line 50: Change the Make task's "save" setting from "none" to "all" so unsaved
buffers are persisted before running the build; locate the Make task entry in
.zed/tasks.json and update the "save" property to "all" to ensure all open files
are written prior to executing the make command.

In `@frontend/shared-ui/assets/styles/main.scss`:
- Around line 382-388: Replace the hardcoded colors and nonstandard border width
in .message-incoming and .dark .message-incoming with the project's CSS variable
pattern: use hsl(var(--border)) (or hsl(var(--muted)) if more appropriate) for
the border color and hsl(var(--background)) for the dark background; change the
border from 4px to the standard 1px unless the 4px thickness is intentional, and
ensure both .message-incoming and .dark .message-incoming reference the same
variables for theming consistency.

In `@i18n/en-US.json`:
- Around line 273-274: The string value for the i18n key
"admin.inbox.expungeInbox" uses the technical term "Expunge" which may confuse
users; update the value in i18n/en-US.json to a more user-friendly phrase such
as "Delete emails from server after import" (or "Remove emails from server after
importing") while keeping "admin.inbox.expungeInbox.description" unchanged so
the description still clarifies the behavior.

In `@internal/inbox/channel/email/imap.go`:
- Line 337: The log call e.lo.Info("EXPUNGE", "email", "Expunging email") should
include the number of messages being expunged for clarity—update the message to
append or include the count (e.g., using len(uidsToDelete) or a tracked counter
if len(uidsToDelete) is not reliable) and reference the same context keys;
modify the code around the EXPUNGE log in imap.go (where uidsToDelete is
built/used) to compute the count and pass it into e.lo.Info so logs show
"Expunging X emails" or similar.
- Around line 254-258: The block performing the type assertion for
imapclient.FetchItemDataUID and assignment to currentUID is over-commented;
replace the verbose comments inside that if-statement with a single concise line
like "Assign UID from fetched item" (keep the if uidData, ok :=
item.(imapclient.FetchItemDataUID); ok { currentUID = uidData.UID } structure)
so the intent remains clear but comments are minimal.
- Around line 330-331: The current code redundantly converts uidsToDelete with
imap.NumSet and can be simplified: keep the existing guard (if len(uidsToDelete)
> 0 && expungeOption) but remove the unnecessary imap.NumSet conversion since
imap.UIDSet already implements imap.NumSet; use uidsToDelete directly (or assign
numSet := uidsToDelete) when calling STORE/EXPUNGE so you pass the UID set
without the extra conversion.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: ca023e82-934c-4f45-b4ec-d898f07d985e

📥 Commits

Reviewing files that changed from the base of the PR and between 5cd691f and 008508a.

📒 Files selected for processing (10)
  • .zed/tasks.json
  • cmd/oauth.go
  • frontend/apps/main/src/features/admin/inbox/EmailInboxForm.vue
  • frontend/apps/main/src/features/admin/inbox/formSchema.js
  • frontend/apps/main/src/features/conversation/message/MessageBubble.vue
  • frontend/shared-ui/assets/styles/main.scss
  • i18n/en-US.json
  • internal/inbox/channel/email/imap.go
  • internal/inbox/models/models.go
  • static/widget.js

Comment on lines +490 to +500
<FormField v-slot="{ componentField, handleChange }" name="imap.expunge_inbox">
<FormItem>
<SwitchField
:title="$t('admin.inbox.expungeInbox')"
:description="$t('admin.inbox.expungeInbox.description')"
:checked="componentField.modelValue"
@update:checked="handleChange"
/>
</FormItem>
</FormField>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Add expunge_inbox field to OAuth IMAP configuration section.

The expunge inbox toggle is only added to the manual setup section (lines 490-500), but OAuth-connected inboxes also support this feature. Users with OAuth-configured inboxes should be able to enable/disable expunge from the UI.

Add the same field to the OAuth IMAP configuration section (after line 278, within the v-show="isOAuthInbox" block).

➕ Proposed addition

After line 278 (inside the OAuth IMAP Configuration section), add:

      <FormField v-slot="{ componentField, handleChange }" name="imap.expunge_inbox">
        <FormItem>
          <SwitchField
            :title="$t('admin.inbox.expungeInbox')"
            :description="$t('admin.inbox.expungeInbox.description')"
            :checked="componentField.modelValue"
            `@update`:checked="handleChange"
          />
        </FormItem>
      </FormField>
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/apps/main/src/features/admin/inbox/EmailInboxForm.vue` around lines
490 - 500, Add the missing expunge_inbox toggle to the OAuth IMAP configuration
block by inserting a FormField for name "imap.expunge_inbox" inside the
v-show="isOAuthInbox" (OAuth IMAP Configuration) section; use the same
SwitchField/FormItem pattern as the manual setup (refer to the existing
FormField usage around "imap.expunge_inbox" and the SwitchField component) so
the switch binds to componentField.modelValue and calls handleChange on
`@update`:checked.

Comment on lines +379 to +381
.message-outgoing{
background: inherit;
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

background: inherit breaks private message styling.

The .message-outgoing rule sets background: inherit, which will override the bg-private Tailwind utility applied to private outgoing messages. Because .message-outgoing is defined after the @tailwind utilities layer in the cascade (and has the same specificity), it wins via source order. This removes the visual privacy indicator for private outgoing messages, which could lead users to mistake private messages for non-private ones.

🔧 Proposed fix

Remove the background: inherit declaration entirely, or scope it to non-private messages only:

-.message-outgoing{
-    background: inherit;
-}
+.message-outgoing:not(.bg-private){
+    background: transparent;
+}

Alternatively, if the intent is to remove background from non-private outgoing messages, the declaration should be scoped more carefully to avoid affecting private messages.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
.message-outgoing{
background: inherit;
}
.message-outgoing:not(.bg-private){
background: transparent;
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/shared-ui/assets/styles/main.scss` around lines 379 - 381, The
.message-outgoing rule is overriding the Tailwind bg-private utility (because it
appears after `@tailwind` utilities with equal specificity) and removing the
private message visual indicator; remove the background: inherit declaration
from the .message-outgoing selector (or restrict it to non-private messages
only, e.g., target .message-outgoing elements that do NOT also have the private
class) so that the bg-private utility can apply; update the styling around
.message-outgoing (and any private marker class like bg-private or
.message--private) to preserve private message backgrounds.

autoReply bool
isLoop bool
extractedMessageID string
currentUID imap.UID

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Fix inconsistent whitespace.

The variable declaration uses mixed tabs and spaces. Use consistent indentation (tabs).

🧹 Proposed fix
-			currentUID		   imap.UID
+			currentUID imap.UID
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
currentUID imap.UID
currentUID imap.UID
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/inbox/channel/email/imap.go` at line 235, The declaration for the
variable currentUID (currentUID imap.UID) contains mixed tabs and spaces; fix it
by normalizing the indentation to use tabs only (align with surrounding
var/const blocks and other variable declarations in imap.go), replacing the
spaces before "currentUID" with a single tab so the variable aligns consistently
with other entries in that declaration block.

} else {
if expungeOption {
// If deletion is enabled, add the message to the delete list
fmt.Printf("Add UID to Expunge %d\n", msgData.uid)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Remove debug print statements.

These fmt.Printf statements should be removed before merging to production. Use the structured logger (e.lo.Debug) instead if debugging output is needed.

🔧 Proposed fix
 			if expungeOption {
 				// If deletion is enabled, add the message to the delete list
-				fmt.Printf("Add UID to Expunge %d\n", msgData.uid)
+				e.lo.Debug("adding message UID to expunge list", "uid", msgData.uid)
 				uidsToDelete.AddNum(msgData.uid)
 			}
 		}

 	}
-	fmt.Printf("UIDs to delete: %s\n", uidsToDelete.String())
 	// Batch delete messages from server

Also applies to: 328-328

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/inbox/channel/email/imap.go` at line 322, Remove the debug
fmt.Printf calls that print msgData.uid and replace them with structured debug
logging using the existing logger (e.lo.Debug), e.g. log the UID via e.lo.Debug
with a clear message and include msgData.uid as a field or formatted value;
update both occurrences that print the UID so no fmt.Printf remains in the IMAP
handling code (references: msgData.uid and logger e.lo.Debug).

@abhinavxd

Copy link
Copy Markdown
Owner

Hey thanks,

I'll check this over this weekend.

@jleroy

jleroy commented Jun 2, 2026

Copy link
Copy Markdown
Contributor

I am not sure I have the capability to update all of the language translations. How do you typically do that? AI?

@vanboom Don’t touch localizations files, just update the source file i18n/en-US.json as you did. This will trigger an update of the related translations keys on Crowdin.

@abhinavxd

Copy link
Copy Markdown
Owner

This PR mixes various things and has unrelated changes in this.

@abhinavxd

Copy link
Copy Markdown
Owner

I think you commited your zed file by mistake.

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.

[Possible Bug] IMAP is pulling deleted messages [Feature Request] Mark fetch emails as Read [Feature Request] Leave messages on server option

3 participants