Skip to content

Comments

feat: add autosuggestions while sending email#1495

Merged
MrgSub merged 27 commits intoMail-0:stagingfrom
retrogtx:suggestions
Aug 10, 2025
Merged

feat: add autosuggestions while sending email#1495
MrgSub merged 27 commits intoMail-0:stagingfrom
retrogtx:suggestions

Conversation

@retrogtx
Copy link
Contributor

@retrogtx retrogtx commented Jun 26, 2025

EMAIL SUGGESTIONS ARE HERE

suggestion.mp4

Summary by CodeRabbit

  • New Features

    • Introduced an autosuggest feature for email recipients, allowing users to quickly select contacts when composing emails.
    • Recipient fields ("To", "Cc", "Bcc") now use a unified, user-friendly autosuggest input for easier recipient entry.
    • Suggestions are based on recent email history and update dynamically as you type.
  • Improvements

    • Enhanced error handling when removing attachments.
    • Streamlined focus management and form synchronization in the email composer.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jun 26, 2025

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Walkthrough

Manual recipient input management in the email composer has been entirely replaced with a new RecipientAutosuggest component. Backend support for recipient suggestions was added, including caching and parsing logic in the mail agent. The TRPC API and UI now fetch and display recipient suggestions dynamically, streamlining recipient entry and improving efficiency.

Changes

Cohort / File(s) Change Summary
EmailComposer Refactor
apps/mail/components/create/email-composer.tsx
Removed all manual recipient input logic, state, and UI. Integrated new RecipientAutosuggest for "To", "Cc", and "Bcc". Simplified focus and from-email sync logic. Added error handling for attachment removal.
Recipient Autosuggest UI
apps/mail/components/ui/recipient-autosuggest.tsx
Introduced new RecipientAutosuggest component. Handles recipient input, validation, autosuggestion via async query, keyboard/mouse interactions, and integration with react-hook-form.
Mail SuggestRecipients API
apps/server/src/trpc/routes/mail.ts
Added suggestRecipients query to the mailRouter, exposing recipient suggestion functionality to the frontend via TRPC.
ZeroDriver Backend Enhancements
apps/server/src/routes/agent/index.ts
Added recipient cache, parsing of malformed senders, recipient suggestion logic, and cache invalidation on mail send/create/sync/delete. Exposed new methods for thread streaming and deletion. Refactored and re-enabled some methods.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant EmailComposer
    participant RecipientAutosuggest
    participant TRPC
    participant Server(ZeroDriver)

    User->>EmailComposer: Focuses recipient input
    EmailComposer->>RecipientAutosuggest: Renders component
    RecipientAutosuggest->>TRPC: suggestRecipients(query)
    TRPC->>Server(ZeroDriver): suggestRecipients(query)
    Server(ZeroDriver)->>TRPC: Return recipient suggestions
    TRPC->>RecipientAutosuggest: Return suggestions
    RecipientAutosuggest->>User: Display suggestions
    User->>RecipientAutosuggest: Selects or types recipient
    RecipientAutosuggest->>EmailComposer: Update recipients
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • fix: email composer paste #1294: Directly related; both PRs overhaul recipient input logic in EmailComposer, including paste handling and manual input management.
  • refactor durable objects #1764: Strong connection; both PRs add and utilize the suggestRecipients method in ZeroDriver and integrate it into the mail UI.
  • Staging #820: Closely related; introduces the RecipientAutosuggest component that this PR integrates into the EmailComposer.

Suggested reviewers

  • ahmetskilinc

Poem

🚀 Compose, suggest, recipients in tow,
Musk-level autosuggest, let the emails flow.
Backend’s caching, frontend’s sleek,
Manual entry? That’s so last week.
With every chip and dropdown shown,
The future of mail is now well-known!
✉️✨

✨ Finishing Touches
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 7

🧹 Nitpick comments (4)
apps/mail/components/ui/recipient-autosuggest.tsx (4)

6-6: Use the local X icon component for consistency.

The codebase has its own X icon component. Consider importing it from the local icons file instead of using lucide-react to maintain consistency across the application.

-import { X } from 'lucide-react';
+import { X } from '@/components/icons/icons';

69-69: Use optional chaining for cleaner code.

The static analysis tool correctly suggests using optional chaining here for better readability.

-              (c.name && c.name.toLowerCase().includes(query.toLowerCase()))
+              (c.name?.toLowerCase().includes(query.toLowerCase()))

176-181: Consider removing Space key as a trigger for adding emails.

Using the Space key to add emails might interfere with typing names that contain spaces (e.g., "John Doe"). Users might accidentally add incomplete emails when trying to type a space in a name.

       case 'Tab':
-      case ' ':
         if (inputValue.trim() && isValidEmail(inputValue.trim())) {
           e.preventDefault();
           addRecipient(inputValue.trim());
         }
         break;

1-307: Add unit tests for the new RecipientAutosuggest component.

This complex component handles multiple interaction patterns (keyboard navigation, paste handling, API calls, caching) and should have comprehensive test coverage to ensure reliability.

Would you like me to generate unit tests for this component or open an issue to track this task?

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 315b2fc and 583baca.

📒 Files selected for processing (6)
  • apps/mail/components/create/email-composer.tsx (8 hunks)
  • apps/mail/components/ui/recipient-autosuggest.tsx (1 hunks)
  • apps/server/src/lib/contacts-cache.ts (1 hunks)
  • apps/server/src/lib/contacts-indexer.ts (1 hunks)
  • apps/server/src/trpc/routes/mail.ts (2 hunks)
  • apps/server/wrangler.jsonc (3 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (3)
apps/server/src/lib/contacts-indexer.ts (2)
apps/server/src/lib/server-utils.ts (1)
  • getZeroAgent (13-17)
apps/server/src/lib/contacts-cache.ts (1)
  • upsertContacts (19-39)
apps/mail/components/ui/recipient-autosuggest.tsx (3)
apps/mail/providers/query-provider.tsx (1)
  • trpcClient (86-103)
apps/mail/lib/utils.ts (1)
  • cn (51-51)
apps/mail/components/icons/icons.tsx (1)
  • X (805-816)
apps/mail/components/create/email-composer.tsx (1)
apps/mail/components/ui/recipient-autosuggest.tsx (1)
  • RecipientAutosuggest (23-307)
🪛 Biome (1.9.4)
apps/server/src/trpc/routes/mail.ts

[error] 69-69: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 124-124: Unnecessary continue statement

Unsafe fix: Delete the unnecessary continue statement

(lint/correctness/noUnnecessaryContinue)


[error] 144-144: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 155-155: Unnecessary continue statement

Unsafe fix: Delete the unnecessary continue statement

(lint/correctness/noUnnecessaryContinue)


[error] 169-169: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

apps/server/src/lib/contacts-cache.ts

[error] 45-45: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

apps/mail/components/ui/recipient-autosuggest.tsx

[error] 69-69: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

🔇 Additional comments (4)
apps/server/src/trpc/routes/mail.ts (1)

488-491: Good implementation of asynchronous contact caching.

The implementation correctly:

  • Aggregates all recipient types (to, cc, bcc)
  • Uses waitUntil to avoid blocking the send operation
  • Handles optional cc/bcc fields with nullish coalescing
apps/mail/components/create/email-composer.tsx (2)

469-479: Well-implemented fix for fromEmail synchronization.

Good solution for keeping the fromEmail field synchronized when settings or aliases load asynchronously. The use of shouldDirty: false prevents triggering the unsaved changes state unnecessarily.


494-502: Excellent refactoring to use RecipientAutosuggest component.

This change significantly improves code maintainability by:

  • Removing complex manual recipient management logic
  • Delegating validation and UI to a dedicated component
  • Providing a consistent UX across To, Cc, and Bcc fields

Also applies to: 537-545, 553-561

apps/mail/components/ui/recipient-autosuggest.tsx (1)

242-242: Fix the fill property usage on the X icon.

The fill property in the className won't work on SVG elements. Use text color classes instead, as SVG components typically use currentColor for fill.

-              <X className="mt-0.5 h-3.5 w-3.5 fill-black dark:fill-[#9A9A9A]" />
+              <X className="mt-0.5 h-3.5 w-3.5 text-black dark:text-[#9A9A9A]" />

Likely an incorrect or invalid review comment.

@retrogtx retrogtx marked this pull request as draft June 26, 2025 07:46
@retrogtx retrogtx marked this pull request as ready for review June 27, 2025 05:30
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (1)
apps/server/src/lib/contacts-indexer.ts (1)

58-59: Critical: Empty catch block suppresses errors silently.

The empty catch block will suppress all errors without logging, making debugging difficult and potentially missing important contacts during processing.

Apply this diff to add proper error logging:

            } catch (e) {
+              console.warn(`[ContactsIndexer] Failed to process thread ${thread.id}:`, e);
            }
🧹 Nitpick comments (1)
apps/server/src/lib/contacts-indexer.ts (1)

72-72: Make the page limit configurable.

The hard-coded page limit of 50 should be configurable to allow for different processing needs and better resource management.

Consider making this configurable:

+const MAX_PAGES_PER_FOLDER = process.env.CONTACTS_INDEX_MAX_PAGES ? parseInt(process.env.CONTACTS_INDEX_MAX_PAGES) : 50;
...
-        if (pageCount > 50) break;
+        if (pageCount > MAX_PAGES_PER_FOLDER) break;
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 583baca and c8f0ac2.

📒 Files selected for processing (3)
  • apps/server/src/lib/contacts-cache.ts (1 hunks)
  • apps/server/src/lib/contacts-indexer.ts (1 hunks)
  • apps/server/src/trpc/routes/mail.ts (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • apps/server/src/trpc/routes/mail.ts
  • apps/server/src/lib/contacts-cache.ts
🧰 Additional context used
🧠 Learnings (1)
apps/server/src/lib/contacts-indexer.ts (2)
Learnt from: retrogtx
PR: Mail-0/Zero#1468
File: apps/server/src/trpc/routes/mail.ts:386-391
Timestamp: 2025-06-27T04:59:29.709Z
Learning: In apps/server/src/trpc/routes/mail.ts, the attachment processing logic conditionally handles mixed attachment types - it preserves existing File-like objects with arrayBuffer methods while only converting serialized attachments that need processing through toAttachmentFiles.
Learnt from: retrogtx
PR: Mail-0/Zero#1328
File: apps/mail/lib/hotkeys/mail-list-hotkeys.tsx:202-209
Timestamp: 2025-06-18T17:26:50.918Z
Learning: In apps/mail/lib/hotkeys/mail-list-hotkeys.tsx, the switchCategoryByIndex function using hardcoded indices for category hotkeys does not break when users reorder categories, contrary to the theoretical index-shifting issue. The actual implementation has constraints or mechanisms that prevent hotkey targeting issues.
🔇 Additional comments (2)
apps/server/src/lib/contacts-indexer.ts (2)

48-57: Approve the email extraction and weighting logic.

The implementation correctly extracts email addresses from different message fields and applies appropriate weights - higher weights for sent folder recipients (3 for 'to', 2 for 'cc'/'bcc') and standard weight for senders. The case-insensitive email handling is also well implemented.


88-92: Good error handling in the scheduling wrapper.

The scheduleContactsIndexing function properly catches and logs errors while allowing the indexing to run in the background without blocking the caller.

@retrogtx retrogtx requested a review from MrgSub July 7, 2025 16:31
@jazzberry-ai
Copy link

jazzberry-ai bot commented Jul 28, 2025

Bug Report

Name Severity Example test case Description
Incorrect email validation regex High Try to add 'test@example.co.uk' as a recipient The email validation regex in RecipientAutosuggest component incorrectly identifies valid email addresses as invalid, preventing them from being added to the recipient list. The regex does not account for domains with multiple levels, such as '.co.uk'.

Comments? Email us. This is the last day of your free trial. Subscribe at jazzberry.ai.

@coderabbitai coderabbitai bot requested a review from ahmetskilinc July 28, 2025 06:31
@coderabbitai coderabbitai bot added content design Improvements & changes to design & UX labels Jul 28, 2025
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🔭 Outside diff range comments (1)
apps/mail/components/create/email-composer.tsx (1)

32-32: Remove dead code - it's just adding weight.

You've got unused imports (Avatar, AvatarFallback) and variables (isValidEmail, mode, activeConnection) sitting around doing nothing. Clean house.

-import { Avatar, AvatarFallback } from '../ui/avatar';

-const isValidEmail = (email: string): boolean => {
-  // for format like test@example.com
-  const simpleEmailRegex = /^[a-zA-Z0-9._+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
-
-  // for format like name <test@example.com>
-  const displayNameEmailRegex = /^.+\s*<\s*[a-zA-Z0-9._+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}\s*>$/;
-
-  return simpleEmailRegex.test(email) || displayNameEmailRegex.test(email);
-};

-  const [mode] = useQueryState('mode');
-  const { data: activeConnection } = useActiveConnection();

Also applies to: 86-94, 132-132, 139-139

♻️ Duplicate comments (3)
apps/server/wrangler.jsonc (1)

154-157: These placeholder KV namespace IDs will crash in production.

The IDs for CONTACTS_KV are obviously placeholders. You need actual Cloudflare KV namespace IDs or this thing won't even start.

Also applies to: 310-313, 463-466

apps/server/src/lib/contacts-indexer.ts (2)

58-59: Silent failures are the worst failures.

You're catching errors and doing absolutely nothing with them. At least log what went wrong so you can debug this thing.

-            } catch (e) {
-            }
+            } catch (e) {
+              console.warn(`[ContactsIndexer] Failed to process thread ${thread.id}:`, e);
+            }

44-61: This concurrent approach could nuke the API.

Processing 100 threads at once? That's asking for rate limits. Batch this stuff.

-        await Promise.allSettled(
-          threads.map(async (thread: ThreadSummary) => {
+        // Process in batches to avoid API meltdown
+        const BATCH_SIZE = 20;
+        for (let i = 0; i < threads.length; i += BATCH_SIZE) {
+          const batch = threads.slice(i, i + BATCH_SIZE);
+          await Promise.allSettled(
+            batch.map(async (thread: ThreadSummary) => {
             try {
               const threadData: IGetThreadResponse = await agent.getThread(thread.id);
               threadData.messages.forEach((message: ParsedMessage) => {
                 if (folder === 'sent') {
                   (message.to || []).forEach((r: Sender) => addEmail(r.email, r.name, 3));
                   (message.cc || []).forEach((r: Sender) => addEmail(r.email, r.name, 2));
                   (message.bcc || []).forEach((r: Sender) => addEmail(r.email, r.name, 2));
                 }
                 if (message.sender?.email) {
                   addEmail(message.sender.email, message.sender.name, 1);
                 }
               });
             } catch (e) {
               console.warn(`[ContactsIndexer] Failed to process thread ${thread.id}:`, e);
             }
-          })
-        );
+            })
+          );
+        }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c48bb3e and 9f48df5.

📒 Files selected for processing (4)
  • apps/mail/components/create/email-composer.tsx (7 hunks)
  • apps/server/src/lib/contacts-indexer.ts (1 hunks)
  • apps/server/src/trpc/routes/mail.ts (3 hunks)
  • apps/server/wrangler.jsonc (3 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit Inference Engine (AGENT.md)

**/*.{js,jsx,ts,tsx}: Use 2-space indentation
Use single quotes
Limit lines to 100 characters in width
Semicolons are required

Files:

  • apps/server/src/trpc/routes/mail.ts
  • apps/mail/components/create/email-composer.tsx
  • apps/server/src/lib/contacts-indexer.ts
**/*.{js,jsx,ts,tsx,css}

📄 CodeRabbit Inference Engine (AGENT.md)

Use Prettier with sort-imports and Tailwind plugins

Files:

  • apps/server/src/trpc/routes/mail.ts
  • apps/mail/components/create/email-composer.tsx
  • apps/server/src/lib/contacts-indexer.ts
**/*.{ts,tsx}

📄 CodeRabbit Inference Engine (AGENT.md)

Enable TypeScript strict mode

Files:

  • apps/server/src/trpc/routes/mail.ts
  • apps/mail/components/create/email-composer.tsx
  • apps/server/src/lib/contacts-indexer.ts
🧠 Learnings (4)
📓 Common learnings
Learnt from: retrogtx
PR: Mail-0/Zero#1573
File: apps/mail/components/create/template-button.tsx:197-216
Timestamp: 2025-07-28T05:37:50.530Z
Learning: retrogtx prefers less nitpicky code review suggestions and may dismiss detailed accessibility/best practice recommendations with casual responses like "bro please".
apps/server/src/trpc/routes/mail.ts (2)

Learnt from: retrogtx
PR: #1468
File: apps/server/src/trpc/routes/mail.ts:386-391
Timestamp: 2025-06-27T04:59:29.731Z
Learning: In apps/server/src/trpc/routes/mail.ts, the attachment processing logic conditionally handles mixed attachment types - it preserves existing File-like objects with arrayBuffer methods while only converting serialized attachments that need processing through toAttachmentFiles.

Learnt from: retrogtx
PR: #1468
File: apps/server/src/trpc/routes/mail.ts:331-331
Timestamp: 2025-06-28T03:56:09.376Z
Learning: In apps/server/src/trpc/routes/mail.ts, the user indicated they are not using ISO format for the scheduleAt parameter, despite the frontend code showing toISOString() usage in the ScheduleSendPicker component.

apps/mail/components/create/email-composer.tsx (4)

Learnt from: danteissaias
PR: #618
File: apps/mail/components/mail/mail-iframe.tsx:12-12
Timestamp: 2025-04-07T20:46:11.697Z
Learning: In the Mail-0/Zero application, sender emails are guaranteed to be non-empty when passed to components that handle them, making additional empty string validation unnecessary.

Learnt from: retrogtx
PR: #1328
File: apps/mail/lib/hotkeys/mail-list-hotkeys.tsx:202-209
Timestamp: 2025-06-18T17:26:50.918Z
Learning: In apps/mail/lib/hotkeys/mail-list-hotkeys.tsx, the switchCategoryByIndex function using hardcoded indices for category hotkeys does not break when users reorder categories, contrary to the theoretical index-shifting issue. The actual implementation has constraints or mechanisms that prevent hotkey targeting issues.

Learnt from: retrogtx
PR: #1354
File: apps/mail/components/ui/prompts-dialog.tsx:85-88
Timestamp: 2025-06-20T05:03:16.944Z
Learning: In React Hook Form, avoid using useEffect for form state synchronization when the values prop can handle reactive updates automatically. The values prop is specifically designed for this purpose and is more optimal than manual useEffect-based synchronization.

Learnt from: retrogtx
PR: #1468
File: apps/server/src/trpc/routes/mail.ts:386-391
Timestamp: 2025-06-27T04:59:29.731Z
Learning: In apps/server/src/trpc/routes/mail.ts, the attachment processing logic conditionally handles mixed attachment types - it preserves existing File-like objects with arrayBuffer methods while only converting serialized attachments that need processing through toAttachmentFiles.

apps/server/src/lib/contacts-indexer.ts (4)

Learnt from: retrogtx
PR: #1734
File: apps/server/src/lib/driver/google.ts:211-221
Timestamp: 2025-07-15T06:46:33.349Z
Learning: In apps/server/src/lib/driver/google.ts, the normalization of "draft" to "drafts" in the count() method is necessary because the navigation item in apps/mail/config/navigation.ts has id: 'drafts' (plural) while the Google API returns "draft" (singular). The nav-main.tsx component matches stats by comparing stat.label with item.id, so the backend must return "drafts" for the draft counter badge to appear in the sidebar.

Learnt from: retrogtx
PR: #1328
File: apps/mail/lib/hotkeys/mail-list-hotkeys.tsx:202-209
Timestamp: 2025-06-18T17:26:50.918Z
Learning: In apps/mail/lib/hotkeys/mail-list-hotkeys.tsx, the switchCategoryByIndex function using hardcoded indices for category hotkeys does not break when users reorder categories, contrary to the theoretical index-shifting issue. The actual implementation has constraints or mechanisms that prevent hotkey targeting issues.

Learnt from: retrogtx
PR: #1468
File: apps/server/src/trpc/routes/mail.ts:386-391
Timestamp: 2025-06-27T04:59:29.731Z
Learning: In apps/server/src/trpc/routes/mail.ts, the attachment processing logic conditionally handles mixed attachment types - it preserves existing File-like objects with arrayBuffer methods while only converting serialized attachments that need processing through toAttachmentFiles.

Learnt from: retrogtx
PR: #1622
File: apps/server/src/lib/email-verification.ts:189-189
Timestamp: 2025-07-05T05:27:24.623Z
Learning: During testing phases, debug logging should be kept active in apps/server/src/lib/email-verification.ts for BIMI validation and email verification debugging, even if it's verbose.

🪛 GitHub Actions: autofix.ci
apps/mail/components/create/email-composer.tsx

[warning] 32-32: ESLint (no-unused-vars): Identifier 'Avatar' is imported but never used. Consider removing this import.


[warning] 32-32: ESLint (no-unused-vars): Identifier 'AvatarFallback' is imported but never used. Consider removing this import.


[warning] 86-86: ESLint (no-unused-vars): Variable 'isValidEmail' is declared but never used. Unused variables should start with a '_'. Consider removing this declaration.


[warning] 132-132: ESLint (no-unused-vars): Variable 'mode' is declared but never used. Unused variables should start with a '_'. Consider removing this declaration.


[warning] 139-139: ESLint (no-unused-vars): Variable 'activeConnection' is declared but never used. Unused variables should start with a '_'. Consider removing this declaration.

apps/server/src/lib/contacts-indexer.ts

[warning] 58-58: ESLint (no-unused-vars): Catch parameter 'e' is caught but never used. Consider handling this error.

🔇 Additional comments (6)
apps/mail/components/create/email-composer.tsx (4)

619-627: Smart move consolidating recipient inputs.

The RecipientAutosuggest component is way cleaner than the manual input chaos you had before. This is how you scale.

Also applies to: 662-670, 678-686


900-905: Good catch on the error handling.

Finally someone's thinking about what happens when things go wrong. This prevents the whole UI from exploding when attachment removal fails.


300-305: Clean focus management.

Less complexity, same result. This is the way.


579-589: Smart sync logic.

Only updating when values actually change - that's efficiency. No wasted cycles.

apps/server/src/trpc/routes/mail.ts (2)

38-50: Clean implementation of recipient suggestions.

Good use of waitUntil for background indexing when cache is empty. Non-blocking, efficient.


424-427: Smart async contact updates.

Updating contacts in the background after send - that's how you keep things fast. No blocking the critical path.

@jazzberry-ai
Copy link

jazzberry-ai bot commented Jul 28, 2025

Bug Report

Name Severity Example test case Description
Case-sensitive filtering in RecipientAutosuggest prevents name suggestions from appearing when casing doesn't match Medium 1. A contact with the name "John Doe" is indexed. 2. In the email composer, the user types "john". 3. No suggestions appear for "John Doe" because the casing doesn't match. The RecipientAutosuggest component filters cached contacts using toLowerCase() on both the email and the query, but not consistently on the contact's name. This prevents suggestions from appearing when the casing of the name in the cache doesn't match the casing of the query. To fix this, convert the name to lowercase before comparing.

Comments? Email us. This is the last day of your free trial. Subscribe at jazzberry.ai.

@coderabbitai coderabbitai bot added the High Priority High Priority Work label Jul 28, 2025
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

♻️ Duplicate comments (1)
apps/server/src/lib/contacts-indexer.ts (1)

81-81: Another silent failure point - not cool! 🛑

Log thread processing failures for debugging.

             });
-          } catch {}
+          } catch (e) {
+            console.warn(`[ContactsIndexer] Failed to process thread ${thread.id}:`, e);
+          }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9f48df5 and cab3da9.

📒 Files selected for processing (4)
  • apps/server/src/lib/contacts-indexer.ts (1 hunks)
  • apps/server/src/routes/agent/index.ts (1 hunks)
  • apps/server/src/routes/agent/rpc.ts (1 hunks)
  • apps/server/src/trpc/routes/mail.ts (3 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit Inference Engine (AGENT.md)

**/*.{js,jsx,ts,tsx}: Use 2-space indentation
Use single quotes
Limit lines to 100 characters in width
Semicolons are required

Files:

  • apps/server/src/routes/agent/rpc.ts
  • apps/server/src/trpc/routes/mail.ts
  • apps/server/src/routes/agent/index.ts
  • apps/server/src/lib/contacts-indexer.ts
**/*.{js,jsx,ts,tsx,css}

📄 CodeRabbit Inference Engine (AGENT.md)

Use Prettier with sort-imports and Tailwind plugins

Files:

  • apps/server/src/routes/agent/rpc.ts
  • apps/server/src/trpc/routes/mail.ts
  • apps/server/src/routes/agent/index.ts
  • apps/server/src/lib/contacts-indexer.ts
**/*.{ts,tsx}

📄 CodeRabbit Inference Engine (AGENT.md)

Enable TypeScript strict mode

Files:

  • apps/server/src/routes/agent/rpc.ts
  • apps/server/src/trpc/routes/mail.ts
  • apps/server/src/routes/agent/index.ts
  • apps/server/src/lib/contacts-indexer.ts
🧠 Learnings (3)
📓 Common learnings
Learnt from: retrogtx
PR: Mail-0/Zero#1573
File: apps/mail/components/create/template-button.tsx:197-216
Timestamp: 2025-07-28T05:37:50.566Z
Learning: retrogtx prefers less nitpicky code review suggestions and may dismiss detailed accessibility/best practice recommendations with casual responses like "bro please".
apps/server/src/trpc/routes/mail.ts (2)

Learnt from: retrogtx
PR: #1468
File: apps/server/src/trpc/routes/mail.ts:386-391
Timestamp: 2025-06-27T04:59:29.731Z
Learning: In apps/server/src/trpc/routes/mail.ts, the attachment processing logic conditionally handles mixed attachment types - it preserves existing File-like objects with arrayBuffer methods while only converting serialized attachments that need processing through toAttachmentFiles.

Learnt from: retrogtx
PR: #1468
File: apps/server/src/trpc/routes/mail.ts:331-331
Timestamp: 2025-06-28T03:56:09.376Z
Learning: In apps/server/src/trpc/routes/mail.ts, the user indicated they are not using ISO format for the scheduleAt parameter, despite the frontend code showing toISOString() usage in the ScheduleSendPicker component.

apps/server/src/lib/contacts-indexer.ts (5)

Learnt from: retrogtx
PR: #1734
File: apps/server/src/lib/driver/google.ts:211-221
Timestamp: 2025-07-15T06:46:33.349Z
Learning: In apps/server/src/lib/driver/google.ts, the normalization of "draft" to "drafts" in the count() method is necessary because the navigation item in apps/mail/config/navigation.ts has id: 'drafts' (plural) while the Google API returns "draft" (singular). The nav-main.tsx component matches stats by comparing stat.label with item.id, so the backend must return "drafts" for the draft counter badge to appear in the sidebar.

Learnt from: retrogtx
PR: #1328
File: apps/mail/lib/hotkeys/mail-list-hotkeys.tsx:202-209
Timestamp: 2025-06-18T17:26:50.918Z
Learning: In apps/mail/lib/hotkeys/mail-list-hotkeys.tsx, the switchCategoryByIndex function using hardcoded indices for category hotkeys does not break when users reorder categories, contrary to the theoretical index-shifting issue. The actual implementation has constraints or mechanisms that prevent hotkey targeting issues.

Learnt from: retrogtx
PR: #1468
File: apps/server/src/trpc/routes/mail.ts:386-391
Timestamp: 2025-06-27T04:59:29.731Z
Learning: In apps/server/src/trpc/routes/mail.ts, the attachment processing logic conditionally handles mixed attachment types - it preserves existing File-like objects with arrayBuffer methods while only converting serialized attachments that need processing through toAttachmentFiles.

Learnt from: retrogtx
PR: #1622
File: apps/server/src/lib/email-verification.ts:189-189
Timestamp: 2025-07-05T05:27:24.623Z
Learning: During testing phases, debug logging should be kept active in apps/server/src/lib/email-verification.ts for BIMI validation and email verification debugging, even if it's verbose.

Learnt from: CR
PR: Mail-0/Zero#0
File: AGENT.md:0-0
Timestamp: 2025-07-21T20:24:46.841Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Limit lines to 100 characters in width

🧬 Code Graph Analysis (1)
apps/server/src/lib/contacts-indexer.ts (4)
apps/server/src/lib/server-utils.ts (1)
  • getZeroAgent (13-18)
apps/server/src/lib/driver/types.ts (1)
  • IGetThreadResponse (6-12)
apps/server/src/routes/agent/index.ts (1)
  • list (1721-1732)
apps/server/src/lib/contacts-cache.ts (1)
  • upsertContacts (19-39)
🪛 GitHub Actions: autofix.ci
apps/server/src/lib/contacts-indexer.ts

[warning] 39-39: eslint(no-unused-vars): Variable 'pageCount' is assigned a value but never used. Unused variables should start with a '_'. Did you mean to use this variable?

🔇 Additional comments (3)
apps/server/src/routes/agent/rpc.ts (1)

213-216: This RPC wrapper is as clean as a Falcon 9 landing. Ship it! 🚀

The async delegation pattern here is exactly what we need - no unnecessary complexity, just pure functionality.

apps/server/src/trpc/routes/mail.ts (2)

39-72: This suggestion merger is like combining SpaceX and Tesla data streams - brilliant! 🎯

The deduplication using lowercase email keys prevents duplicates effectively. Smart move triggering background indexing when the cache is empty.


446-448: Background contact caching - as essential as battery thermal management! 🔋

Smart use of waitUntil to update contacts without blocking the send operation. This is how you build responsive systems.

@jazzberry-ai
Copy link

jazzberry-ai bot commented Jul 28, 2025

Bug Report

Name Severity Example test case Description
Missing error logging in thread processing Low When contact indexing is running, simulate an error while processing a thread. Errors during thread processing are caught but not logged, making debugging difficult.
Potential Security Issue: Inclusion of Stale Email Aliases Medium Add an email alias to an account, index contacts, then remove the alias and index again. The contact suggestions may still show the old alias, which, if compromised, can be a security risk.
Duplicate Emails on Paste due to Case Sensitivity Low Paste "test@example.com" when "Test@example.com" is already in the recipient list. The handlePaste function in RecipientAutosuggest doesn't normalize emails to lowercase before checking for duplicates, resulting in duplicates.

Comments? Email us. This is the last day of your free trial. Subscribe at jazzberry.ai.

@coderabbitai coderabbitai bot requested a review from nizzyabi July 28, 2025 09:29
@jazzberry-ai
Copy link

jazzberry-ai bot commented Aug 6, 2025

An error occured.

This error may be due to rate limits. If this error persists, please email us.

@jazzberry-ai
Copy link

jazzberry-ai bot commented Aug 6, 2025

Bug Report

Name Severity Example test case Description
SQL Injection in contacts.filter Low Provide a malicious string as the query parameter, e.g., a string that attempts to execute arbitrary JavaScript or HTML. The query parameter is not sanitized in contacts.filter, potentially leading to code injection if a user can craft a malicious string.
Performance Issue with Filtering Medium User has a large number of emails in the threads table and provides a common query string. The filtering and sorting is done in memory after fetching LIMIT 100 contacts, even when a query is provided. This may be inefficient if the user's database becomes large, as the contacts array is not limited until after the in memory filter.

Comments? Email us.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

♻️ Duplicate comments (2)
apps/mail/components/ui/recipient-autosuggest.tsx (1)

213-217: Memory leak waiting to happen - like leaving a Tesla unlocked in Oakland.

The setTimeout could fire after component unmount, causing a memory leak. Store the timeout ID in a ref and clear it on unmount.

+  const blurTimeoutRef = useRef<NodeJS.Timeout>();
+
   const handleInputBlur = useCallback(() => {
-    setTimeout(() => {
+    blurTimeoutRef.current = setTimeout(() => {
       document.removeEventListener('mousedown', handleClickOutside);
     }, 150);
   }, [handleClickOutside]);
+
+  useEffect(() => {
+    return () => {
+      if (blurTimeoutRef.current) {
+        clearTimeout(blurTimeoutRef.current);
+      }
+    };
+  }, []);
apps/server/src/routes/agent/index.ts (1)

1823-1907: The caching strategy is solid, but we can optimize further! 🚀

Great work implementing the caching with hash-based invalidation! The error handling for malformed data is particularly robust - like having multiple backup systems on a spacecraft.

One optimization opportunity: Consider making the hardcoded limits (100 for queries, 10 for results) configurable through environment variables. This would let you tune performance based on different deployment scenarios without code changes.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b793eb6 and bc33ebb.

📒 Files selected for processing (4)
  • apps/mail/components/create/email-composer.tsx (7 hunks)
  • apps/mail/components/ui/recipient-autosuggest.tsx (1 hunks)
  • apps/server/src/routes/agent/index.ts (8 hunks)
  • apps/server/src/trpc/routes/mail.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit Inference Engine (AGENT.md)

**/*.{js,jsx,ts,tsx}: Use 2-space indentation
Use single quotes for strings
Limit lines to 100 characters in length
Semicolons are required at the end of statements

Files:

  • apps/server/src/trpc/routes/mail.ts
  • apps/mail/components/ui/recipient-autosuggest.tsx
  • apps/mail/components/create/email-composer.tsx
  • apps/server/src/routes/agent/index.ts
**/*.{js,jsx,ts,tsx,css,scss}

📄 CodeRabbit Inference Engine (AGENT.md)

Use Prettier with sort-imports and Tailwind plugins for code formatting

Files:

  • apps/server/src/trpc/routes/mail.ts
  • apps/mail/components/ui/recipient-autosuggest.tsx
  • apps/mail/components/create/email-composer.tsx
  • apps/server/src/routes/agent/index.ts
**/*.{ts,tsx}

📄 CodeRabbit Inference Engine (AGENT.md)

Enable TypeScript strict mode

Files:

  • apps/server/src/trpc/routes/mail.ts
  • apps/mail/components/ui/recipient-autosuggest.tsx
  • apps/mail/components/create/email-composer.tsx
  • apps/server/src/routes/agent/index.ts
**/*.{css,js,ts,jsx,tsx,mdx}

📄 CodeRabbit Inference Engine (.cursor/rules/tailwind-css-v4.mdc)

**/*.{css,js,ts,jsx,tsx,mdx}: Chain variants together for composable variants (e.g., group-has-data-potato:opacity-100).
Use new variants such as starting, not-*, inert, nth-*, in-*, open (for :popover-open), and ** for all descendants.
Do not use deprecated utilities like bg-opacity-*, text-opacity-*, border-opacity-*, and divide-opacity-*; use the new syntax (e.g., bg-black/50).
Use renamed utilities: shadow-sm is now shadow-xs, shadow is now shadow-sm, drop-shadow-sm is now drop-shadow-xs, drop-shadow is now drop-shadow-sm, blur-sm is now blur-xs, blur is now blur-sm, rounded-sm is now rounded-xs, rounded is now rounded-sm, outline-none is now outline-hidden.
Use bg-(--brand-color) syntax for CSS variables in arbitrary values instead of bg-[--brand-color].
Stacked variants now apply left-to-right instead of right-to-left.

Files:

  • apps/server/src/trpc/routes/mail.ts
  • apps/mail/components/ui/recipient-autosuggest.tsx
  • apps/mail/components/create/email-composer.tsx
  • apps/server/src/routes/agent/index.ts
🧠 Learnings (19)
📓 Common learnings
Learnt from: danteissaias
PR: Mail-0/Zero#618
File: apps/mail/components/mail/mail-iframe.tsx:12-12
Timestamp: 2025-04-07T20:46:11.697Z
Learning: In the Mail-0/Zero application, sender emails are guaranteed to be non-empty when passed to components that handle them, making additional empty string validation unnecessary.
Learnt from: retrogtx
PR: Mail-0/Zero#1573
File: apps/mail/components/create/template-button.tsx:197-216
Timestamp: 2025-07-28T05:37:50.566Z
Learning: retrogtx prefers less nitpicky code review suggestions and may dismiss detailed accessibility/best practice recommendations with casual responses like "bro please".
Learnt from: retrogtx
PR: Mail-0/Zero#1468
File: apps/server/src/main.ts:854-858
Timestamp: 2025-08-04T18:33:59.515Z
Learning: retrogtx gets frustrated with contradictory review suggestions and prefers consistent guidance. When previous suggestions conflict with new ones, acknowledge the contradiction and defer to the existing implementation rather than pushing alternative approaches.
📚 Learning: in apps/server/src/trpc/routes/mail.ts, the attachment processing logic conditionally handles mixed ...
Learnt from: retrogtx
PR: Mail-0/Zero#1468
File: apps/server/src/trpc/routes/mail.ts:386-391
Timestamp: 2025-06-27T04:59:29.731Z
Learning: In apps/server/src/trpc/routes/mail.ts, the attachment processing logic conditionally handles mixed attachment types - it preserves existing File-like objects with arrayBuffer methods while only converting serialized attachments that need processing through toAttachmentFiles.

Applied to files:

  • apps/server/src/trpc/routes/mail.ts
  • apps/mail/components/create/email-composer.tsx
  • apps/server/src/routes/agent/index.ts
📚 Learning: in apps/server/src/trpc/routes/mail.ts, the user indicated they are not using iso format for the sch...
Learnt from: retrogtx
PR: Mail-0/Zero#1468
File: apps/server/src/trpc/routes/mail.ts:331-331
Timestamp: 2025-06-28T03:56:09.376Z
Learning: In apps/server/src/trpc/routes/mail.ts, the user indicated they are not using ISO format for the scheduleAt parameter, despite the frontend code showing toISOString() usage in the ScheduleSendPicker component.

Applied to files:

  • apps/server/src/trpc/routes/mail.ts
  • apps/mail/components/ui/recipient-autosuggest.tsx
📚 Learning: for the "upgrade" link in addconnectiondialog, using a proper element instead of a w...
Learnt from: danteissaias
PR: Mail-0/Zero#902
File: apps/mail/components/connection/add.tsx:77-77
Timestamp: 2025-05-07T16:55:46.513Z
Learning: For the "Upgrade" link in AddConnectionDialog, using a proper <button> element instead of a <span> with onClick is recognized as an accessibility improvement but was deferred as out of scope in PR #902 (CSS variables PR).

Applied to files:

  • apps/mail/components/ui/recipient-autosuggest.tsx
📚 Learning: applies to **/*.{js,jsx,ts,tsx} : semicolons are required at the end of statements...
Learnt from: CR
PR: Mail-0/Zero#0
File: AGENT.md:0-0
Timestamp: 2025-08-03T20:41:43.899Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Semicolons are required at the end of statements

Applied to files:

  • apps/mail/components/ui/recipient-autosuggest.tsx
📚 Learning: applies to **/*.{js,jsx,ts,tsx} : limit lines to 100 characters in length...
Learnt from: CR
PR: Mail-0/Zero#0
File: AGENT.md:0-0
Timestamp: 2025-08-03T20:41:43.899Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Limit lines to 100 characters in length

Applied to files:

  • apps/mail/components/ui/recipient-autosuggest.tsx
📚 Learning: in react hook form, avoid using useeffect for form state synchronization when the values prop can ha...
Learnt from: retrogtx
PR: Mail-0/Zero#1354
File: apps/mail/components/ui/prompts-dialog.tsx:85-88
Timestamp: 2025-06-20T05:03:16.944Z
Learning: In React Hook Form, avoid using useEffect for form state synchronization when the values prop can handle reactive updates automatically. The values prop is specifically designed for this purpose and is more optimal than manual useEffect-based synchronization.

Applied to files:

  • apps/mail/components/ui/recipient-autosuggest.tsx
  • apps/mail/components/create/email-composer.tsx
📚 Learning: during testing phases, debug logging should be kept active in apps/server/src/lib/email-verification...
Learnt from: retrogtx
PR: Mail-0/Zero#1622
File: apps/server/src/lib/email-verification.ts:189-189
Timestamp: 2025-07-05T05:27:24.623Z
Learning: During testing phases, debug logging should be kept active in apps/server/src/lib/email-verification.ts for BIMI validation and email verification debugging, even if it's verbose.

Applied to files:

  • apps/mail/components/ui/recipient-autosuggest.tsx
📚 Learning: when working with mailto urls in javascript/typescript, the `url.pathname` property correctly extrac...
Learnt from: danteissaias
PR: Mail-0/Zero#458
File: apps/mail/lib/email-utils.ts:126-131
Timestamp: 2025-03-16T23:14:09.209Z
Learning: When working with mailto URLs in JavaScript/TypeScript, the `url.pathname` property correctly extracts the email address from a mailto URL (e.g., for "mailto:testexample.com?subject=Test", `url.pathname` will be "testexample.com").

Applied to files:

  • apps/mail/components/ui/recipient-autosuggest.tsx
📚 Learning: in the mail-0/zero application, sender emails are guaranteed to be non-empty when passed to componen...
Learnt from: danteissaias
PR: Mail-0/Zero#618
File: apps/mail/components/mail/mail-iframe.tsx:12-12
Timestamp: 2025-04-07T20:46:11.697Z
Learning: In the Mail-0/Zero application, sender emails are guaranteed to be non-empty when passed to components that handle them, making additional empty string validation unnecessary.

Applied to files:

  • apps/mail/components/ui/recipient-autosuggest.tsx
  • apps/mail/components/create/email-composer.tsx
📚 Learning: in the mail-0/zero theme system (apps/mail/lib/themes/theme-utils.ts), when color themes are being a...
Learnt from: snehendu098
PR: Mail-0/Zero#1323
File: apps/mail/lib/themes/theme-utils.ts:318-318
Timestamp: 2025-06-24T06:22:58.753Z
Learning: In the Mail-0/Zero theme system (apps/mail/lib/themes/theme-utils.ts), when color themes are being applied, all color values come in HSL format, so there's no need for additional format validation when converting colors with hslToHex().

Applied to files:

  • apps/mail/components/ui/recipient-autosuggest.tsx
  • apps/mail/components/create/email-composer.tsx
📚 Learning: in apps/mail/lib/hotkeys/mail-list-hotkeys.tsx, the switchcategorybyindex function using hardcoded i...
Learnt from: retrogtx
PR: Mail-0/Zero#1328
File: apps/mail/lib/hotkeys/mail-list-hotkeys.tsx:202-209
Timestamp: 2025-06-18T17:26:50.918Z
Learning: In apps/mail/lib/hotkeys/mail-list-hotkeys.tsx, the switchCategoryByIndex function using hardcoded indices for category hotkeys does not break when users reorder categories, contrary to the theoretical index-shifting issue. The actual implementation has constraints or mechanisms that prevent hotkey targeting issues.

Applied to files:

  • apps/mail/components/ui/recipient-autosuggest.tsx
  • apps/mail/components/create/email-composer.tsx
  • apps/server/src/routes/agent/index.ts
📚 Learning: on small and medium screens (mobile devices), buttons don't naturally lose focus after being clicked...
Learnt from: Fahad-Dezloper
PR: Mail-0/Zero#1440
File: apps/mail/components/create/ai-chat.tsx:101-113
Timestamp: 2025-06-22T19:23:10.599Z
Learning: On small and medium screens (mobile devices), buttons don't naturally lose focus after being clicked like they do on desktop browsers. This requires manual intervention using setTimeout with additional blur() calls and DOM manipulation to properly clear focus and active states in button click handlers for responsive design.

Applied to files:

  • apps/mail/components/ui/recipient-autosuggest.tsx
📚 Learning: in draft deletion operations, using settimeout with a delay (like 500ms) before showing success toas...
Learnt from: AnjanyKumarJaiswal
PR: Mail-0/Zero#1732
File: apps/mail/components/create/email-composer.tsx:634-657
Timestamp: 2025-07-15T03:31:14.991Z
Learning: In draft deletion operations, using setTimeout with a delay (like 500ms) before showing success toast notifications improves UX by allowing UI state changes (like closing composers and clearing IDs) to complete before displaying the toast, preventing jarring immediate toast appearances that could disappear quickly during interface transitions.

Applied to files:

  • apps/mail/components/ui/recipient-autosuggest.tsx
📚 Learning: applies to **/*.{css,js,ts,jsx,tsx,mdx} : do not use deprecated utilities like `bg-opacity-*`, `text...
Learnt from: CR
PR: Mail-0/Zero#0
File: .cursor/rules/tailwind-css-v4.mdc:0-0
Timestamp: 2025-08-03T20:42:04.207Z
Learning: Applies to **/*.{css,js,ts,jsx,tsx,mdx} : Do not use deprecated utilities like `bg-opacity-*`, `text-opacity-*`, `border-opacity-*`, and `divide-opacity-*`; use the new syntax (e.g., `bg-black/50`).

Applied to files:

  • apps/mail/components/ui/recipient-autosuggest.tsx
📚 Learning: applies to **/*.{js,jsx,ts,tsx} : use 2-space indentation...
Learnt from: CR
PR: Mail-0/Zero#0
File: AGENT.md:0-0
Timestamp: 2025-08-03T20:41:43.899Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Use 2-space indentation

Applied to files:

  • apps/mail/components/ui/recipient-autosuggest.tsx
📚 Learning: in apps/server/src/lib/driver/google.ts, the normalization of "draft" to "drafts" in the count() met...
Learnt from: retrogtx
PR: Mail-0/Zero#1734
File: apps/server/src/lib/driver/google.ts:211-221
Timestamp: 2025-07-15T06:46:33.349Z
Learning: In apps/server/src/lib/driver/google.ts, the normalization of "draft" to "drafts" in the count() method is necessary because the navigation item in apps/mail/config/navigation.ts has id: 'drafts' (plural) while the Google API returns "draft" (singular). The nav-main.tsx component matches stats by comparing stat.label with item.id, so the backend must return "drafts" for the draft counter badge to appear in the sidebar.

Applied to files:

  • apps/server/src/routes/agent/index.ts
📚 Learning: retrogtx prefers less nitpicky code review suggestions and may dismiss detailed accessibility/best p...
Learnt from: retrogtx
PR: Mail-0/Zero#1573
File: apps/mail/components/create/template-button.tsx:197-216
Timestamp: 2025-07-28T05:37:50.566Z
Learning: retrogtx prefers less nitpicky code review suggestions and may dismiss detailed accessibility/best practice recommendations with casual responses like "bro please".

Applied to files:

  • apps/server/src/routes/agent/index.ts
📚 Learning: retrogtx gets frustrated with contradictory review suggestions and prefers consistent guidance. when...
Learnt from: retrogtx
PR: Mail-0/Zero#1468
File: apps/server/src/main.ts:854-858
Timestamp: 2025-08-04T18:33:59.515Z
Learning: retrogtx gets frustrated with contradictory review suggestions and prefers consistent guidance. When previous suggestions conflict with new ones, acknowledge the contradiction and defer to the existing implementation rather than pushing alternative approaches.

Applied to files:

  • apps/server/src/routes/agent/index.ts
🧬 Code Graph Analysis (1)
apps/server/src/trpc/routes/mail.ts (3)
apps/server/src/trpc/trpc.ts (1)
  • activeDriverProcedure (45-87)
apps/server/src/ctx.ts (1)
  • HonoContext (13-13)
apps/server/src/lib/server-utils.ts (1)
  • getZeroAgent (28-41)
🪛 Biome (2.1.2)
apps/mail/components/ui/recipient-autosuggest.tsx

[error] 267-267: The elements with this role can be changed to the following elements:
For examples and more information, see WAI-ARIA Roles (lint/a11y/useSemanticElements) 🔇 Additional comments (5) apps/server/src/trpc/routes/mail.ts (1) 35-48: This TRPC endpoint is cleaner than a Cybertruck's lines. The implementation follows established patterns perfectly - proper zod validation, sensible defaults, and clean integration with the agent layer. The real performance magic happens in the agent's suggestRecipients method. apps/mail/components/create/email-composer.tsx (2) 627-685: This refactor is like going from manual transmission to Autopilot - pure efficiency. Replacing all that manual recipient handling with the RecipientAutosuggest component is a massive win. Clean integration with react-hook-form, proper field separation, and way less code to maintain. 913-918: Error handling done right - like Falcon 9's landing legs, always have a backup plan. Smart move wrapping attachment removal in try-catch. Users deserve graceful error handling, not a crashed UI. apps/server/src/routes/agent/index.ts (2) 319-358: Excellent defensive programming for handling malformed data! 🚀 This is exactly the kind of robust parsing we need when dealing with real-world data chaos. The cascading pattern matching approach ensures we extract useful information even from the messiest inputs. This is like landing a rocket on a barge in rough seas - you need multiple fallback systems. 890-912: Smart move using async generators for thread streaming! 🎯 This streaming approach is like Starlink satellites deploying - sending data in manageable chunks rather than one massive payload. The 2-second rate limiting prevents us from getting throttled by the API. This will scale beautifully for users with massive inboxes.

Comment on lines +110 to +113
const isValidEmail = useCallback((email: string): boolean => {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return emailRegex.test(email);
}, []);
Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

This email regex is like a Model 3 with cloth seats - functional but basic.

The pattern will accept invalid emails like @@.com or test@. - but if your backend does proper validation, this lightweight client-side check might be intentionally simple. Just make sure the backend is bulletproof.


🏁 Script executed:

#!/bin/bash
# Check if backend has proper email validation
rg -A 10 "suggestRecipients|email.*validation" apps/server/src/routes/agent/

Length of output: 1063


Add robust server-side email validation

This client-side regex is like a Falcon 1—lightweight and nimble, but not enough to survive re-entry. It’s fine for a quick UI check, but the server must enforce full RFC5322-compliant validation to keep junk addresses out of orbit. I didn’t see any email validation in apps/server/src/routes/agent/index.ts, so we need to lock this down on the backend.

• apps/mail/components/ui/recipient-autosuggest.tsx (lines 110–113): lightweight regex
• apps/server/src/routes/agent/index.ts: no email validation found

Next steps:

  1. Create apps/server/src/lib/email-validation.ts with a robust validator (e.g. validator.js).
  2. Call it in all email-handling endpoints before persisting or sending.
🤖 Prompt for AI Agents
In apps/mail/components/ui/recipient-autosuggest.tsx lines 110-113, the current
email validation uses a simple regex suitable only for client-side checks. To
fix this, create a new file apps/server/src/lib/email-validation.ts implementing
a robust RFC5322-compliant email validator using a library like validator.js.
Then, update all email-handling endpoints in
apps/server/src/routes/agent/index.ts to call this server-side validator before
processing or storing emails, ensuring strict validation on the backend.

@jazzberry-ai
Copy link

jazzberry-ai bot commented Aug 6, 2025

Bug Report

Name Severity Example test case Description
Incorrect email parsing High "<john.doe@example.com>" The parsing logic incorrectly extracts email addresses enclosed in angle brackets.
Fails to handle name-only input Medium "John Doe" The parsing logic doesn't handle cases where only a name is provided without an email address.
Adds extra characters when parsing from JSON Medium {\"name\": \"John Doe\", \"email\": \"john.doe@example.com\"} The parsing logic includes extra characters (e.g., quotes) when extracting email addresses from JSON strings.

Comments? Email us.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

♻️ Duplicate comments (3)
apps/mail/components/ui/recipient-autosuggest.tsx (2)

112-115: This email regex is still a toy - needs server-side validation like Model S needs Autopilot supervision 🚀

The client-side regex will accept invalid emails. While the backend should handle proper validation, I didn't see any email validation in the suggestRecipients endpoint.


90-92: 300ms debounce is slower than Cybertruck delivery timelines - users need faster feedback ⚡

With the performance issues mentioned in the PR, reducing debounce to 150ms would improve perceived responsiveness.

apps/server/src/routes/agent/index.ts (1)

1824-1908: Houston, we've made progress but still need that index! 🚀

Great job limiting to 100 threads! However, that ORDER BY latest_received_on DESC at line 1827 and 1835 without an index is like trying to land Starship without grid fins.

As mentioned before, add this index to make it zoom:

CREATE INDEX IF NOT EXISTS idx_threads_received_sender 
ON threads(latest_received_on DESC) 
WHERE latest_sender IS NOT NULL;
📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bc33ebb and 10d4a10.

📒 Files selected for processing (2)
  • apps/mail/components/ui/recipient-autosuggest.tsx (1 hunks)
  • apps/server/src/routes/agent/index.ts (8 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit Inference Engine (AGENT.md)

**/*.{js,jsx,ts,tsx}: Use 2-space indentation
Use single quotes for strings
Limit lines to 100 characters in length
Semicolons are required at the end of statements

Files:

  • apps/mail/components/ui/recipient-autosuggest.tsx
  • apps/server/src/routes/agent/index.ts
**/*.{js,jsx,ts,tsx,css,scss}

📄 CodeRabbit Inference Engine (AGENT.md)

Use Prettier with sort-imports and Tailwind plugins for code formatting

Files:

  • apps/mail/components/ui/recipient-autosuggest.tsx
  • apps/server/src/routes/agent/index.ts
**/*.{ts,tsx}

📄 CodeRabbit Inference Engine (AGENT.md)

Enable TypeScript strict mode

Files:

  • apps/mail/components/ui/recipient-autosuggest.tsx
  • apps/server/src/routes/agent/index.ts
**/*.{css,js,ts,jsx,tsx,mdx}

📄 CodeRabbit Inference Engine (.cursor/rules/tailwind-css-v4.mdc)

**/*.{css,js,ts,jsx,tsx,mdx}: Chain variants together for composable variants (e.g., group-has-data-potato:opacity-100).
Use new variants such as starting, not-*, inert, nth-*, in-*, open (for :popover-open), and ** for all descendants.
Do not use deprecated utilities like bg-opacity-*, text-opacity-*, border-opacity-*, and divide-opacity-*; use the new syntax (e.g., bg-black/50).
Use renamed utilities: shadow-sm is now shadow-xs, shadow is now shadow-sm, drop-shadow-sm is now drop-shadow-xs, drop-shadow is now drop-shadow-sm, blur-sm is now blur-xs, blur is now blur-sm, rounded-sm is now rounded-xs, rounded is now rounded-sm, outline-none is now outline-hidden.
Use bg-(--brand-color) syntax for CSS variables in arbitrary values instead of bg-[--brand-color].
Stacked variants now apply left-to-right instead of right-to-left.

Files:

  • apps/mail/components/ui/recipient-autosuggest.tsx
  • apps/server/src/routes/agent/index.ts
🧠 Learnings (17)
📓 Common learnings
Learnt from: danteissaias
PR: Mail-0/Zero#618
File: apps/mail/components/mail/mail-iframe.tsx:12-12
Timestamp: 2025-04-07T20:46:11.697Z
Learning: In the Mail-0/Zero application, sender emails are guaranteed to be non-empty when passed to components that handle them, making additional empty string validation unnecessary.
Learnt from: retrogtx
PR: Mail-0/Zero#1573
File: apps/mail/components/create/template-button.tsx:197-216
Timestamp: 2025-07-28T05:37:50.566Z
Learning: retrogtx prefers less nitpicky code review suggestions and may dismiss detailed accessibility/best practice recommendations with casual responses like "bro please".
Learnt from: retrogtx
PR: Mail-0/Zero#1468
File: apps/server/src/main.ts:854-858
Timestamp: 2025-08-04T18:33:59.515Z
Learning: retrogtx gets frustrated with contradictory review suggestions and prefers consistent guidance. When previous suggestions conflict with new ones, acknowledge the contradiction and defer to the existing implementation rather than pushing alternative approaches.
📚 Learning: for the "upgrade" link in addconnectiondialog, using a proper element instead of a w...
Learnt from: danteissaias
PR: Mail-0/Zero#902
File: apps/mail/components/connection/add.tsx:77-77
Timestamp: 2025-05-07T16:55:46.513Z
Learning: For the "Upgrade" link in AddConnectionDialog, using a proper <button> element instead of a <span> with onClick is recognized as an accessibility improvement but was deferred as out of scope in PR #902 (CSS variables PR).

Applied to files:

  • apps/mail/components/ui/recipient-autosuggest.tsx
📚 Learning: applies to **/*.{js,jsx,ts,tsx} : semicolons are required at the end of statements...
Learnt from: CR
PR: Mail-0/Zero#0
File: AGENT.md:0-0
Timestamp: 2025-08-03T20:41:43.899Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Semicolons are required at the end of statements

Applied to files:

  • apps/mail/components/ui/recipient-autosuggest.tsx
📚 Learning: applies to **/*.{js,jsx,ts,tsx} : limit lines to 100 characters in length...
Learnt from: CR
PR: Mail-0/Zero#0
File: AGENT.md:0-0
Timestamp: 2025-08-03T20:41:43.899Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Limit lines to 100 characters in length

Applied to files:

  • apps/mail/components/ui/recipient-autosuggest.tsx
📚 Learning: in react hook form, avoid using useeffect for form state synchronization when the values prop can ha...
Learnt from: retrogtx
PR: Mail-0/Zero#1354
File: apps/mail/components/ui/prompts-dialog.tsx:85-88
Timestamp: 2025-06-20T05:03:16.944Z
Learning: In React Hook Form, avoid using useEffect for form state synchronization when the values prop can handle reactive updates automatically. The values prop is specifically designed for this purpose and is more optimal than manual useEffect-based synchronization.

Applied to files:

  • apps/mail/components/ui/recipient-autosuggest.tsx
📚 Learning: on small and medium screens (mobile devices), buttons don't naturally lose focus after being clicked...
Learnt from: Fahad-Dezloper
PR: Mail-0/Zero#1440
File: apps/mail/components/create/ai-chat.tsx:101-113
Timestamp: 2025-06-22T19:23:10.599Z
Learning: On small and medium screens (mobile devices), buttons don't naturally lose focus after being clicked like they do on desktop browsers. This requires manual intervention using setTimeout with additional blur() calls and DOM manipulation to properly clear focus and active states in button click handlers for responsive design.

Applied to files:

  • apps/mail/components/ui/recipient-autosuggest.tsx
📚 Learning: in draft deletion operations, using settimeout with a delay (like 500ms) before showing success toas...
Learnt from: AnjanyKumarJaiswal
PR: Mail-0/Zero#1732
File: apps/mail/components/create/email-composer.tsx:634-657
Timestamp: 2025-07-15T03:31:14.991Z
Learning: In draft deletion operations, using setTimeout with a delay (like 500ms) before showing success toast notifications improves UX by allowing UI state changes (like closing composers and clearing IDs) to complete before displaying the toast, preventing jarring immediate toast appearances that could disappear quickly during interface transitions.

Applied to files:

  • apps/mail/components/ui/recipient-autosuggest.tsx
📚 Learning: in apps/mail/lib/hotkeys/mail-list-hotkeys.tsx, the switchcategorybyindex function using hardcoded i...
Learnt from: retrogtx
PR: Mail-0/Zero#1328
File: apps/mail/lib/hotkeys/mail-list-hotkeys.tsx:202-209
Timestamp: 2025-06-18T17:26:50.918Z
Learning: In apps/mail/lib/hotkeys/mail-list-hotkeys.tsx, the switchCategoryByIndex function using hardcoded indices for category hotkeys does not break when users reorder categories, contrary to the theoretical index-shifting issue. The actual implementation has constraints or mechanisms that prevent hotkey targeting issues.

Applied to files:

  • apps/mail/components/ui/recipient-autosuggest.tsx
  • apps/server/src/routes/agent/index.ts
📚 Learning: applies to **/*.{css,js,ts,jsx,tsx,mdx} : do not use deprecated utilities like `bg-opacity-*`, `text...
Learnt from: CR
PR: Mail-0/Zero#0
File: .cursor/rules/tailwind-css-v4.mdc:0-0
Timestamp: 2025-08-03T20:42:04.207Z
Learning: Applies to **/*.{css,js,ts,jsx,tsx,mdx} : Do not use deprecated utilities like `bg-opacity-*`, `text-opacity-*`, `border-opacity-*`, and `divide-opacity-*`; use the new syntax (e.g., `bg-black/50`).

Applied to files:

  • apps/mail/components/ui/recipient-autosuggest.tsx
📚 Learning: applies to **/*.{js,jsx,ts,tsx} : use 2-space indentation...
Learnt from: CR
PR: Mail-0/Zero#0
File: AGENT.md:0-0
Timestamp: 2025-08-03T20:41:43.899Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Use 2-space indentation

Applied to files:

  • apps/mail/components/ui/recipient-autosuggest.tsx
📚 Learning: in the mail-0/zero application, sender emails are guaranteed to be non-empty when passed to componen...
Learnt from: danteissaias
PR: Mail-0/Zero#618
File: apps/mail/components/mail/mail-iframe.tsx:12-12
Timestamp: 2025-04-07T20:46:11.697Z
Learning: In the Mail-0/Zero application, sender emails are guaranteed to be non-empty when passed to components that handle them, making additional empty string validation unnecessary.

Applied to files:

  • apps/mail/components/ui/recipient-autosuggest.tsx
📚 Learning: during testing phases, debug logging should be kept active in apps/server/src/lib/email-verification...
Learnt from: retrogtx
PR: Mail-0/Zero#1622
File: apps/server/src/lib/email-verification.ts:189-189
Timestamp: 2025-07-05T05:27:24.623Z
Learning: During testing phases, debug logging should be kept active in apps/server/src/lib/email-verification.ts for BIMI validation and email verification debugging, even if it's verbose.

Applied to files:

  • apps/mail/components/ui/recipient-autosuggest.tsx
📚 Learning: in apps/server/src/trpc/routes/mail.ts, the attachment processing logic conditionally handles mixed ...
Learnt from: retrogtx
PR: Mail-0/Zero#1468
File: apps/server/src/trpc/routes/mail.ts:386-391
Timestamp: 2025-06-27T04:59:29.731Z
Learning: In apps/server/src/trpc/routes/mail.ts, the attachment processing logic conditionally handles mixed attachment types - it preserves existing File-like objects with arrayBuffer methods while only converting serialized attachments that need processing through toAttachmentFiles.

Applied to files:

  • apps/mail/components/ui/recipient-autosuggest.tsx
  • apps/server/src/routes/agent/index.ts
📚 Learning: in apps/server/src/lib/driver/google.ts, the normalization of "draft" to "drafts" in the count() met...
Learnt from: retrogtx
PR: Mail-0/Zero#1734
File: apps/server/src/lib/driver/google.ts:211-221
Timestamp: 2025-07-15T06:46:33.349Z
Learning: In apps/server/src/lib/driver/google.ts, the normalization of "draft" to "drafts" in the count() method is necessary because the navigation item in apps/mail/config/navigation.ts has id: 'drafts' (plural) while the Google API returns "draft" (singular). The nav-main.tsx component matches stats by comparing stat.label with item.id, so the backend must return "drafts" for the draft counter badge to appear in the sidebar.

Applied to files:

  • apps/server/src/routes/agent/index.ts
📚 Learning: retrogtx prefers less nitpicky code review suggestions and may dismiss detailed accessibility/best p...
Learnt from: retrogtx
PR: Mail-0/Zero#1573
File: apps/mail/components/create/template-button.tsx:197-216
Timestamp: 2025-07-28T05:37:50.566Z
Learning: retrogtx prefers less nitpicky code review suggestions and may dismiss detailed accessibility/best practice recommendations with casual responses like "bro please".

Applied to files:

  • apps/server/src/routes/agent/index.ts
📚 Learning: retrogtx gets frustrated with contradictory review suggestions and prefers consistent guidance. when...
Learnt from: retrogtx
PR: Mail-0/Zero#1468
File: apps/server/src/main.ts:854-858
Timestamp: 2025-08-04T18:33:59.515Z
Learning: retrogtx gets frustrated with contradictory review suggestions and prefers consistent guidance. When previous suggestions conflict with new ones, acknowledge the contradiction and defer to the existing implementation rather than pushing alternative approaches.

Applied to files:

  • apps/server/src/routes/agent/index.ts
📚 Learning: in apps/server/src/trpc/routes/mail.ts, the user indicated they are not using iso format for the sch...
Learnt from: retrogtx
PR: Mail-0/Zero#1468
File: apps/server/src/trpc/routes/mail.ts:331-331
Timestamp: 2025-06-28T03:56:09.376Z
Learning: In apps/server/src/trpc/routes/mail.ts, the user indicated they are not using ISO format for the scheduleAt parameter, despite the frontend code showing toISOString() usage in the ScheduleSendPicker component.

Applied to files:

  • apps/server/src/routes/agent/index.ts
🧬 Code Graph Analysis (1)
apps/server/src/routes/agent/index.ts (4)
apps/server/src/env.ts (1)
  • env (93-93)
apps/server/src/types.ts (1)
  • IOutgoingMessage (193-211)
apps/server/src/routes/agent/db/schema.ts (1)
  • threads (5-22)
apps/server/src/lib/utils.ts (1)
  • c (13-23)
🪛 Biome (2.1.2)
apps/mail/components/ui/recipient-autosuggest.tsx

[error] 269-269: The elements with this role can be changed to the following elements:
For examples and more information, see WAI-ARIA Roles (lint/a11y/useSemanticElements)

@jazzberry-ai
Copy link

jazzberry-ai bot commented Aug 6, 2025

Bug Report

Name Severity Example test case Description
Simplified Malformed Sender Parsing Medium "Name <test@example.com>" The parseMalformedSender function in apps/server/src/routes/agent/index.ts has been simplified to only extract the email address using a basic regex. This change removes the more complex fallback parsing logic that attempted to extract the name from malformed sender strings. While this change reduces the chance of runtime errors due to incorrect regex, it might result in a loss of functionality where the contact name is not correctly extracted from malformed sender strings, leading to a less informative recipient suggestion in the UI. In cases when the email follows a simple pattern, such as Name test@example.com, the name part is ignored.
Logic error in shouldLoop High Check if THREAD_SYNC_LOOP is false The constant shouldLoop is assigned to env.THREAD_SYNC_LOOP !== 'true'. If the intention of THREAD_SYNC_LOOP is to set the value of shouldLoop to true, when it is true, there is a logic error and we need to check the usages of shouldLoop. If THREAD_SYNC_LOOP is true, then shouldLoop is false which is opposite to the intended logic.

Comments? Email us.

@github-actions
Copy link
Contributor

github-actions bot commented Aug 7, 2025

This PR has merge conflicts and has been open for more than 3 days. It will be automatically closed. Please resolve the conflicts and reopen the PR if you'd like to continue working on it.

@github-actions github-actions bot closed this Aug 7, 2025
@retrogtx retrogtx reopened this Aug 7, 2025
@jazzberry-ai
Copy link

jazzberry-ai bot commented Aug 7, 2025

Bug Report

Name Severity Example test case Description
Potential Regular Expression Denial of Service (ReDoS) in parseMalformedSender Medium Create a thread with a latest_sender field containing a malformed string with a very long name, designed to trigger backtracking in the regular expression. For example: name: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA. Then, trigger the recipient autosuggest feature. The regular expressions used in the parseMalformedSender function are vulnerable to ReDoS. A specially crafted input string can cause the regular expression engine to backtrack excessively, leading to a significant performance degradation or even a denial of service. The complex parsing logic attempts to be resilient against different name formats, but this introduces the risk of pathological inputs.

Comments? Email us.

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

Your free trial has ended. If you'd like to continue receiving code reviews, you can add a payment method here.

@github-actions
Copy link
Contributor

github-actions bot commented Aug 7, 2025

This PR has merge conflicts and has been open for more than 3 days. It will be automatically closed. Please resolve the conflicts and reopen the PR if you'd like to continue working on it.

@github-actions github-actions bot closed this Aug 7, 2025
@retrogtx retrogtx reopened this Aug 7, 2025
@jazzberry-ai
Copy link

jazzberry-ai bot commented Aug 7, 2025

Bug Report

Name Severity Example test case Description
ReDoS in parseMalformedSender High A long string without '<' characters followed by whitespace, '<', and '>'. Example: '"A" * 5000 + " email@example.com"' The parseMalformedSender function uses a regex that is vulnerable to ReDoS. A malicious actor could inject crafted email data into the threads table, leading to excessive CPU consumption and potentially causing a denial of service.

Comments? Email us.

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

Your free trial has ended. If you'd like to continue receiving code reviews, you can add a payment method here.

@jazzberry-ai
Copy link

jazzberry-ai bot commented Aug 7, 2025

Bug Report

Name Severity Example test case Description
Missing Cache Invalidation in sendDraft High Create a draft, add a new recipient, and send the draft. The recipient suggestion isn't updated after sending a draft.

Comments? Email us.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (2)
apps/server/src/routes/agent/index.ts (2)

338-377: These console.warns need to be behind a debug flag - we're not debugging in production at Tesla! 🔧

Both console.warn statements should only fire when DEBUG mode is enabled. Otherwise we're spamming logs like a broken Starlink satellite.

-      console.warn('[SuggestRecipients] Used fallback parsing for plain email:', email);
+      if (this.env.DEBUG) console.warn('[SuggestRecipients] Used fallback parsing for plain email:', email);
-    console.warn('[SuggestRecipients] Extracted from malformed data:', { email, name });
+    if (this.env.DEBUG) console.warn('[SuggestRecipients] Extracted from malformed data:', { email, name });

1575-1659: Houston, we've achieved orbit! But those console.errors need to chill. 🚀

The LIMIT 100 and hash-based cache invalidation show serious engineering prowess - way better than fetching the entire database! The performance is now closer to a Plaid Model S than a golf cart.

However, those console.error statements at lines 1606 and 1612 should be conditional:

-            console.error('[SuggestRecipients] Failed to parse latest_sender, no fallback possible. Raw data:', row.latest_sender);
+            if (this.env.DEBUG) console.error('[SuggestRecipients] Failed to parse latest_sender, no fallback possible. Raw data:', row.latest_sender);
-            console.error('[SuggestRecipients] Failed to parse latest_sender, no fallback possible:', error, 'Raw data:', row.latest_sender);
+            if (this.env.DEBUG) console.error('[SuggestRecipients] Failed to parse latest_sender, no fallback possible:', error, 'Raw data:', row.latest_sender);

Remember to add that database index on latest_received_on DESC as discussed - it'll make this query go from Prius to Roadster speeds!

📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 56c0506 and 96fb1b0.

📒 Files selected for processing (2)
  • apps/server/src/routes/agent/index.ts (6 hunks)
  • apps/server/src/trpc/routes/mail.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit Inference Engine (AGENT.md)

**/*.{js,jsx,ts,tsx}: Use 2-space indentation
Use single quotes for strings
Limit lines to 100 characters in length
Semicolons are required at the end of statements

Files:

  • apps/server/src/trpc/routes/mail.ts
  • apps/server/src/routes/agent/index.ts
**/*.{js,jsx,ts,tsx,css,scss}

📄 CodeRabbit Inference Engine (AGENT.md)

Use Prettier with sort-imports and Tailwind plugins for code formatting

Files:

  • apps/server/src/trpc/routes/mail.ts
  • apps/server/src/routes/agent/index.ts
**/*.{ts,tsx}

📄 CodeRabbit Inference Engine (AGENT.md)

Enable TypeScript strict mode

Files:

  • apps/server/src/trpc/routes/mail.ts
  • apps/server/src/routes/agent/index.ts
**/*.{css,js,ts,jsx,tsx,mdx}

📄 CodeRabbit Inference Engine (.cursor/rules/tailwind-css-v4.mdc)

**/*.{css,js,ts,jsx,tsx,mdx}: Chain variants together for composable variants (e.g., group-has-data-potato:opacity-100).
Use new variants such as starting, not-*, inert, nth-*, in-*, open (for :popover-open), and ** for all descendants.
Do not use deprecated utilities like bg-opacity-*, text-opacity-*, border-opacity-*, and divide-opacity-*; use the new syntax (e.g., bg-black/50).
Use renamed utilities: shadow-sm is now shadow-xs, shadow is now shadow-sm, drop-shadow-sm is now drop-shadow-xs, drop-shadow is now drop-shadow-sm, blur-sm is now blur-xs, blur is now blur-sm, rounded-sm is now rounded-xs, rounded is now rounded-sm, outline-none is now outline-hidden.
Use bg-(--brand-color) syntax for CSS variables in arbitrary values instead of bg-[--brand-color].
Stacked variants now apply left-to-right instead of right-to-left.

Files:

  • apps/server/src/trpc/routes/mail.ts
  • apps/server/src/routes/agent/index.ts
🧠 Learnings (8)
📓 Common learnings
Learnt from: danteissaias
PR: Mail-0/Zero#618
File: apps/mail/components/mail/mail-iframe.tsx:12-12
Timestamp: 2025-04-07T20:46:11.697Z
Learning: In the Mail-0/Zero application, sender emails are guaranteed to be non-empty when passed to components that handle them, making additional empty string validation unnecessary.
Learnt from: retrogtx
PR: Mail-0/Zero#1573
File: apps/mail/components/create/template-button.tsx:197-216
Timestamp: 2025-07-28T05:37:50.566Z
Learning: retrogtx prefers less nitpicky code review suggestions and may dismiss detailed accessibility/best practice recommendations with casual responses like "bro please".
Learnt from: retrogtx
PR: Mail-0/Zero#1468
File: apps/server/src/main.ts:854-858
Timestamp: 2025-08-04T18:33:59.515Z
Learning: retrogtx gets frustrated with contradictory review suggestions and prefers consistent guidance. When previous suggestions conflict with new ones, acknowledge the contradiction and defer to the existing implementation rather than pushing alternative approaches.
📚 Learning: in apps/server/src/trpc/routes/mail.ts, the attachment processing logic conditionally handles mixed ...
Learnt from: retrogtx
PR: Mail-0/Zero#1468
File: apps/server/src/trpc/routes/mail.ts:386-391
Timestamp: 2025-06-27T04:59:29.731Z
Learning: In apps/server/src/trpc/routes/mail.ts, the attachment processing logic conditionally handles mixed attachment types - it preserves existing File-like objects with arrayBuffer methods while only converting serialized attachments that need processing through toAttachmentFiles.

Applied to files:

  • apps/server/src/trpc/routes/mail.ts
  • apps/server/src/routes/agent/index.ts
📚 Learning: in apps/server/src/trpc/routes/mail.ts, the user indicated they are not using iso format for the sch...
Learnt from: retrogtx
PR: Mail-0/Zero#1468
File: apps/server/src/trpc/routes/mail.ts:331-331
Timestamp: 2025-06-28T03:56:09.376Z
Learning: In apps/server/src/trpc/routes/mail.ts, the user indicated they are not using ISO format for the scheduleAt parameter, despite the frontend code showing toISOString() usage in the ScheduleSendPicker component.

Applied to files:

  • apps/server/src/trpc/routes/mail.ts
  • apps/server/src/routes/agent/index.ts
📚 Learning: in apps/server/src/lib/driver/google.ts, the normalization of "draft" to "drafts" in the count() met...
Learnt from: retrogtx
PR: Mail-0/Zero#1734
File: apps/server/src/lib/driver/google.ts:211-221
Timestamp: 2025-07-15T06:46:33.349Z
Learning: In apps/server/src/lib/driver/google.ts, the normalization of "draft" to "drafts" in the count() method is necessary because the navigation item in apps/mail/config/navigation.ts has id: 'drafts' (plural) while the Google API returns "draft" (singular). The nav-main.tsx component matches stats by comparing stat.label with item.id, so the backend must return "drafts" for the draft counter badge to appear in the sidebar.

Applied to files:

  • apps/server/src/routes/agent/index.ts
📚 Learning: retrogtx prefers less nitpicky code review suggestions and may dismiss detailed accessibility/best p...
Learnt from: retrogtx
PR: Mail-0/Zero#1573
File: apps/mail/components/create/template-button.tsx:197-216
Timestamp: 2025-07-28T05:37:50.566Z
Learning: retrogtx prefers less nitpicky code review suggestions and may dismiss detailed accessibility/best practice recommendations with casual responses like "bro please".

Applied to files:

  • apps/server/src/routes/agent/index.ts
📚 Learning: retrogtx gets frustrated with contradictory review suggestions and prefers consistent guidance. when...
Learnt from: retrogtx
PR: Mail-0/Zero#1468
File: apps/server/src/main.ts:854-858
Timestamp: 2025-08-04T18:33:59.515Z
Learning: retrogtx gets frustrated with contradictory review suggestions and prefers consistent guidance. When previous suggestions conflict with new ones, acknowledge the contradiction and defer to the existing implementation rather than pushing alternative approaches.

Applied to files:

  • apps/server/src/routes/agent/index.ts
📚 Learning: in apps/mail/lib/hotkeys/mail-list-hotkeys.tsx, the switchcategorybyindex function using hardcoded i...
Learnt from: retrogtx
PR: Mail-0/Zero#1328
File: apps/mail/lib/hotkeys/mail-list-hotkeys.tsx:202-209
Timestamp: 2025-06-18T17:26:50.918Z
Learning: In apps/mail/lib/hotkeys/mail-list-hotkeys.tsx, the switchCategoryByIndex function using hardcoded indices for category hotkeys does not break when users reorder categories, contrary to the theoretical index-shifting issue. The actual implementation has constraints or mechanisms that prevent hotkey targeting issues.

Applied to files:

  • apps/server/src/routes/agent/index.ts
📚 Learning: during testing phases, debug logging should be kept active in apps/server/src/lib/email-verification...
Learnt from: retrogtx
PR: Mail-0/Zero#1622
File: apps/server/src/lib/email-verification.ts:189-189
Timestamp: 2025-07-05T05:27:24.623Z
Learning: During testing phases, debug logging should be kept active in apps/server/src/lib/email-verification.ts for BIMI validation and email verification debugging, even if it's verbose.

Applied to files:

  • apps/server/src/routes/agent/index.ts
🔇 Additional comments (6)
apps/server/src/trpc/routes/mail.ts (1)

43-56: Clean implementation! This is the way. 🚀

The TRPC endpoint is beautifully simple - just passing through to the agent. No over-engineering, no unnecessary complexity. Exactly how a good API wrapper should be.

apps/server/src/routes/agent/index.ts (5)

332-336: Smart caching strategy! Like SpaceX reusing rockets. 🚀

The recipient cache structure with frequency and recency tracking is solid. Simple invalidation beats complex cache management any day.


653-668: Perfect cache invalidation timing! ⚡

Invalidating after successful send/create operations ensures the cache reflects reality. This is how we maintain data integrity at scale.


939-946: Deletion done right! Clean as a Cybertruck. 🗑️

Good job using 'trash' consistently with the normalizeFolderName method. Cache invalidation and broadcast are properly sequenced.


1028-1031: Cache invalidation in syncThread - precision timing! ⚡

Invalidating after DB update ensures consistency. This is engineering excellence.


1568-1573: Simple wrapper - no over-engineering! Perfect. ✨

Sometimes the simplest solution is the best solution. This is how we build rockets that actually work.

Copy link
Collaborator

MrgSub commented Aug 9, 2025

Merge activity

  • Aug 9, 7:33 PM UTC: A user started a stack merge that includes this pull request via Graphite.
  • Aug 9, 7:33 PM UTC: Graphite couldn't merge this PR because it failed for an unknown reason (Stack merges are not currently supported for forked repositories. Please create a branch in the target repository in order to merge).

@MrgSub MrgSub merged commit 2e2474d into Mail-0:staging Aug 10, 2025
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

content design Improvements & changes to design & UX High Priority High Priority Work

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants