feat: email integration — IMAP sync, inbox, compose, contact emails, dashboard widget#20
Conversation
… (Phase A) Add contact_loyalty_programs table for managing cruise line, airline, and hotel loyalty memberships. Add universal booking fields (net_price_cents, non_refundable_deposit, cancellation_schedule_json) to activity_pricing, and cruise-specific fields (reservation_number, stateroom_category_code, onboard_credit_cents/currency) to custom_cruise_details. Wire import service to extract new fields from Traveltek API responses. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add loyalty programs API: controller, service, DTOs with PII access control, membership number normalization, and unique constraint handling - Add loyalty programs UI: contact detail section with dialog-based CRUD, 19 common provider suggestions, and tier level badges - Add cruise form fields: reservation number, stateroom category code, onboard credit with currency selector - Add cancellation schedule inline table editor on Booking & Pricing tab - Add agency pricing card with net price and non-refundable deposit - Wire audit system: entity type, sanitizer whitelist, Drizzle enum Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…migrations Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
# Conflicts: # apps/api/src/cruise-booking/services/import-booking.service.ts # packages/database/src/migrations/meta/_journal.json
# Conflicts: # packages/database/src/schema/index.ts
Resolve merge conflicts: keep both ClientPortalModule and PortalModule, use expanded imports in contacts.service, accept feature branch for all client portal files (real Supabase auth replacing mock auth). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The AuthProvider context expected signInWithOtp/signOut/getAccessToken
but useAuth() returns { user, loading, logout }. Updated the interface
to match since useAuthContext() is not consumed anywhere.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Next.js 15 requires useSearchParams() to be inside a Suspense boundary. Split LoginPage into wrapper + LoginPageContent. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Resolve conflict in travelers/page.tsx — take feature branch's profile editor over preview's PassengerInfoForm stub. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
New Email tab in Profile for IMAP/SMTP account configuration: - Email account CRUD with connection test - Display existing accounts with sync status - Signature editing link points to Preferences tab (not duplicated) - use-email-accounts.ts hook for TanStack Query Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ce footer Admin settings page with: - Tag-style allowed domains editor (empty = no restriction) - HTML compliance footer with live preview - Uses existing PATCH /agencies/:agencyId/settings endpoint Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…r, and email reader - Install DOMPurify for HTML email body sanitization - Create use-emails hook (folders, emails list, detail, sync mutation) - Convert /emails to redirect to /emails/inbox - Create inbox page with folder sidebar, email list, and reader pane - Create EmailReader with DOMPurify sanitization and attachment downloads - Create ContactMatchBanner for linked contact display - Fix unused import/variable in email-tab.tsx Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace "Coming Soon" placeholder with ContactEmailsSection that shows emails matched to the contact via the contactId filter parameter. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
P0: Make imapUid nullable for outbound emails, convert unique index to partial (WHERE imap_uid IS NOT NULL) to prevent collision on SMTP sends. P0: Fix TS strict-init errors on DTO classes (add ! assertions), remove unused imports/vars across email-accounts module. P1: Add unique partial index on email_attachments(email_id, imap_part_id) for attachment metadata dedupe on re-sync. P1: Stream attachment downloads with proper Content-Type/Disposition headers using NestJS StreamableFile instead of returning raw object. P1: Use @isemail() on send DTO address field for early validation. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…navigation Wrap email inbox page in DashboardLayout (was missing, causing top nav to disappear). Add Zustand store for email view state (folder, selected email, search) so users don't lose their position when navigating to other pages and returning. Fix BigInt serialization error from ImapFlow by wrapping uidValidity/uidNext/uid/size in Number() before storing in JSONB or integer columns. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…compatible with ON CONFLICT The partial unique index (WHERE imap_uid IS NOT NULL) could not be matched by Drizzle's ON CONFLICT target, causing every email upsert to fail silently. Changed to a regular unique index — PostgreSQL treats NULL as distinct, so outbound emails with NULL imap_uid won't conflict. Also added ImapFlow error event handler via createImapClient() helper to prevent unhandled socket timeout errors from crashing the Node process. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…rward, compose - Backend: PATCH flags endpoint, DELETE email endpoint, batch flags endpoint - Frontend: hover actions on email list (mark read/unread, star, delete) - Auto-mark as read when email is opened - Unread indicator dot on email list items - Reply/Reply All/Forward open compose dialog with pre-filled fields - New compose button in sidebar - Create Contact button navigates to contacts with pre-filled data - Compose dialog with To, Cc, Subject, Body fields Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Previously, when all recipients were filtered out by the non-production domain allowlist, the code only logged a warning but continued to call sendMail() with empty recipients. Now throws BadRequestException to prevent any send attempt. Also adds kaponline.com to allowed domains. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Unread email count badge on "Emails" nav link (60s polling) - Folder sidebar: create, rename, delete custom folders via IMAP - Move-to-folder dropdown on email list hover actions and reader toolbar - Backend: createFolder, renameFolder, deleteFolder, moveEmail endpoints - Protected system folders (Inbox, Sent, Drafts, Trash, Junk) cannot be renamed or deleted Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When lastUid equals uidNext-1 (no new messages), fetching UID range `lastUid+1:*` fails on some IMAP servers with "Command failed". Now checks uidNext before attempting the fetch to avoid unnecessary errors. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Route transactional emails through the assigned agent's SMTP account first, falling back to Resend on pre-delivery failures. This ensures agent emails appear in their Sent folder and come from their real address, improving deliverability and client experience. Key changes: - Add shared buildEmailBody() utility for unified signature/footer - Add sendRaw() lightweight SMTP method to SmtpSendService - Add findActiveAccountForUser() for deterministic account selection - Implement agent resolution waterfall (contact → trip → createdBy) - Wire EmailModule → EmailAccountsModule via forwardRef() - Double-send prevention: post-delivery DB failures don't trigger Resend - IMAP sync messageId dedup for SMTP-sent outbound emails - Remove inline footers from hardcoded templates (now via buildEmailBody) - Resend fallback uses verified domain for from, agent email as replyTo Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ents Contact Communications tab now shows ALL emails (agent IMAP + system/automation) merged into a unified timeline, with search, type filtering, and delivery status. System emails display even when no IMAP account is configured. Also includes inbox UI improvements: folder sidebar, contact match banner, move-to-folder dropdown, drag-and-drop config, and email list refinements. - Add useEmailLogs hook for system email logs - Add category field to EmailLogResponse shared type - Rewrite contact-emails-section with unified email view - Improve inbox folder sidebar, email list, and contact matching UI Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…emails - Wrap ContactEmailsSection in p-6 div for consistent margins with other tabs - Deduplicate emails in Communications tab: when an SMTP-sent email appears in both synced_emails and email_logs (matching messageId/providerMessageId), keep only the agent version (richer data with snippet, read status) - Simplify email count display Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add email preview dialog that lazy-fetches body on demand for both agent (IMAP) and system emails. Clickable email rows with keyboard accessibility. "Open in Inbox" navigates to /emails/inbox with the email pre-selected. Extract shared DOMPurify sanitizer. Add Recent Emails sidebar widget on contact detail page. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Shows recent INBOX emails with unread badge, click-to-navigate to inbox with email pre-selected. Quick tools: Compose, Open Inbox, and Sync button. Widget hides when no email account is configured. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
… emails Quick Create now includes "New Email" which opens compose on the inbox page. Clicking an email in the dashboard sidebar opens the preview dialog (same as contact emails tab) instead of navigating away. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Caution Review failedThe pull request is closed. ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (96)
📝 WalkthroughWalkthroughComprehensive email integration with IMAP/SMTP account configuration, on-demand sync, per-folder management, and compose/reply/forward; extends group bookings with documents and media tables; integrates emails with contacts via unified email views and contact matching; adds profile email account setup and settings for compliance footers and allowed domains. Changes
Estimated code review effort🎯 5 (Critical) | ⏱️ ~120 minutes Possibly related PRs
Poem
✨ Finishing Touches
🧪 Generate unit tests (beta)
|
Summary
Test plan
🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Enhancements