Skip to content

Conversation

jlokos
Copy link
Contributor

@jlokos jlokos commented Apr 15, 2025

feat: add CC/BCC support to mailto handler and email composer

Description

This PR adds proper handling of CC and BCC fields in mailto links to the 0.email. When users click on mailto links that include CC or BCC parameters, these values are now correctly parsed, validated, and displayed in the email composer.

Key improvements:

  • Parsing CC and BCC values from mailto URLs
  • Adding CC and BCC headers to MIME messages when creating drafts
  • Extracting CC and BCC values from draft headers
  • Validating and sanitizing email addresses to prevent API errors
  • Updating UI to display CC and BCC fields when values are present

This enhancement builds upon the existing mailto protocol handler support from PR #574, completing the full implementation of the mailto URL standard.


Type of Change

  • ✨ New feature (non-breaking change which adds functionality)
  • 🎨 UI/UX improvement

Areas Affected

  • Email Integration (Gmail, IMAP, etc.)
  • User Interface/Experience
  • API Endpoints

Testing Done

  • Manual testing performed
  • Cross-browser testing (if UI changes)

I've tested this implementation with various mailto link formats including:

Security Considerations

  • No sensitive data is exposed
  • Input validation is implemented

The implementation includes robust validation and sanitization of email addresses to prevent security issues and API errors. Email addresses are validated using regex patterns, and all invalid addresses are filtered out before being sent to the Gmail API.

Checklist

  • I have read the CONTRIBUTING document
  • My code follows the project's style guidelines
  • I have performed a self-review of my code
  • I have commented my code, particularly in complex areas
  • My changes generate no new warnings

Additional Notes

The implementation addresses a specific issue where email addresses with spaces or special characters in CC/BCC fields would cause API errors. The solution includes:

  1. Adding email validation and sanitization in the Google driver
  2. Improving the mailto URL parser to handle special characters
  3. Ensuring the UI correctly displays CC/BCC fields when values are present

By submitting this pull request, I confirm that my contribution is made under the terms of the project's license.

Summary by CodeRabbit

  • New Features

    • Added support for CC and BCC fields when composing, saving, and sending emails.
    • Mailto links now support CC and BCC parameters in addition to To, Subject, and Body.
  • Bug Fixes

    • Improved email address validation and sanitization for all recipient fields.
    • Enhanced mailto URL parsing for better reliability and error handling.
  • Refactor

    • Unified CC and BCC handling in the compose email interface for a more streamlined experience.
    • Updated protocol handler and redirect routes to use a consistent /mail/create path.

Copy link

vercel bot commented Apr 15, 2025

@jlokos is attempting to deploy a commit to the Zero Team on Vercel.

A member of the Team first needs to authorize it.

Copy link
Contributor

coderabbitai bot commented Apr 15, 2025

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

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

This change removes the /mail/compose page and migrates mailto handling and email composition to the /mail/create route. It enhances mailto parsing to support CC and BCC fields, updates the Google draft driver to handle CC/BCC recipients, and refactors the email creation component to unify CC/BCC handling in its state and workflow. The mailto protocol handler registration and all related redirects are updated to use the new /mail/create endpoints. Type definitions and draft parsing/creation logic are updated to support the new fields and error handling.

Changes

Files/Paths Change Summary
apps/mail/app/(routes)/mail/compose/page.tsx Removed the compose page component and its related interface and logic.
apps/mail/app/api/driver/google.ts Extended draft parsing and creation to support cc and bcc fields; added email sanitization and error handling; updated ParsedDraft interface.
apps/mail/components/create/create-email.tsx Refactored CreateEmail to unify CC/BCC handling in state; added initial props for CC/BCC; updated draft loading, saving, sending, and form reset logic to include CC/BCC; UI and validation changes.
apps/mail/components/mail/use-mail.ts Added showCc and showBcc properties to the Config type and initial state.
apps/mail/app/(routes)/mail/create/handle-mailto/route.ts Refactored mailto parsing for CC/BCC support; updated draft creation and all redirects to use /mail/create; improved parsing robustness and error handling.
apps/mail/components/mail/mail.tsx Updated mailto protocol handler registration to use /mail/create/handle-mailto route.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant Browser
    participant MailApp
    participant GoogleAPI

    User->>Browser: Clicks mailto link
    Browser->>MailApp: Navigates to /mail/create/handle-mailto?mailto=...
    MailApp->>MailApp: Parses mailto (to, subject, body, cc, bcc)
    MailApp->>GoogleAPI: Creates draft with all fields
    GoogleAPI-->>MailApp: Returns draft ID
    MailApp->>Browser: Redirects to /mail/create?draftId=...
    Browser->>MailApp: Loads /mail/create with draft
    MailApp->>User: Renders CreateEmail with prefilled fields
Loading

Possibly related PRs

Suggested labels

design

Suggested reviewers

  • MrgSub

Poem

A bunny hops from compose to create,
With CC and BCC, now drafts are first-rate!
Mailto links parsed with a clever new way,
All fields in one hop—hip hip, hooray!
Compose is retired, but don’t be forlorn,
For a unified inbox is now freshly born.
🐰✉️


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.
    • Generate unit testing code for this file.
    • 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 generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • 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 generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

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 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.

@jlokos jlokos marked this pull request as ready for review April 15, 2025 20:33
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: 0

🧹 Nitpick comments (5)
apps/mail/components/create/create-email.tsx (3)

120-147: useEffect to auto-show CC/BCC if initial values exist.
The logic is correct, but note that you also set CC/BCC visibility in another effect (lines 501+). Consider unifying them to minimize repetitive state updates.


501-555: Additional effect setting CC/BCC states.
Similar to lines 120–147. Consider merging these to reduce duplication.


917-930: Plus button for file attachments.
This is a creative, minimal UI for adding attachments. For improved accessibility, consider adding an aria-label to the button or referencing the file input’s label.

apps/mail/app/(routes)/mail/compose/handle-mailto/route.ts (2)

14-24: Use optional chaining for regex matches.

The code can be simplified using optional chaining as suggested by the static analysis.

- const emailMatch = mailtoUrl.match(/^mailto:([^?]+)/);
- if (emailMatch && emailMatch[1]) {
+ const emailMatch = mailtoUrl.match(/^mailto:([^?]+)/);
+ if (emailMatch?.[1]) {
🧰 Tools
🪛 Biome (1.9.4)

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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


26-36: Use optional chaining for regex matches here too.

Similar to the previous comment, optional chaining would improve readability.

- const queryParamsMatch = mailtoUrl.match(/\?(.+)$/);
- if (queryParamsMatch && queryParamsMatch[1]) {
+ const queryParamsMatch = mailtoUrl.match(/\?(.+)$/);
+ if (queryParamsMatch?.[1]) {
🧰 Tools
🪛 Biome (1.9.4)

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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between fbbc13c and bb8ed18.

📒 Files selected for processing (5)
  • apps/mail/app/(routes)/mail/compose/handle-mailto/route.ts (4 hunks)
  • apps/mail/app/(routes)/mail/compose/page.tsx (2 hunks)
  • apps/mail/app/api/driver/google.ts (5 hunks)
  • apps/mail/components/create/create-email.tsx (17 hunks)
  • apps/mail/components/mail/use-mail.ts (2 hunks)
🧰 Additional context used
🪛 Biome (1.9.4)
apps/mail/app/(routes)/mail/compose/handle-mailto/route.ts

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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

🔇 Additional comments (27)
apps/mail/components/mail/use-mail.ts (2)

12-13: New boolean fields align well with CC/BCC toggling.
Defining showCc and showBcc for visibility flags is consistent with the rest of the code and appears straightforward.


23-24: Default initialization is appropriate.
Initializing both showCc and showBcc to false in the atom state is a clear design choice—no issues found.

apps/mail/app/(routes)/mail/compose/page.tsx (4)

3-4: Imports look properly structured.
No issues with importing headers from next/headers and auth from @/lib/auth.


13-14: Optional CC/BCC support added to query params.
Defining cc?: string; and bcc?: string; ensures consistent typed usage everywhere.


40-46: Properly passing CC/BCC to the create-email component.
Providing initialCc and initialBcc aligns well with the extended functionality for multiple recipients.


50-50: No functional changes to review.
Line 50 is simply a closing brace; skipping.

apps/mail/components/create/create-email.tsx (9)

1-1: New imports introduced for CC/BCC and attachment UI.
These imports (e.g., Popover, PopoverContent, useMail, etc.) are relevant to the new CC/BCC and attachments functionality. No concerns on usage.

Also applies to: 3-4, 9-10, 17-18, 26-26


58-59: New props for CC/BCC.
Adding initialCc and initialBcc props is a clear and flexible approach to pass prefilled recipients.

Also applies to: 64-65


70-77: State management for CC/BCC recipients.
Converting the comma-delimited strings into arrays and storing them in ccEmails/bccEmails works well.


166-170: Loading and processing CC/BCC from draft.
Splitting comma-delimited addresses and filtering out empty entries is straightforward.


180-185: Single mail state update for CC/BCC visibility.
Bundling showCc and showBcc updates into a single call is efficient.


216-232: Utility function to process draft emails.
processDraftEmails gracefully handles arrays and raw strings, ensuring consistent email lists.


365-388: Form reset now includes CC/BCC.
Clearing all CC/BCC inputs and flags is essential for a complete reset.


423-451: Including CC/BCC in the final email object.
Conditionally adding CC/BCC preserves backwards compatibility and is suitably guarded by mail.showCc/mail.showBcc.


901-901: Truncating attachment filenames.
truncateFileName(file.name, 20) is a neat approach to preserve UI readability. No issues found.

apps/mail/app/(routes)/mail/compose/handle-mailto/route.ts (6)

5-9: Good addition of email validation function.

The isValidEmail function provides a clean, reusable way to validate email addresses using regex. This helps maintain consistent validation throughout the mailto handling flow.


51-61: Good implementation of CC/BCC decoding.

The implementation uses the same error handling pattern as the existing code for subject and body, providing consistent handling of URL-encoded parameters.


68-70: Good validation and logging before returning parsed data.

The function now properly validates email addresses and logs the complete parsed data including CC and BCC fields before returning.


80-80: Updated function signature to support CC/BCC fields.

The createDraftFromMailto function signature now correctly accepts the additional CC and BCC fields that were parsed from the mailto URL.


103-106: Added CC/BCC fields to draft data object.

The draft data object now properly includes the CC and BCC fields, ensuring they're passed to the draft creation process.


111-112: Enhanced logging for draft creation.

Added more detailed logging of the draft creation result, which will help with debugging.

apps/mail/app/api/driver/google.ts (6)

42-43: Added CC/BCC fields to ParsedDraft interface.

The interface now properly supports the CC and BCC fields needed for the feature implementation.


54-66: Well-implemented helper function for email extraction.

The getEmails helper function efficiently extracts and processes email addresses from headers, reducing code duplication for To, CC, and BCC fields.


85-86: Added CC/BCC fields to returned parsed draft object.

The parsed draft object now correctly includes the CC and BCC fields extracted from the headers.


786-798: Good implementation of email sanitization.

The sanitizeEmails helper function properly:

  1. Handles empty or whitespace-only input
  2. Splits by commas to handle multiple addresses
  3. Trims whitespace from each address
  4. Validates using regex to ensure only valid addresses are included
  5. Re-joins with proper formatting

This improves the robustness of the CC/BCC handling.


801-823: Well-structured dynamic header construction.

The code now builds email headers dynamically based on the presence of sanitized To, CC, and BCC fields. This approach is more maintainable than the previous implementation and handles optional fields appropriately.


838-855: Good error handling for draft operations.

The try-catch block for draft creation/updating properly logs errors and rethrows them, improving error visibility during debugging while still allowing callers to handle failures.

@nizzyabi
Copy link
Collaborator

looks good, thoughts @MrgSub

Copy link
Contributor

coderabbitai bot commented Apr 15, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@jlokos
Copy link
Contributor Author

jlokos commented Apr 15, 2025

@coderabbitai full review

Copy link
Contributor

coderabbitai bot commented Apr 15, 2025

✅ Actions performed

Full review triggered.

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

🧹 Nitpick comments (3)
apps/mail/app/(routes)/mail/compose/handle-mailto/route.ts (1)

6-9: Email validation function implementation

The email validation uses a simple regex pattern that handles common email formats. While this will work for most cases, consider enhancing it to handle more complex valid email formats according to RFC 5322.

-const isValidEmail = (email: string): boolean => {
-  const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
-  return emailRegex.test(email);
+const isValidEmail = (email: string): boolean => {
+  // More comprehensive regex that handles more edge cases
+  const emailRegex = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
+  return emailRegex.test(email);
+};
apps/mail/components/create/create-email.tsx (2)

10-10: Remove unused import to keep code clean.

It appears that the useMail hook is imported but never used within this file. Unused imports may confuse future maintainers, so removing them helps keep the codebase tidy.

Apply this diff to remove the unused import:

- import { useMail } from '@/components/mail/use-mail';

183-199: Consider validating emails during draft parsing.

processDraftEmails splits addresses but does not check for invalid or incomplete emails (e.g., using isValidEmail). If partial/invalid addresses are undesired in the UI, consider adding validation or filtering them out here.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 4446d65 and b7a7da4.

📒 Files selected for processing (5)
  • apps/mail/app/(routes)/mail/compose/handle-mailto/route.ts (4 hunks)
  • apps/mail/app/(routes)/mail/compose/page.tsx (2 hunks)
  • apps/mail/app/api/driver/google.ts (5 hunks)
  • apps/mail/components/create/create-email.tsx (17 hunks)
  • apps/mail/components/mail/use-mail.ts (2 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
apps/mail/components/create/create-email.tsx (4)
apps/mail/actions/send.ts (1)
  • sendEmail (7-58)
apps/mail/lib/utils.ts (1)
  • truncateFileName (116-123)
apps/mail/components/ui/input.tsx (1)
  • Input (31-31)
apps/mail/components/ui/button.tsx (1)
  • Button (55-55)
🔇 Additional comments (30)
apps/mail/components/mail/use-mail.ts (2)

12-13: State added for CC/BCC UI controls

The addition of showCc and showBcc flags to the Config type properly establishes state controls for toggling visibility of these fields in the compose UI. This change supports the broader implementation of CC/BCC support throughout the mail composition flow.


23-24: Default visibility states correctly initialized

Good job initializing both CC and BCC visibility flags to false by default, ensuring they start hidden until explicitly toggled by the user. This matches common email client patterns.

apps/mail/app/(routes)/mail/compose/page.tsx (3)

3-4: Appropriate imports added

Added imports for Next.js headers and authentication support which are necessary for the updated compose page functionality.


13-14: Interface extended for CC/BCC params

Good job extending the ComposePageProps interface to include optional cc and bcc query parameters, maintaining proper typing throughout the application.


40-46: Component props updated to include CC/BCC values

The CreateEmail component now receives initialCc and initialBcc props, completing the flow from URL parameters to component state. This ensures consistent handling of CC/BCC fields throughout the email composition lifecycle.

apps/mail/app/(routes)/mail/compose/handle-mailto/route.ts (4)

21-25: Improved mailto URL parsing

The switch to regex-based parsing for the email address is a good approach, making the code more robust against malformed URLs. The decoding of the extracted email address is also handled correctly.


27-65: Enhanced query parameter handling

Good implementation of robust parameter extraction with individual try-catch blocks for each field. This ensures that if one parameter fails to decode properly, the others can still be processed successfully.


68-70: Email validation before returning

Good practice to validate the email address before returning the parsed data, ensuring that only valid mailtos are processed.


80-106: Updated draft creation with CC and BCC

The createDraftFromMailto function correctly passes CC and BCC values to the draft creation API. The inclusion of additional logging is also helpful for debugging.

apps/mail/app/api/driver/google.ts (6)

42-43: Extended ParsedDraft interface

Adding CC and BCC fields to the ParsedDraft interface ensures type safety throughout the application. Good practice to make these optional arrays of strings.


54-66: Helper function for header extraction

The getEmails helper function is a clean abstraction that properly extracts email addresses from various header types. This eliminates code duplication and standardizes the extraction logic.


85-86: Updated return values with CC/BCC fields

Good job ensuring the parsed draft object includes the extracted CC and BCC fields, maintaining consistency with the interface extension.


793-806: Robust email sanitization function

The sanitizeEmails function properly handles validation and sanitization of email addresses, preventing invalid emails from being passed to the API. This will help avoid API errors when handling addresses with spaces or special characters.

One suggestion: Consider adding a log message when an invalid email is filtered out to aid debugging.

const sanitizeEmails = (emailStr: string): string => {
  if (!emailStr || !emailStr.trim()) return '';
  
  return emailStr
    .split(',')
    .map(email => email.trim())
    .filter(email => {
      // Basic email validation
      const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
+     const isValid = emailRegex.test(email);
+     if (!isValid && email.trim() !== '') {
+       console.log(`Filtering out invalid email: ${email}`);
+     }
+     return isValid;
-     return emailRegex.test(email);
    })
    .join(', ');
};

808-830: Proper MIME header construction

The implementation correctly builds email headers including sanitized CC and BCC fields. This follows email standards and ensures that invalid addresses are filtered out before sending.


846-863: Enhanced error handling

The improved try-catch block properly handles both draft creation and update scenarios with appropriate error logging. This makes debugging and error tracing much easier.

apps/mail/components/create/create-email.tsx (15)

59-60: New props for CC and BCC are clearly integrated.

The new initialCc and initialBcc props align well with the existing pattern for initializing fields. Good job!


65-66: Type definitions look correct.

The optional initialCc and initialBcc fields are consistent with the rest of the component’s API.


74-74: Good approach to unify CC/BCC visibility in a single state object.

Maintaining both showCc and showBcc under one object can simplify state updates and reduce duplication.


285-288: Draft data structure looks consistent.

The inclusion of cc and bcc fields in the draft object ties in well with mail.showCc and mail.showBcc. This should facilitate a unified approach to saving drafts.


308-322: Dependencies for the saveDraft callback are accurate.

All relevant state variables and setters are included, preventing stale closures and ensuring the function reacts correctly to changes.


338-361: Reset function is well-structured.

It clears all relevant form states, ensuring the component can easily start fresh. This is helpful for after-send or new-draft scenarios.


377-394: Local input checks enhance user experience.

Validating to, subject, and messageContent before calling sendEmail prevents unnecessary API calls and gives immediate feedback to users.


399-414: Conditional CC/BCC handling is seamless.

The conditional inclusion of CC/BCC arrays ensures the sendEmail action receives only relevant information.


415-421: Toast notifications provide clarity.

Notifying users of success or failure gives appropriate feedback, and calling resetEmailForm after sending is a clean finishing touch.


638-646: Using requestAnimationFrame for focusing is clever.

This prevents race conditions with DOM updates when toggling CC visibility. No issues here.


658-668: BCC toggle logic mirrors CC.

Maintaining symmetry in toggling BCC fields keeps the code consistent and easy to reason about.


675-719: Rendering CC emails and input fields is correct.

The chip UI and input handling align with your approach for “To” recipients. Implementation details look consistent.


721-765: BCC rendering follows the same pattern as CC.

Consistent design patterns help reduce errors and simplify future maintenance.


925-941: Attachment input UI is well-structured.

Offering a hidden file input with a visual button is a standard, user-friendly pattern for adding attachments.


946-948: Disable logic prevents incomplete sends.

Requiring valid to/subject/messageContent before enabling the send button is a sensible safeguard.

Comment on lines 134 to 190
// Process to, cc, and bcc email addresses
const toList = processDraftEmails(draft.to);
const ccList = processDraftEmails(draft.cc);
const bccList = processDraftEmails(draft.bcc);

// Set emails and update mail state in a batch
if (toList.length > 0) {
setToEmails(toList);
}

if (draft.subject) {
setSubjectInput(draft.subject);
}

// Single mail state update for both CC and BCC
const mailStateUpdates = {
showCc: ccList.length > 0,
showBcc: bccList.length > 0,
};

setMail((prev) => ({ ...prev, ...mailStateUpdates }));

// Only set cc/bcc emails if there are any
if (ccList.length > 0) {
setCcEmails(ccList);
}

if (bccList.length > 0) {
setBccEmails(bccList);
}

Copy link
Contributor

@coderabbitai coderabbitai bot Apr 15, 2025

Choose a reason for hiding this comment

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

⚠️ Potential issue

Handle clearing addresses when a draft has no recipients.

Currently, the code only sets toEmails, ccEmails, or bccEmails if the parsed list is non-empty (length > 0). This may leave stale emails from a previously loaded draft. Consider always updating these states to ensure they properly clear when empty.

Apply the following diff to fix the stale data risk:

- if (toList.length > 0) {
-   setToEmails(toList);
- }
+ setToEmails(toList);

...
- if (ccList.length > 0) {
-   setCcEmails(ccList);
- }
+ setCcEmails(ccList);

...
- if (bccList.length > 0) {
-   setBccEmails(bccList);
- }
+ setBccEmails(bccList);
📝 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
// Process to, cc, and bcc email addresses
const toList = processDraftEmails(draft.to);
const ccList = processDraftEmails(draft.cc);
const bccList = processDraftEmails(draft.bcc);
// Set emails and update mail state in a batch
if (toList.length > 0) {
setToEmails(toList);
}
if (draft.subject) {
setSubjectInput(draft.subject);
}
// Single mail state update for both CC and BCC
const mailStateUpdates = {
showCc: ccList.length > 0,
showBcc: bccList.length > 0,
};
setMail((prev) => ({ ...prev, ...mailStateUpdates }));
// Only set cc/bcc emails if there are any
if (ccList.length > 0) {
setCcEmails(ccList);
}
if (bccList.length > 0) {
setBccEmails(bccList);
}
// Process to, cc, and bcc email addresses
const toList = processDraftEmails(draft.to);
const ccList = processDraftEmails(draft.cc);
const bccList = processDraftEmails(draft.bcc);
// Set emails and update mail state in a batch
setToEmails(toList);
if (draft.subject) {
setSubjectInput(draft.subject);
}
// Single mail state update for both CC and BCC
const mailStateUpdates = {
showCc: ccList.length > 0,
showBcc: bccList.length > 0,
};
setMail((prev) => ({ ...prev, ...mailStateUpdates }));
// Clear or set cc/bcc emails
setCcEmails(ccList);
setBccEmails(bccList);

Copy link
Collaborator

Choose a reason for hiding this comment

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

maybe we can do this?

Copy link
Contributor

Choose a reason for hiding this comment

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

@MrgSub Yes, that's exactly what you should do! The suggested change is important because it prevents stale email addresses from persisting.

Currently, if you load a draft without CC/BCC recipients after viewing one that had them, the old addresses would still display because the empty arrays aren't being applied to the state. Always setting these states (even with empty arrays) ensures accurate representation of the current draft.

This is a small but important fix for proper state management. Would you like me to suggest any other improvements to the CC/BCC implementation?

ʕ •ᴥ•ʔ

`From: me`,
`To: ${data.to}`,
// Helper function to sanitize email addresses
const sanitizeEmails = (emailStr: string): string => {
Copy link
Collaborator

Choose a reason for hiding this comment

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

do we need this inside createDraft

Comment on lines 134 to 190
// Process to, cc, and bcc email addresses
const toList = processDraftEmails(draft.to);
const ccList = processDraftEmails(draft.cc);
const bccList = processDraftEmails(draft.bcc);

// Set emails and update mail state in a batch
if (toList.length > 0) {
setToEmails(toList);
}

if (draft.subject) {
setSubjectInput(draft.subject);
}

// Single mail state update for both CC and BCC
const mailStateUpdates = {
showCc: ccList.length > 0,
showBcc: bccList.length > 0,
};

setMail((prev) => ({ ...prev, ...mailStateUpdates }));

// Only set cc/bcc emails if there are any
if (ccList.length > 0) {
setCcEmails(ccList);
}

if (bccList.length > 0) {
setBccEmails(bccList);
}

Copy link
Collaborator

Choose a reason for hiding this comment

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

maybe we can do this?

@jlokos jlokos closed this Apr 16, 2025
@jlokos jlokos reopened this Apr 16, 2025
@SwedishChef1
Copy link

@jlokos
Copy link
Contributor Author

jlokos commented Apr 17, 2025

@AxelJetpack from understanding the browser should already be handling this (chrome://settings/handlers). I have not run into this issue. If its problematic for others I guess I could add a guard via localStorage.

2025-04-17 at 14 37 27@2x

@MrgSub @nizzyabi - once merged I can set a localStorage guard up (if needed) - I would prefer to base it from here since my initial PR #574 was modified in this PR.

@SwedishChef1
Copy link

@AxelJetpack from understanding the browser should already be handling this (chrome://settings/handlers). I have not run into this issue. If its problematic for others I guess I could add a guard via localStorage.

2025-04-17 at 14 37 27@2x

@MrgSub @nizzyabi - once merged I can set a localStorage guard up (if needed) - I would prefer to base it from here since my initial PR #574 was modified in this PR.

Thank you! I'll see if I can get some more information from the user! :)

@ahmetskilinc ahmetskilinc changed the base branch from main to staging April 21, 2025 11:49
jlokos added 3 commits April 25, 2025 19:17
Implements proper handling of CC and BCC fields in mailto links, including:
- Parsing CC and BCC values from mailto URLs
- Adding CC and BCC headers to MIME messages when creating drafts
- Extracting CC and BCC values from draft headers
- Validating and sanitizing email addresses
- Updating UI to display CC and BCC fields when values are present

Enhances the existing mailto protocol handler support from PR Mail-0#574
Removes the redundant /mail/compose route and unifies email creation and draft handling under /mail/create.
@jlokos jlokos force-pushed the feat/mailto-cc-bcc-support branch from a16de52 to 0df55d2 Compare April 25, 2025 19:20
@jlokos jlokos changed the base branch from staging to global-ai April 25, 2025 19:24
@MrgSub MrgSub deleted the branch Mail-0:global-ai April 27, 2025 04:04
@MrgSub MrgSub closed this Apr 27, 2025
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.

4 participants