Claude-skill-registry dashboard-mail

V1.0 - Expert guidance for the Dashboard Mail module supporting Outlook, Gmail, and custom IMAP providers.

install
source · Clone the upstream repo
git clone https://github.com/majiayu000/claude-skill-registry
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/dashboard-mail" ~/.claude/skills/majiayu000-claude-skill-registry-dashboard-mail && rm -rf "$T"
manifest: skills/data/dashboard-mail/SKILL.md
source content

Dashboard Mail Module

ALWAYS: Log This Interaction

After completing work using this skill, append to

History/{YYYY-MM-DD}.md
:

## {HH:MM} - {Action Taken}
{One-line summary of what was done}

Mail integration module for aggregating multiple email accounts into a unified dashboard widget and page.

Architecture

src/modules/mail/
├── actions.ts              # Server actions (CRUD for accounts)
├── types.ts                # TypeScript types and utilities
├── index.ts                # Module exports
├── components/
│   ├── mail-widget.tsx     # Dashboard widget (compact)
│   ├── mail-list.tsx       # Message list view
│   ├── mail-item.tsx       # Individual message row
│   ├── account-tabs.tsx    # Account switcher tabs
│   ├── account-card.tsx    # Account display card
│   └── bulk-action-bar.tsx # Bulk action toolbar
└── lib/
    ├── outlook-client.ts   # Microsoft Graph API client
    ├── gmail-client.ts     # Gmail API client (placeholder)
    ├── imap-client.ts      # Custom IMAP client (placeholder)
    ├── token-manager.ts    # Encrypted credential storage
    ├── cache.ts            # Redis caching layer
    └── rate-limiter.ts     # API rate limiting

src/app/mail/
├── page.tsx                # Full mail page
└── settings/
    └── page.tsx            # Account management UI

Database Schema

Tables

mail_account_settings
- Per-user account configurations

ColumnTypeDescription
iduuidPrimary key
user_iduuidFK to auth.users
providertext
outlook
,
gmail
, or
imap
account_nametextDisplay name (e.g., "Work Gmail")
email_addresstextAccount email
is_enabledbooleanActive flag
sync_frequency_minutesintegerPolling interval (min 1)

mail_oauth_tokens
- Encrypted credentials (AES-256-GCM)

ColumnTypeDescription
account_iduuidFK to mail_account_settings
encrypted_access_tokentextEncrypted OAuth/IMAP password
encrypted_refresh_tokentextOAuth refresh token (nullable)
ivtextInitialization vector
auth_tagtextGCM authentication tag
token_expires_attimestamptzToken expiry (OAuth only)

Known Schema Gap

IMAP needs additional columns for custom server settings:

  • imap_host
    (text) - Server hostname
  • imap_port
    (integer) - Server port (default 993)

Currently IMAP falls back to env vars

IMAP_HOST
,
IMAP_PORT
which is a placeholder workaround.

Providers

ProviderStatusAuth MethodAPI
OutlookImplementedOAuth 2.0Microsoft Graph
GmailPlaceholderOAuth 2.0Gmail API
IMAPPlaceholderPasswordIMAP protocol

Outlook OAuth Setup

Required env vars:

GRAPH_CLIENT_ID=
GRAPH_CLIENT_SECRET=
GRAPH_REDIRECT_URI=

Gmail OAuth Setup

Required env vars:

GMAIL_CLIENT_ID=
GMAIL_CLIENT_SECRET=
GMAIL_REDIRECT_URI=

IMAP Setup (Placeholder)

Current env vars (temporary until DB columns added):

IMAP_HOST=
IMAP_USER=
IMAP_PASS=
IMAP_PORT=993

Key Types

type MailProvider = "outlook" | "gmail" | "imap";

interface MailAccount {
  id: string;
  provider: MailProvider;
  accountName: string;
  emailAddress: string;
  isEnabled: boolean;
  syncFrequencyMinutes: number;
}

interface MailMessage {
  id: string;
  subject: string;
  from: MailAddress;
  receivedAt: Date;
  isRead: boolean;
  preview: string;
}

type BulkActionType = "markRead" | "markUnread" | "moveToJunk" | "delete";

Server Actions

ActionDescription
getMailAccounts()
List user's configured accounts
createMailAccount(input)
Add new account
updateMailAccount(id, input)
Modify account settings
deleteMailAccount(id)
Remove account and tokens
getMailSummary()
Aggregated unread counts
getMailMessages(accountId)
Fetch messages for account
performBulkAction(request)
Execute bulk operations

Caching

Redis caching via Upstash with keys:

  • mail:summary:{userId}
    - Account summaries
  • mail:messages:{accountId}:{folder}
    - Message lists
  • mail:account:{accountId}
    - Account details

Security

  • Tokens encrypted with AES-256-GCM using
    MAIL_ENCRYPTION_KEY
  • Each token has unique IV and auth tag
  • RLS policies restrict access to owner's data only
  • Refresh tokens stored separately with own IV/auth tag

Settings UI

Located at

/mail/settings
:

  • Add account: Select provider → Enter name/email → OAuth or credential flow
  • Toggle accounts on/off
  • Delete accounts with confirmation dialog
  • Provider dropdown: Gmail, Outlook, IMAP (Custom)

TODO

  1. Add
    imap_host
    and
    imap_port
    columns to
    mail_account_settings
  2. Update settings form to collect IMAP server details when provider is "imap"
  3. Implement Gmail client
  4. Implement IMAP client using
    imap
    npm package
  5. Add OAuth callback routes for Gmail