Skip to content

Process read emails in bulk process#1118

Merged
elie222 merged 4 commits intomainfrom
feat/allow-process-read
Dec 19, 2025
Merged

Process read emails in bulk process#1118
elie222 merged 4 commits intomainfrom
feat/allow-process-read

Conversation

@elie222
Copy link
Owner

@elie222 elie222 commented Dec 19, 2025

Summary by CodeRabbit

  • New Features

    • Added "Notify Sender" action for cold email rules to automatically send notifications to senders
    • Added "Include read emails" toggle for bulk rule runs (Business Plus tier)
  • Bug Fixes

    • Improved reply subject formatting for emails without a subject line
  • Chores

    • Version bump to v2.25.1
    • UI reorganization in cold email blocker

✏️ Tip: You can customize this high-level summary in your review settings.

@vercel
Copy link

vercel bot commented Dec 19, 2025

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

Project Deployment Review Updated (UTC)
inbox-zero Ready Ready Preview Dec 19, 2025 0:41am

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 19, 2025

Warning

Rate limit exceeded

@elie222 has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 7 minutes and 11 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between e18ddb0 and ee29103.

📒 Files selected for processing (2)
  • apps/web/app/(app)/[emailAccountId]/assistant/BulkRunRules.tsx (10 hunks)
  • version.txt (1 hunks)

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.

Walkthrough

This PR introduces a new NOTIFY_SENDER action type for cold email rules, enabling automated notifications to senders of detected cold emails. Changes span the full stack: schema definitions, database migration, UI components for action configuration and display, action execution handlers, email notification templates, and premium feature gating for bulk operations.

Changes

Cohort / File(s) Change Summary
Action Type Schema & Constants
prisma/schema.prisma, prisma/migrations/20251219012216_add_notify_sender_action_type/migration.sql
Adds NOTIFY_SENDER enum value to ActionType via schema and migration.
UI Constants & Color Mapping
apps/web/app/(app)/[emailAccountId]/assistant/constants.ts
Introduces NOTIFY_SENDER to ACTION_TYPE_COLORS (amber-500), ACTION_TYPE_TEXT_COLORS, ACTION_TYPE_ICONS (BellIcon), and updates getActionTypeColor to recognize "notify" or "sender" patterns.
Action Item Configuration
apps/web/utils/action-item.ts, apps/web/utils/action-display.tsx, apps/web/utils/actions/rule.validation.ts
Adds NOTIFY_SENDER support to actionInputs, sanitizeActionFields, getActionFields, getActionDisplay, getActionIcon, and Zod validation schema.
Action Execution
apps/web/utils/ai/actions.ts
Routes ActionType.NOTIFY_SENDER to a new notify_sender handler that extracts sender email, sends notification, and handles errors gracefully.
Email Notification Service
apps/web/utils/cold-email/send-notification.ts
New helper function sendColdEmailNotification that sends cold email notifications via Resend with configuration guard, logging, and error handling.
Resend Email Integration
packages/resend/src/send.tsx, packages/resend/emails/cold-email-notification.tsx
Adds sendColdEmailNotification function and new ColdEmailNotification React email template component; centralizes RESEND_NOT_CONFIGURED_MESSAGE.
Action UI Components
apps/web/app/(app)/[emailAccountId]/assistant/ActionSteps.tsx, ActionSummaryCard.tsx, AvailableActionsPanel.tsx, RuleForm.tsx
Adds NOTIFY_SENDER rendering in ActionCard, summary text with tooltip, available action entry, and conditional option in RuleForm (gated by COLD_EMAIL system type and NEXT_PUBLIC_IS_RESEND_CONFIGURED).
Component Utilities
apps/web/components/PlanBadge.tsx, apps/web/app/(landing)/components/page.tsx
Adds NOTIFY_SENDER case to getActionLabel and getActionColor; adds action to ActionBadges list.
Bulk Run Rules
apps/web/app/(app)/[emailAccountId]/assistant/BulkRunRules.tsx
Adds Premium tier gating (Business Plus), includeRead toggle, conditional isUnread filtering in query, and updated UI messaging for email counts.
Cold Email Blocker Layout
apps/web/app/(app)/[emailAccountId]/cold-email-blocker/ColdEmailContent.tsx
Reorders tab triggers, changes default active tab from "test" to "cold-emails".
Email & Utility Updates
apps/web/utils/email/subject.ts, apps/web/utils/error.ts, apps/web/components/email-list/EmailMessage.tsx, apps/web/env.ts, version.txt
Adds guard for empty subjects in formatReplySubject; adds getErrorMessage helper and updates captureException signature; updates EmailMessage to use formatReplySubject; adds NEXT_PUBLIC_IS_RESEND_CONFIGURED env variable; bumps version to v2.25.1.

Sequence Diagram

sequenceDiagram
    participant Rule as Rule Engine
    participant Action as Action Handler
    participant Notif as Notification Service
    participant Resend as Resend API
    participant Logger as Logger

    Rule->>Action: Execute NOTIFY_SENDER action
    Action->>Action: Extract sender email & subject
    Action->>Notif: sendColdEmailNotification()
    alt Configuration check
        Notif->>Logger: Log warning if RESEND_API_KEY missing
        Notif-->>Action: Return error
    else Key present
        Notif->>Notif: Format reply subject & build payload
        Notif->>Resend: Send email via Resend API
        alt Success
            Resend-->>Notif: Return messageId
            Notif->>Logger: Log acceptance with messageId
            Notif-->>Action: Return { success: true }
        else Failure
            Resend-->>Notif: Return error
            Notif->>Logger: Log error message
            Notif-->>Action: Return { success: false, error }
        end
    end
    Action->>Logger: Log result (best-effort, continue on failure)
    Action-->>Rule: Complete (non-blocking)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • BulkRunRules.tsx: Premium tier gating logic, includeRead toggle, and conditional isUnread filtering require careful validation for query construction and UI messaging accuracy
  • send-notification.ts: Error handling flow, RESEND_API_KEY guard, and integration with Resend API need verification
  • Email template (ColdEmailNotificationComponent): Verify email content is appropriate and template renders correctly
  • RuleForm.tsx conditional logic: Ensure NOTIFY_SENDER option appears only when rule.systemType === COLD_EMAIL and NEXT_PUBLIC_IS_RESEND_CONFIGURED is set
  • Action registration across components: Confirm consistent NOTIFY_SENDER handling in ActionSteps, ActionSummaryCard, and AvailableActionsPanel
  • Database migration: Verify ALTER TYPE syntax is correct for PostgreSQL enum extension

Possibly related PRs

Suggested reviewers

  • edulelis

🐰 A sender's plea now finds an ear,
With bells that chime both far and clear,
Inbox Zero whispers soft and true,
"Your cold emails caught—we'll notify you!"
In amber glow, the action shines,
New rules and flows in perfect lines. 🔔

Pre-merge checks and finishing touches

❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Title check ⚠️ Warning The PR title 'Process read emails in bulk process' refers to a real aspect of the changes (adding includeRead toggle in BulkRunRules.tsx), but it fails to capture the main objective of adding the NOTIFY_SENDER action type, which represents the majority of the changeset across 15+ files. Update the title to reflect the primary change: 'Add NOTIFY_SENDER action type for cold email blocking' or similar. Alternatively, if bulk email processing is the main goal, clarify that the PR adds both bulk read email processing and a new notification action.
Docstring Coverage ⚠️ Warning Docstring coverage is 12.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

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.

@macroscopeapp
Copy link
Contributor

macroscopeapp bot commented Dec 19, 2025

Add a premium-gated toggle in BulkRunRules to include read emails in bulk processing and pass the flag to onRun in BulkRunRules.tsx

Add an Include read emails toggle gated at BUSINESS_PLUS_MONTHLY, wire an upgrade link to PremiumModal, and pass includeRead to onRun to omit the isUnread filter when true; bump version to v2.25.2.

📍Where to Start

Start with the BulkRunRules component in BulkRunRules.tsx, focusing on the includeRead state, the premium gating logic, and the updated onRun call.


Macroscope summarized ee29103.

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.

2 issues found across 23 files

Prompt for AI agents (all 2 issues)

Check if these issues are valid — if so, understand the root cause of each and fix them.


<file name="packages/resend/emails/cold-email-notification.tsx">

<violation number="1" location="packages/resend/emails/cold-email-notification.tsx:34">
P2: Image source is hardcoded while `baseUrl` prop is available for configurable URLs. This inconsistency means the image will always point to production even when `baseUrl` is overridden (e.g., in development/staging environments). Consider using the `baseUrl` prop for consistency.</violation>
</file>

<file name="apps/web/app/(app)/[emailAccountId]/assistant/constants.ts">

<violation number="1" location="apps/web/app/(app)/[emailAccountId]/assistant/constants.ts:66">
P2: The `|| lowerExample.includes(&quot;sender&quot;)` condition is too broad and will cause false matches. Strings like &quot;Forward to sender&quot; or &quot;Reply to sender&quot; will incorrectly return NOTIFY_SENDER color because &quot;sender&quot; matches first. Consider using only `lowerExample.includes(&quot;notify&quot;)` or a more specific combined check like `lowerExample.includes(&quot;notify sender&quot;)`.</violation>
</file>

Reply to cubic to teach it or ask questions. Re-run a review with @cubic-dev-ai review this PR

<Container className="mx-auto w-full max-w-[600px] p-0">
<Section className="p-8 text-center">
<Link href={baseUrl} className="text-[15px]">
<Img
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Dec 19, 2025

Choose a reason for hiding this comment

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

P2: Image source is hardcoded while baseUrl prop is available for configurable URLs. This inconsistency means the image will always point to production even when baseUrl is overridden (e.g., in development/staging environments). Consider using the baseUrl prop for consistency.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/resend/emails/cold-email-notification.tsx, line 34:

<comment>Image source is hardcoded while `baseUrl` prop is available for configurable URLs. This inconsistency means the image will always point to production even when `baseUrl` is overridden (e.g., in development/staging environments). Consider using the `baseUrl` prop for consistency.</comment>

<file context>
@@ -0,0 +1,89 @@
+          &lt;Container className=&quot;mx-auto w-full max-w-[600px] p-0&quot;&gt;
+            &lt;Section className=&quot;p-8 text-center&quot;&gt;
+              &lt;Link href={baseUrl} className=&quot;text-[15px]&quot;&gt;
+                &lt;Img
+                  src={&quot;https://www.getinboxzero.com/icon.png&quot;}
+                  width=&quot;40&quot;
</file context>
Fix with Cubic

Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Dec 19, 2025

Choose a reason for hiding this comment

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

P2: The || lowerExample.includes("sender") condition is too broad and will cause false matches. Strings like "Forward to sender" or "Reply to sender" will incorrectly return NOTIFY_SENDER color because "sender" matches first. Consider using only lowerExample.includes("notify") or a more specific combined check like lowerExample.includes("notify sender").

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/web/app/(app)/[emailAccountId]/assistant/constants.ts, line 66:

<comment>The `|| lowerExample.includes(&quot;sender&quot;)` condition is too broad and will cause false matches. Strings like &quot;Forward to sender&quot; or &quot;Reply to sender&quot; will incorrectly return NOTIFY_SENDER color because &quot;sender&quot; matches first. Consider using only `lowerExample.includes(&quot;notify&quot;)` or a more specific combined check like `lowerExample.includes(&quot;notify sender&quot;)`.</comment>

<file context>
@@ -53,12 +56,16 @@ export const ACTION_TYPE_ICONS = {
 export function getActionTypeColor(example: string): string {
   const lowerExample = example.toLowerCase();
 
+  if (lowerExample.includes(&quot;notify&quot;) || lowerExample.includes(&quot;sender&quot;)) {
+    return ACTION_TYPE_COLORS[ActionType.NOTIFY_SENDER];
+  }
</file context>
Suggested change
if (lowerExample.includes("notify") || lowerExample.includes("sender")) {
if (lowerExample.includes("notify")) {

✅ Addressed in 4e976a9

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

🧹 Nitpick comments (1)
apps/web/app/(app)/[emailAccountId]/assistant/AvailableActionsPanel.tsx (1)

24-24: Consider adding a tooltip for NOTIFY_SENDER.

While ActionSummaryCard includes a tooltip for this action, adding one here would provide consistent user guidance across the UI. Other actions like CALL_WEBHOOK and DIGEST have tooltips in this component.

🔎 Proposed addition
 const actionTooltips: Partial<Record<ActionType, string>> = {
   [ActionType.CALL_WEBHOOK]:
     "For developers: trigger external integrations by sending email data to a custom URL",
   [ActionType.DIGEST]:
     "Group emails together and receive them as a daily summary",
+  [ActionType.NOTIFY_SENDER]:
+    "Sends an automated notification from Inbox Zero (not from your email) informing the sender their email was filtered as cold outreach",
 };

Comment on lines 66 to 68
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 | 🟡 Minor

Keyword "sender" may be too broad for action type detection.

The condition checks for "sender" OR "notify" in the example string, but "sender" is a generic word that could appear in other action contexts (e.g., "reply to sender", "forward to sender"). This could cause false positives where non-NOTIFY_SENDER actions incorrectly match this condition.

Consider making the check more specific (e.g., "notify sender" as a phrase) or placing this condition lower in the priority chain to allow more specific action types to match first.

🔎 Suggested fix
- if (lowerExample.includes("notify") || lowerExample.includes("sender")) {
+ if (lowerExample.includes("notify") && lowerExample.includes("sender")) {
    return ACTION_TYPE_COLORS[ActionType.NOTIFY_SENDER];
  }

Or alternatively, check for the phrase "notify sender":

- if (lowerExample.includes("notify") || lowerExample.includes("sender")) {
+ if (lowerExample.includes("notify sender")) {
    return ACTION_TYPE_COLORS[ActionType.NOTIFY_SENDER];
  }
📝 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
if (lowerExample.includes("notify") || lowerExample.includes("sender")) {
return ACTION_TYPE_COLORS[ActionType.NOTIFY_SENDER];
}
if (lowerExample.includes("notify") && lowerExample.includes("sender")) {
return ACTION_TYPE_COLORS[ActionType.NOTIFY_SENDER];
}
🤖 Prompt for AI Agents
In apps/web/app/(app)/[emailAccountId]/assistant/constants.ts around lines 66 to
68, the condition treating any example containing "sender" as NOTIFY_SENDER is
too broad and can produce false positives; change the detection to match a more
specific phrase such as "notify sender" (or use word-boundary/regex checks for
the phrase) and/or move this branch lower in the priority order so more specific
actions (e.g., "reply to sender", "forward to sender") are matched first; update
the conditional accordingly to check for the full phrase or use a regex like
/\bnotify\s+sender\b/i and ensure ordering of checks prevents premature matches.

@elie222 elie222 merged commit 61bda77 into main Dec 19, 2025
12 of 13 checks passed
@elie222 elie222 deleted the feat/allow-process-read branch December 19, 2025 12:30
This was referenced Dec 19, 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.

1 participant

Comments