Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Parse From header according to RFC 2822 #472

Merged
merged 4 commits into from
Mar 18, 2025

Conversation

danteissaias
Copy link
Contributor

@danteissaias danteissaias commented Mar 17, 2025

Description

This PR makes the From header parsing match RFC 2822. It can technically hold multiple email addresses, but since that’s not used in practice, we just grab the first one.

This fixes a bug I had where a From header with just an email address and no name showed up wrong in the UI.

Important

When testing this PR, make sure to clear your local Dexie/SWC cache. We don’t revalidate messages after fetching them, so you won’t have the newly parsed sender.


Type of Change

Please delete options that are not relevant.

  • 🐛 Bug fix (non-breaking change which fixes an issue)
  • ✨ New feature (non-breaking change which adds functionality)
  • 💥 Breaking change (fix or feature with breaking changes)
  • 📝 Documentation update
  • 🎨 UI/UX improvement
  • 🔒 Security enhancement
  • ⚡ Performance improvement

Areas Affected

Please check all that apply:

  • Email Integration (Gmail, IMAP, etc.)
  • User Interface/Experience
  • Authentication/Authorization
  • Data Storage/Management
  • API Endpoints
  • Documentation
  • Testing Infrastructure
  • Development Workflow
  • Deployment/Infrastructure

Testing Done

Describe the tests you've done:

  • Unit tests added/updated
  • Integration tests added/updated
  • Manual testing performed
  • Cross-browser testing (if UI changes)
  • Mobile responsiveness verified (if UI changes)

Security Considerations

For changes involving data or authentication:

  • No sensitive data is exposed
  • Authentication checks are in place
  • Input validation is implemented
  • Rate limiting is considered (if applicable)

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
  • I have updated the documentation
  • My changes generate no new warnings
  • I have added tests that prove my fix/feature works
  • All tests pass locally
  • Any dependent changes are merged and published

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
    • Enhanced the extraction of email sender details to ensure more accurate display of sender information in your inbox.
  • Style
    • Applied minor formatting adjustments to email thread presentations and layouts for a more consistent viewing experience.
  • Chores
    • Updated and reorganized dependencies to support these improvements and maintain overall system performance.

Copy link

vercel bot commented Mar 17, 2025

@danteissaias 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 Mar 17, 2025

Walkthrough

This PR modifies email handling and UI components. The driver function now extracts sender details using a new utility function, parseFrom, instead of manual string splitting. A new parseFrom function is added in the email utilities file to robustly parse the "From" header with fallback defaults. Minor formatting improvements are applied to UI components, and CSS class orders are rearranged in the mail layout. Additionally, package dependencies are reorganized and new ones are introduced for email parsing and rich text editing.

Changes

File Path Change Summary
apps/mail/app/api/driver/google.ts Replaced manual sender parsing with a call to parseFrom from the email-utils module.
apps/mail/lib/email-utils.ts Added new parseFrom function using the email-addresses library; defined FALLBACK_SENDER for fallback values.
apps/mail/components/mail/mail-list.tsx Adjusted object destructuring formatting in the Thread component (added spaces for consistency).
apps/mail/components/mail/mail.tsx Rearranged CSS classes in the DemoMailLayout component without affecting functionality.
apps/mail/package.json Reorganized dependencies: re-added some dependencies and introduced new ones (email-addresses, input-otp, @tiptap/starter-kit).

Sequence Diagram(s)

sequenceDiagram
    participant Driver as Driver Function
    participant Parser as parseFrom()
    participant EmailLib as email-addresses Library
    
    Driver->>Parser: Pass sender string
    Parser->>EmailLib: Parse email header
    EmailLib-->>Parser: Return parsed data (or empty)
    Parser-->>Driver: Return sender object (or fallback)
Loading

Suggested reviewers

  • nizzyabi
  • MrgSub

Poem

Hoppity-hop, I'm the coding bunny,
Parsing emails crisp and sunny.
parseFrom leads the way so neat,
In every function, a joyful beat.
Cheers to clean code—let’s hop to the tune! 🐰
Enjoy the nibble of refined design!

Tip

⚡🧪 Multi-step agentic review comment chat (experimental)
  • We're introducing multi-step agentic chat in review comments. This experimental feature enhances review discussions with the CodeRabbit agentic chat by enabling advanced interactions, including the ability to create pull requests directly from comments.
    - To enable this feature, set early_access to true under in the settings.
✨ Finishing Touches
  • 📝 Generate Docstrings

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

@danteissaias danteissaias changed the title Parse from header according to RFC 2822 Parse From header according to RFC 2822 Mar 17, 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: 0

🧹 Nitpick comments (4)
apps/mail/lib/email-utils.ts (4)

135-138: Consider more descriptive fallback values

While "Unknown" works as a fallback, consider using values that better indicate a parsing failure rather than potentially misleading users into thinking there might be an actual sender named "Unknown".

const FALLBACK_SENDER = {
-  name: "Unknown",
-  email: "unknown"
+  name: "No Sender Name",
+  email: "no-sender@unknown"
}

140-159: Missing TypeScript return type annotation

The function is well-implemented and handles various edge cases correctly. However, adding a return type would improve type safety and make it clearer for consumers what structure to expect.

- export const parseFrom = (fromHeader: string) => {
+ export const parseFrom = (fromHeader: string): { name: string; email: string } => {

Also, the implementation correctly handles parsing failures and different sender types according to RFC 2822. The comments explaining the handling of multiple email addresses are helpful for future maintainers.


151-154: Add defensive check for empty addresses array

The code correctly handles the group case by using the first address, but there's a potential edge case if the addresses array is defined but empty.

if (firstSender.type === "group") {
-  const email = firstSender.addresses[0]?.address || FALLBACK_SENDER.email
+  const email = firstSender.addresses?.length ? (firstSender.addresses[0]?.address || FALLBACK_SENDER.email) : FALLBACK_SENDER.email
  return {name, email}
}

156-158: Add defensive check for missing address property

For completeness, consider adding a fallback for the unlikely case where the address property is undefined.

- const email = firstSender.address
+ const email = firstSender.address || FALLBACK_SENDER.email
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 18bab46 and 473f99e.

⛔ Files ignored due to path filters (1)
  • bun.lock is excluded by !**/*.lock
📒 Files selected for processing (5)
  • apps/mail/app/api/driver/google.ts (3 hunks)
  • apps/mail/components/mail/mail-list.tsx (1 hunks)
  • apps/mail/components/mail/mail.tsx (2 hunks)
  • apps/mail/lib/email-utils.ts (2 hunks)
  • apps/mail/package.json (4 hunks)
🔇 Additional comments (8)
apps/mail/components/mail/mail-list.tsx (1)

64-64: Good spacing adjustment for consistency.

The spacing in the object literal has been updated for better code style consistency.

apps/mail/components/mail/mail.tsx (2)

99-99: CSS class reordering looks good.

Reordering CSS classes for better readability. This is a stylistic change that doesn't affect functionality.


134-134: CSS class reordering looks good.

Similar to the previous change, this is a stylistic improvement that reorders CSS classes without changing their effect.

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

6-6: Good addition of parseFrom import.

Adding import for the new utility function that will handle RFC 2822 email parsing.


141-141: Great improvement in From header parsing.

Replacing manual string splitting with a dedicated parsing function that handles RFC 2822 format correctly. This should properly address the bug where From headers containing only an email address were incorrectly displayed.

apps/mail/package.json (2)

74-74: Good addition of email-addresses dependency.

Adding the email-addresses package to support proper RFC 2822 compliant parsing of email headers.


17-17: Package dependency adjustments look good.

The reordering and addition of various dependencies supports the changes made in the codebase while maintaining compatibility.

Also applies to: 49-49, 55-55, 79-79

apps/mail/lib/email-utils.ts (1)

3-3: Good import renaming strategy

Renaming the library's parseFrom to _parseFrom clearly distinguishes it from the wrapper function you've created. This prevents namespace conflicts and indicates the internal usage relationship.

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 (2)
apps/mail/lib/email-utils.ts (2)

140-159: Well-structured RFC 2822 parsing implementation

The implementation of parseFrom is thorough and handles multiple scenarios correctly, including:

  • Failed parsing
  • Missing sender information
  • Group-type senders (as defined in RFC 2822)
  • Regular individual senders

The function's comment about multiple email addresses is helpful context that explains your design decision.

Consider adding TypeScript return type annotations for better type safety:

-export const parseFrom = (fromHeader: string) => {
+export const parseFrom = (fromHeader: string): { name: string; email: string } => {

152-152: Consider simplifying the conditional expression

This line handles several nested conditions which could be simplified for better readability.

-  const email = firstSender.addresses?.length ? (firstSender.addresses[0]?.address || FALLBACK_SENDER.email) : FALLBACK_SENDER.email;
+  const firstAddress = firstSender.addresses?.[0]?.address;
+  const email = firstAddress || FALLBACK_SENDER.email;
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 473f99e and e74dc13.

📒 Files selected for processing (1)
  • apps/mail/lib/email-utils.ts (2 hunks)
🔇 Additional comments (3)
apps/mail/lib/email-utils.ts (3)

3-3: Good addition of email parsing library

The import of parseFrom from the "email-addresses" library is a solid choice for standardized email address parsing, aligning well with the PR's objective to handle the From header according to RFC 2822.


135-138: Appropriate fallback values

The FALLBACK_SENDER constant defines reasonable default values for cases where sender information cannot be parsed, which is good defensive programming.


144-146: Great documentation of RFC understanding

The comment explaining that the From header can technically contain multiple email addresses according to RFC 2822 shows attention to detail and standards compliance, which aligns perfectly with the PR's objectives.

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 (2)
apps/mail/lib/email-utils.ts (2)

140-160: Consider adding TypeScript type definitions for the return value.

The implementation correctly handles various edge cases when parsing the "From" header according to RFC 2822, which should fix the reported UI bug. However, adding an explicit interface or type for the return value would improve type safety and documentation.

+interface SenderInfo {
+  name: string;
+  email: string;
+}
+
+const FALLBACK_SENDER: SenderInfo = {
 const FALLBACK_SENDER = {
   name: "No Sender Name",
   email: "no-sender@unknown"
 }

-export const parseFrom = (fromHeader: string) => {
+export const parseFrom = (fromHeader: string): SenderInfo => {

151-155: Fix indentation for consistency.

The indentation in this block uses 3 spaces instead of 2 spaces used elsewhere in the file.

 if (firstSender.type === "group") {
-   const firstAddress = firstSender.addresses?.[0]?.address;
-   const email = firstAddress || FALLBACK_SENDER.email;
-   return { name, email };
+  const firstAddress = firstSender.addresses?.[0]?.address;
+  const email = firstAddress || FALLBACK_SENDER.email;
+  return { name, email };
 }
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between e74dc13 and 7c0d3bb.

📒 Files selected for processing (1)
  • apps/mail/lib/email-utils.ts (2 hunks)
🔇 Additional comments (3)
apps/mail/lib/email-utils.ts (3)

1-1: Good choice importing and renaming the external library function.

Using _parseFrom for the imported function while exporting your own parseFrom implementation is a clean approach that avoids name conflicts while making your API clear.


135-138: FALLBACK_SENDER provides good defaults for error cases.

Creating a constant for fallback values ensures consistency across the codebase when parsing fails. This is a good defensive programming practice.


144-146: Good documentation on RFC 2822 compliance.

The comment explaining why you're only processing the first sender is valuable for future maintainers to understand the design decision, especially since it references the relevant RFC standard.

Copy link
Collaborator

@MrgSub MrgSub left a comment

Choose a reason for hiding this comment

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

LGTM

Copy link

vercel bot commented Mar 18, 2025

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
0 ✅ Ready (Inspect) Visit Preview 💬 Add feedback Mar 18, 2025 0:57am

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants