Skip to content

Load more data for outlook stats#977

Merged
elie222 merged 2 commits intomainfrom
fix/outlook-stats
Nov 16, 2025
Merged

Load more data for outlook stats#977
elie222 merged 2 commits intomainfrom
fix/outlook-stats

Conversation

@elie222
Copy link
Owner

@elie222 elie222 commented Nov 16, 2025

Summary by CodeRabbit

  • Bug Fixes

    • Optimized message retrieval and folder filtering for Outlook and Microsoft email services.
    • Improved draft handling consistency.
  • Chores

    • Version bumped to v2.19.8.

@vercel
Copy link

vercel bot commented Nov 16, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Updated (UTC)
inbox-zero Ready Ready Preview Nov 16, 2025 10:24am

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 16, 2025

Walkthrough

This PR refactors Outlook message retrieval by removing folder-ID inference logic and helper functions, shifting folder and draft filtering to downstream processing. The queryBatchMessages function now uses optional conditional folder filtering instead of forced inbox/archive defaults, while a corresponding test file is removed.

Changes

Cohort / File(s) Summary
Outlook Message Retrieval
apps/web/utils/outlook/message.ts, apps/web/utils/email/microsoft.ts
Removed hasUnquotedParentFolderId and stripQuotedLiterals helper functions. Changed queryBatchMessages to apply folder filtering conditionally (only when folderId is provided) rather than forcing inbox/archive defaults. Restructured filter construction to build conditional filter arrays and made request.filter calls conditional. Adjusted ordering to apply DESC only for non-paginated requests. Removed folderId inference and parameter passing in getMessagesWithPagination.
Test Removal
apps/web/utils/outlook/message.test.ts
Deleted entire test suite covering hasUnquotedParentFolderId function, including positive/negative detection tests across various query patterns and edge cases.
Version Bump
version.txt
Updated version from v2.19.7 to v2.19.8.

Sequence Diagram

sequenceDiagram
    participant Client
    participant microsoft.ts as getMessagesWithPagination<br/>(microsoft.ts)
    participant message.ts as queryBatchMessages<br/>(message.ts)
    participant OutlookAPI

    Client->>microsoft.ts: Request messages
    Note over microsoft.ts: No folderId inference<br/>from parentFolderId
    microsoft.ts->>message.ts: Call queryBatchMessages<br/>(no folderId param)
    
    alt folderId provided
        message.ts->>message.ts: Build filters array<br/>with folderFilter
    else folderId not provided
        message.ts->>message.ts: Build filters array<br/>without folder constraint
    end
    
    message.ts->>OutlookAPI: Request with conditional<br/>filter constraints
    OutlookAPI-->>message.ts: Return messages<br/>(multiple folders possible)
    message.ts->>message.ts: Post-fetch filtering<br/>(downstream filtering:<br/>drafts, folder constraints)
    message.ts-->>Client: Filtered messages
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • apps/web/utils/outlook/message.ts: The primary complexity lies here with restructured filter construction logic, conditional folder filtering, modified ordering logic, and changes to both search and non-search code paths. Review should verify that the conditional filter application is correct and that post-fetch filtering properly handles edge cases.
  • Interaction between microsoft.ts and message.ts: Verify that removing folderId inference and passing doesn't break expected behavior and that downstream filtering in convertMessages compensates appropriately.
  • Removed functions: Confirm that stripQuotedLiterals and hasUnquotedParentFolderId have no other callers throughout the codebase.

Possibly related PRs

  • Don't load threads for outlook draft #906: Both PRs shift Outlook message/thread retrieval to rely on convertMessage and downstream folder/draft filtering, removing folder-ID–based assumptions in favor of post-fetch processing.
  • Fix outlook error #839: Both PRs modify folder-filtering logic in apps/web/utils/outlook/message.ts and apps/web/utils/email/microsoft.ts, restructuring how filters are constructed and applied to message queries.
  • Fix outlook search #909: Both PRs modify queryBatchMessages in apps/web/utils/outlook/message.ts, with this PR removing folder-filtering logic while the other adds search-query sanitization and related search-path changes.

Suggested reviewers

  • mosesjames7271-svg

Poem

🐰 With folder filtering moved downstream,
No more inbox-ID dreams!
Conditional logic flows so clean,
Filtering fetched, not foreseen—
A refactor, swift and lean! ✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Title check ❓ Inconclusive The title 'Load more data for outlook stats' is vague and does not clearly reflect the main changes in the PR. The PR primarily removes folder ID filtering logic and helper functions from Outlook message querying, but the title suggests a feature addition rather than a refactoring. Consider a more specific title such as 'Remove folder ID filtering from Outlook message queries' or 'Refactor Outlook message filtering to rely on downstream processing' to better reflect the actual changes.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/outlook-stats

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

No issues found across 4 files

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 (1)
apps/web/utils/outlook/message.ts (1)

232-256: Filter‑path refactor to use filters[] and conditional .filter() is an improvement

Building a filters array, composing combinedFilter only when non‑empty, and guarding the call to .filter(combinedFilter) avoids sending an empty $filter and keeps the logic straightforward.

This is a clean, maintainable approach and aligns with the new optional folder filter behavior.

If you later need to add more conditions (e.g., explicit Junk/Deleted exclusion), extending this filters array pattern will keep the code simple and testable.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1b8c1ac and 41a51a6.

📒 Files selected for processing (4)
  • apps/web/utils/email/microsoft.ts (1 hunks)
  • apps/web/utils/outlook/message.test.ts (0 hunks)
  • apps/web/utils/outlook/message.ts (3 hunks)
  • version.txt (1 hunks)
💤 Files with no reviewable changes (1)
  • apps/web/utils/outlook/message.test.ts
🧰 Additional context used
🧬 Code graph analysis (1)
apps/web/utils/outlook/message.ts (1)
apps/web/utils/outlook/odata-escape.ts (1)
  • escapeODataString (13-20)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: cubic · AI code reviewer
  • GitHub Check: test
🔇 Additional comments (2)
version.txt (1)

1-1: Version bump looks consistent

Version updated to v2.19.8; no code logic involved here. Looks good.

apps/web/utils/outlook/message.ts (1)

186-225: New optional folder filtering semantics look good, but confirm callers expect broader scope

The change to compute folderFilter only when folderId is provided and to rely on post‑processing for search results means:

  • If folderId is omitted, both search and filter paths now operate over all folders (subject to Graph defaults) instead of implicitly limiting to inbox/archive.
  • If folderId is provided, the behavior remains scoped via parentFolderId eq '<folderId>' or post‑filtering in the search path.

This matches the PR goal of loading more data, but it does change the contract: any consumers that previously assumed “inbox/archive only” from queryBatchMessages when omitting folderId will now see a wider set (e.g., sent, archive, potentially others).

Recommend quickly auditing the known call sites (e.g., generic message listing vs. stats) to ensure:

  • UI‑facing flows that should stay inbox‑only pass an explicit folderId or use queryMessagesWithFilters.
  • Stats/reporting flows intentionally rely on the broader scope.

Comment on lines +763 to 765
// Don't pass folderId - let the API return all folders except Junk/Deleted (auto-excluded)
// Drafts are filtered out in convertMessages
const response = await queryBatchMessages(this.client, {
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Clarify drafts behavior and Junk/Deleted assumptions for this path

The new behavior (no folderId passed) makes sense for “load more data for Outlook stats” and matches the new queryBatchMessages semantics.

Two points to double‑check:

  1. Drafts filtering:

    • convertMessages explicitly filters out message.isDraft.
    • getDrafts() here calls getMessagesWithPagination({ query: "isDraft eq true", ... }), which ultimately goes through queryBatchMessagesconvertMessages, so any drafts returned by Graph will be dropped.
    • If getDrafts() is used anywhere, it will never return results with the current pipeline. You may want either:
      • A dedicated drafts path that bypasses convertMessages, or
      • A way to opt out of the draft filter when the caller explicitly requests drafts.
  2. “API excludes Junk/Deleted by default” comment:

    • If this relies on Microsoft Graph behavior rather than our own filters, it might be worth confirming and/or documenting that guarantee; otherwise, we may need explicit exclusion filters if Junk/Deleted should stay out of stats.

🏁 Script executed:

#!/bin/bash
# Find getDrafts implementation
echo "=== Finding getDrafts implementation ==="
rg -nA 20 'getDrafts\s*\(' --type=ts apps/web/utils/

echo ""
echo "=== Finding convertMessages implementation ==="
rg -nA 30 'export.*convertMessages|function convertMessages' --type=ts apps/web/utils/

echo ""
echo "=== Checking queryBatchMessages and getMessagesWithPagination ==="
rg -nB 5 -A 15 'const queryBatchMessages|function queryBatchMessages' --type=ts apps/web/

Length of output: 11592


🌐 Web query:

Microsoft Graph API /me/mailFolders default behavior Junk Deleted excluded

💡 Result:

Short answer: /me/mailFolders lists the mail folders directly under the mailbox root (shallow), and it does not implicitly exclude JunkEmail or DeletedItems — those well‑known folders exist as children and will be returned if they are direct children. (What does get excluded by default is hidden folders; and /me/messages — a different endpoint — does skip some folders like Sent/Outbox/Junk/Deleted when listing "all messages".) [1][2][3]

Notes and quick tips:

  • To get a specific folder use the well‑known name, e.g. /me/mailFolders/Inbox or /me/mailFolders/JunkEmail. [2]
  • To include hidden folders add ?includeHiddenFolders=true. [1][3]

Sources:

  • MailFolders behavior (list, includeHiddenFolders). [1]
  • Well‑known folder names and examples (Inbox, JunkEmail, DeletedItems). [2]
  • Microsoft Q&A / guidance on traversal (v1.0 shallow vs beta full traversal). [3]

🏁 Script executed:

#!/bin/bash
# Get full queryBatchMessages implementation
echo "=== Full queryBatchMessages implementation ==="
rg -nA 50 'export async function queryBatchMessages' apps/web/utils/outlook/message.ts

echo ""
echo "=== Check for Graph endpoint calls and folder filtering ==="
rg -nB 5 -A 5 'mailFolders|/messages|JunkEmail|DeletedItems' apps/web/utils/outlook/message.ts | head -80

Length of output: 3063


🏁 Script executed:

#!/bin/bash
# Find getMessagesWithPagination in microsoft.ts (the method called by getDrafts)
echo "=== getMessagesWithPagination in microsoft.ts ==="
rg -nB 5 -A 40 'async getMessagesWithPagination' apps/web/utils/email/microsoft.ts

echo ""
echo "=== Check if convertMessages is called directly or in queryBatchMessages ==="
rg -nB 3 -A 3 'convertMessages' apps/web/utils/email/microsoft.ts

Length of output: 2061


🏁 Script executed:

#!/bin/bash
# Get complete queryBatchMessages implementation (it was cut off)
echo "=== Complete queryBatchMessages implementation ==="
rg -nA 120 'export async function queryBatchMessages' apps/web/utils/outlook/message.ts | grep -A 120 'export async function queryBatchMessages'

echo ""
echo "=== Check where convertMessages is called in queryBatchMessages output ==="
rg -n 'convertMessages' apps/web/utils/outlook/message.ts

Length of output: 4856


Fix getDrafts() to bypass draft filtering when explicitly requesting drafts

When getDrafts() calls getMessagesWithPagination({ query: "isDraft eq true", ... }), the results flow through queryBatchMessagesconvertMessages, which unconditionally filters out all messages where !message.isDraft (line 370 of apps/web/utils/outlook/message.ts). This means getDrafts() will always return an empty array, breaking the active feature in apps/web/utils/ai/report/fetch.ts:110–128 that relies on it to fetch draft email templates.

Two options to fix:

  • Add a bypass flag to convertMessages to skip draft filtering when explicitly requested, or
  • Create a dedicated drafts-only path that skips convertMessages filtering.

The comment about Junk/Deleted being auto-excluded by the API is accurate per Microsoft Graph /me/messages behavior and does not require changes.

🤖 Prompt for AI Agents
In apps/web/utils/email/microsoft.ts around lines 763-765, getDrafts() currently
calls queryBatchMessages → convertMessages which unconditionally filters out
drafts; update convertMessages to accept an options parameter (e.g., {
allowDrafts: boolean } defaulting to false) that, when true, bypasses the
"!message.isDraft" filter, then change queryBatchMessages/getDrafts to pass
allowDrafts: true for the drafts path; ensure all other call sites keep default
behavior and update related types/comments accordingly.

@elie222 elie222 merged commit 4a48330 into main Nov 16, 2025
18 checks passed
@elie222 elie222 deleted the fix/outlook-stats branch November 16, 2025 10:50
@coderabbitai coderabbitai bot mentioned this pull request Dec 3, 2025
This was referenced Jan 7, 2026
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.

1 participant

Comments