Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -77,4 +77,7 @@ docker-compose.override.yml
# cli logs
logs

coverage
coverage

# Memory bank (Cline AI documentation)
memory-bank/
8 changes: 8 additions & 0 deletions .idea/.gitignore

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/copilot.data.migration.agent.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/copilot.data.migration.ask.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/copilot.data.migration.ask2agent.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/copilot.data.migration.edit.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 12 additions & 0 deletions .idea/inbox-zero.iml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

28 changes: 28 additions & 0 deletions .idea/inspectionProfiles/Project_Default.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions .idea/modules.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/vcs.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

239 changes: 239 additions & 0 deletions Cline_Notes/outlook-deep-clean-plan.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,239 @@
# Outlook Deep-Clean Implementation Plan

## Overview
This document outlines the staged approach to add Outlook support to the deep-clean feature. The deep-clean feature currently only supports Gmail accounts.

## Current State
- **Status**: UI visible for both providers, backend only supports Gmail
- **Blocker**: Server action throws error for non-Google providers
- **Date Started**: January 28, 2025

## Architecture Context
The deep-clean feature uses:
- QStash for background processing
- AI/LLM for intelligent email classification
- Provider abstraction layer (`EmailProvider` interface)
- Redis for temporary caching
- PostgreSQL for persistent storage

## Implementation Stages

### Stage 1: Provider Abstraction Preparation 🔧
**Goal**: Set up foundation for multi-provider support

**Tasks**:
1. Create provider-agnostic email state constants
- Standard folder/label types (INBOX, ARCHIVE, UNREAD, etc.)
- Gmail label mappings
- Outlook folder mappings

2. Create Outlook folder helpers
- `apps/web/utils/outlook/folder.ts`
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot Oct 29, 2025

Choose a reason for hiding this comment

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

The Stage 1 task list points to apps/web/utils/outlook/folder.ts, but the actual helper file is apps/web/utils/outlook/folders.ts, so the documentation should use the correct plural path.

Prompt for AI agents
Address the following comment on Cline_Notes/outlook-deep-clean-plan.md at line 31:

<comment>The Stage 1 task list points to `apps/web/utils/outlook/folder.ts`, but the actual helper file is `apps/web/utils/outlook/folders.ts`, so the documentation should use the correct plural path.</comment>

<file context>
@@ -0,0 +1,239 @@
+   - Outlook folder mappings
+
+2. Create Outlook folder helpers
+   - `apps/web/utils/outlook/folder.ts`
+   - Outlook system folder operations
+   - `getOrCreateInboxZeroFolder()` equivalent
</file context>
Fix with Cubic

- Outlook system folder operations
- `getOrCreateInboxZeroFolder()` equivalent

3. Update `EmailProvider` interface
- Ensure all operations are abstracted
- Add missing methods if needed

**Files**:
- `apps/web/utils/email/constants.ts` (NEW)
- `apps/web/utils/outlook/folder.ts` (NEW/ENHANCE)
- `apps/web/utils/email/types.ts` (UPDATE)

---

### Stage 2: Server Action Refactoring 🔄
**Goal**: Make `cleanInboxAction` provider-agnostic

**Tasks**:
1. Remove Google-only provider check (lines 35-39)
2. Update label/folder creation to use provider abstraction
3. Update thread query logic to be provider-agnostic

**Files**:
- `apps/web/utils/actions/clean.ts`

---

### Stage 3: AI Analysis Provider Support 🤖
**Goal**: Ensure AI/static rules work for both providers

**Tasks**:
1. Update static rule checks
- Starred/flagged messages
- Sent messages
- Attachments (should work)
- Calendar/receipt detection

2. Verify AI analysis with Outlook messages
3. Update category-based filtering

**Files**:
- `apps/web/app/api/clean/route.ts`
- Helper functions

---

### Stage 4: Create Outlook Action Handler 📬
**Goal**: Implement Outlook equivalent of Gmail handler

**Tasks**:
1. Create `/api/clean/outlook/route.ts`
2. Implement folder operations for Outlook
3. Update QStash routing

**Files**:
- `apps/web/app/api/clean/outlook/route.ts` (NEW)
- `apps/web/app/api/clean/route.ts` (UPDATE)

---

### Stage 5: Redis & Database Updates 💾
**Goal**: Ensure storage works for both providers

**Tasks**:
1. Review Redis thread storage
2. Verify database models
3. Update undo/change actions

**Files**:
- `apps/web/utils/redis/clean.ts`
- `apps/web/utils/actions/clean.ts`

---

### Stage 6: UI & Error Handling 🎨
**Goal**: Ensure smooth user experience

**Tasks**:
1. Update error messages
2. Add Outlook-specific guidance
3. Test UI flow

**Files**:
- `apps/web/app/(app)/clean/` components

---

### Stage 7: Testing & Documentation ✅
**Goal**: Comprehensive validation

**Tasks**:
1. Integration testing
2. Performance testing
3. Documentation updates

---

## Key Differences: Gmail vs Outlook

| Feature | Gmail | Outlook |
|---------|-------|---------|
| Organization | Labels (multi) | Folders (single) |
| Archive | Remove INBOX label | Move to Archive folder |
| Mark Read | Remove UNREAD label | Set isRead flag |
| Categories | PROMOTIONS, SOCIAL | Focused/Other |
| Starred | STARRED label | Flagged status |

## Risk Mitigation

1. **Backward Compatibility**: Gmail functionality must remain unchanged
2. **Rate Limits**: Outlook Graph API has different limits
3. **Folder Structure**: Outlook is hierarchical, Gmail is flat
4. **Testing**: Real Outlook accounts needed

## Success Criteria

- ✅ Gmail users see no change
- ✅ Outlook users can run deep-clean
- ✅ Skip options work for both (starred, attachments, etc.)
- ✅ AI analysis works equally
- ✅ Undo operations work for both
- ✅ No security regressions

## Implementation Plan

**Phase 1** (Current): Stages 1-3
- Foundation and core abstraction
- Make server actions provider-agnostic
- Update AI analysis

**Phase 2**: Stages 4-5
- Outlook-specific handler
- Storage updates

**Phase 3**: Stages 6-7
- Polish and testing
- Documentation

## Progress Tracking

- [x] Stage 1: Provider Abstraction Preparation ✅ COMPLETE
- [x] Stage 2: Server Action Refactoring ✅ COMPLETE
- [x] Stage 3: AI Analysis Provider Support ✅ COMPLETE
- [ ] Stage 4: Create Outlook Action Handler (NEXT)
- [ ] Stage 5: Redis & Database Updates
- [ ] Stage 6: UI & Error Handling
- [ ] Stage 7: Testing & Documentation

## Completed Work (January 28, 2025)

### Phase 1: Foundation & Core Abstraction (Stages 1-3)

**Stage 1: Provider Abstraction Preparation**
- ✅ Created `apps/web/utils/email/constants.ts` with provider-agnostic email state constants
- ✅ Mapped Gmail labels and Outlook folders to common concepts
- ✅ Added Outlook folder helper functions to `apps/web/utils/outlook/folders.ts`:
- `getOrCreateInboxZeroFolder()` - Creates InboxZero tracking folders
- `moveMessageToFolder()` - Moves messages between folders
- `markMessageAsRead()` - Sets read/unread status
- `flagMessage()` - Flags/stars messages
- `getWellKnownFolderId()` - Gets standard Outlook folder IDs

**Stage 2: Server Action Refactoring**
- ✅ Removed Google-only provider check from `cleanInboxAction`
- ✅ Updated error messages to be provider-agnostic ("label/folder" instead of "label")
- ✅ Modified thread query to use `labelId` parameter (works for both Gmail and Outlook)
- ✅ Added provider detection for inbox vs folder selection

**Stage 3: AI Analysis Provider Support**
- ✅ Updated static rule checks in `/api/clean/route.ts` to be provider-agnostic:
- `isStarred()` - Checks both Gmail STARRED label and Outlook isFlagged property
- `isSent()` - Works with both providers' SENT indicators
- `hasAttachments()` - Already provider-agnostic
- ✅ Updated category filtering to gracefully handle Gmail-specific categories
- ✅ Added `isFlagged` property to `ParsedMessage` type for Outlook support

**Key Changes Made:**
1. New file: `apps/web/utils/email/constants.ts` (provider abstraction constants)
2. Enhanced: `apps/web/utils/outlook/folders.ts` (InboxZero folder helpers)
3. Modified: `apps/web/utils/actions/clean.ts` (removed provider restriction)
4. Modified: `apps/web/app/api/clean/route.ts` (provider-agnostic rules)
5. Modified: `apps/web/utils/types.ts` (added isFlagged property)

**Status:** Gmail functionality preserved, foundation ready for Outlook implementation

## Related Files

### Core Clean Implementation
- `apps/web/utils/actions/clean.ts` - Server actions
- `apps/web/app/api/clean/route.ts` - Main processing endpoint
- `apps/web/app/api/clean/gmail/route.ts` - Gmail action handler

### Provider Abstraction
- `apps/web/utils/email/provider.ts` - Provider factory
- `apps/web/utils/email/types.ts` - EmailProvider interface
- `apps/web/utils/email/google.ts` - Gmail implementation
- `apps/web/utils/email/microsoft.ts` - Outlook implementation

### Supporting Files
- `apps/web/utils/redis/clean.ts` - Redis caching
- `apps/web/utils/ai/clean/ai-clean.ts` - AI analysis
- `apps/web/prisma/schema.prisma` - Database models

## Notes

- Outlook Graph API documentation: https://learn.microsoft.com/en-us/graph/api/resources/mail-api-overview
- Gmail API documentation: https://developers.google.com/gmail/api
- QStash rate limiting configured per user to avoid conflicts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@ import { TypographyH3 } from "@/components/Typography";
import { useStep } from "@/app/(app)/[emailAccountId]/clean/useStep";
import { ButtonListSurvey } from "@/components/ButtonListSurvey";
import { CleanAction } from "@prisma/client";
import { Button } from "@/components/ui/button";

export function ActionSelectionStep() {
const { onNext } = useStep();
const { onNext, onPrevious } = useStep();
const [_, setAction] = useQueryState(
"action",
parseAsStringEnum([CleanAction.ARCHIVE, CleanAction.MARK_READ]),
Expand Down Expand Up @@ -39,6 +40,12 @@ export function ActionSelectionStep() {
]}
onClick={(value) => onSetAction(value as CleanAction)}
/>

<div className="mt-6">
<Button variant="outline" onClick={onPrevious}>
Back
</Button>
</div>
</div>
);
}
Loading