assistant-skills/email-to-expense/SKILL.md

3.6 KiB

name description
email-to-expense Process emails from a Gmail label into work expenses. Opens Gmail via browser automation, iterates through emails in the "expense" label, saves each as PDF, extracts metadata, and logs them to MongoDB via the log-work-expense skill. Triggers when user mentions: - "process my expense emails" - "email to expense" - "triage my expense label" - "process expense label"

Email to Expense

Pulls emails from Gmail's "expense" label, saves them as PDFs, extracts metadata, and inserts them into wip.work_expenses.

Prerequisites

  • Browser tool available (openclaw browser)
  • User's Gmail must be logged in (use profile="user")
  • log-work-expense skill scripts accessible at ~/notes/skills/log-work-expense/scripts/

Flow

1. Open Gmail with expense label

Open Gmail filtered to the "expense" label using the user's browser profile:

URL: https://mail.google.com/mail/u/0/#label/expense

If the label name has spaces or special characters, URL-encode it. The label may also be accessed as "2 expense" — adjust accordingly.

Take a snapshot to see how many emails are in the list. Note the email count.

2. Iterate through each email

For each email in the label (oldest first to maintain order):

  1. Click the email to open it
  2. Snapshot the open email to extract metadata:
    • Date — from the email header (parse the displayed date string)
    • Sender — from the "From" field
    • Subject — from the subject line
  3. Save as PDF — Use the browser's print-to-PDF functionality:
    • Use action="pdf" if available, or trigger Ctrl+P and save to a temp directory
    • Save to /tmp/email_expense_<index>.pdf
  4. Upload PDF to S2 — Use the S2 upload endpoint from TOOLS.md:
    curl -X POST https://api.connorrhodes.com/agent/s2_upload \
      -H "x-api-key: LT6CXiLT5cEApfqtThz17bENr6OLp804FepOMqa1tZkfTGXiiCcSFlupl6gaYeX" \
      -F "file=@/tmp/email_expense_<index>.pdf"
    
    Collect the returned S2 URL.
  5. Return to the email list — Go back to the label view

3. Classify each expense

After collecting all emails, classify each one:

Known merchants (auto-classify):

Sender / Keyword Type Default Account
DoorDash meal (ask user)
Uber Eats meal (ask user)
Amazon other (ask user)

For unknown senders, ask the user to classify:

  • Type: meal, mileage, other, professional-development, software, etc.
  • Account: the work account to bill against

4. Insert into MongoDB

For each classified email, run the existing log_expense.py script:

uv run --with pymongo ~/notes/skills/log-work-expense/scripts/log_expense.py \
  <type> <account> <date> "<note>" <s2_url>
  • type: meal, mileage, or other
  • account: from classification step
  • date: parsed from the email header (YYYY-MM-DD format)
  • note: include sender and subject for context, e.g. "DoorDash - order confirmation"
  • s2_url: the uploaded PDF URL

5. Confirm

Show a summary table of all processed expenses:

  • Sender | Date | Type | Account | Status

6. Cleanup

  • Remove local PDF files from /tmp/
  • Optionally archive/remove the processed label from Gmail (ask user first)

Notes

  • Always ask the user to confirm before inserting expenses into the database
  • If an email doesn't look like an expense (no receipt, no order confirmation, etc.), skip it and note it
  • The Gmail label URL format: https://mail.google.com/mail/u/0/#label/<labelname>
  • For labels with spaces, the URL typically uses the raw label name