원클릭으로
email-processing
Email, inbox, Outlook, Microsoft 365, mail, messages, fetch emails, search emails, draft, reply, email processing (project)
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
메뉴
Email, inbox, Outlook, Microsoft 365, mail, messages, fetch emails, search emails, draft, reply, email processing (project)
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
SOC 직업 분류 기준
brief, summary, daily, weekly, end of day, EOD, digest, morning, recap, meeting prep, what's due, status update, review
Interactive web tasks, browser login, click, scroll, form interaction, authenticated sessions, Playwright MCP (project)
Query and summarize Claude Code terminal session history
fact, decision, architecture, knowledge, permanent, remember forever, always know, decisions, outcomes, lessons learned
GitHub CLI, docker commands, git operations, curl, native CLI tools, gh issue, gh pr, container, repository, API calls (project)
Create and manage Overleaf LaTeX documents. Use when transcribing handwritten work to LaTeX, creating academic documents, homework solutions, problem sets, or any LaTeX/Overleaf operations. Handles PDF/image to LaTeX conversion. Homework transcription workflow.
| name | email-processing |
| description | Email, inbox, Outlook, Microsoft 365, mail, messages, fetch emails, search emails, draft, reply, email processing (project) |
| triggers | ["email","inbox","outlook","mail","messages","draft","reply"] |
| requires | {"scripts":["email_processor.py","microsoft_graph.py"],"config":["skills.entries.email-processing.enabled"]} |
| os | ["linux","darwin"] |
Outlook email integration via Microsoft Graph API. Fetch, search, and manage emails - including creating drafts (but NEVER sending automatically).
# Setup (one-time)
python microsoft_graph.py configure CLIENT_ID SECRET --tenant TENANT_ID
python microsoft_graph.py auth-url # Follow the URL to authenticate
# Fetch new emails
python email_processor.py fetch
# Search emails
python email_processor.py search "budget report"
# Create a draft (NEVER sends automatically)
python email_processor.py draft --to "user@example.com" --subject "Subject" --body "Body text"
The email system creates DRAFTS only - it NEVER sends emails automatically.
When the user asks to "send an email" or "reply to X":
create_draft()This is a deliberate safety feature. the user must manually send all emails.
Before using email features, Microsoft Graph must be configured:
Required permissions:
Mail.Read - Read user's emailsMail.ReadWrite - Create draftsoffline_access - Maintain access (refresh tokens)python microsoft_graph.py configure CLIENT_ID CLIENT_SECRET --tenant TENANT_ID
python microsoft_graph.py auth-url
# Visit the URL, sign in, copy the code from redirect URL
python microsoft_graph.py authenticate CODE
python microsoft_graph.py status # Verify: "Authenticated: Yes"
from email_processor import fetch_new_emails
# Fetch new emails since last sync
result = fetch_new_emails(limit=50)
# Returns: {success, fetched, stored, skipped, emails}
if result['success']:
for email in result['emails']:
print(f"{email['sender']}: {email['subject']}")
from email_processor import search_emails, get_email
# Search by subject, sender, or body content
results = search_emails("project update", days=7)
# Get full email content by ID
email = get_email(42)
print(email['body_full']) # Full email body
from email_processor import list_emails, get_actionable_emails
# List recent emails
recent = list_emails(days=7, limit=50)
# Get actionable emails (questions, requests, deadlines)
actionable = get_actionable_emails()
for email in actionable:
print(f"[!] {email['sender']}: {email['subject']}")
from email_processor import create_draft
# Create a draft - does NOT send
result = create_draft(
to="user@example.com, other@example.com", # Comma-separated
subject="Re: Project Update",
body="Here's the update you requested...",
cc="manager@example.com" # Optional
)
if result['success']:
print(f"Draft created: {result['draft_id']}")
print(f"View in Outlook: {result['web_link']}")
print("NOTE: Draft must be sent manually from Outlook!")
# Fetch new emails from Outlook
python email_processor.py fetch --limit 50
# Search emails
python email_processor.py search "query" --days 7
# List recent emails
python email_processor.py list --days 7 --limit 50
python email_processor.py list --actionable # Only actionable emails
# Get full email by ID
python email_processor.py get 42
# Create a draft (DOES NOT SEND)
python email_processor.py draft --to "user@example.com" --subject "Subject" --body "Body text" --cc "cc@example.com"
Emails are automatically flagged as "actionable" based on content:
| Category | Detected Phrases |
|---|---|
| Requests | please, could you, would you, need you to |
| Urgency | urgent, ASAP, by tomorrow, deadline |
| Questions | ?, what do you think, your thoughts |
| Responses | let me know, get back to me, waiting for |
| Meetings | schedule a, set up a meeting, calendar invite |
# In CLI output: [!] indicates actionable
# [!] [ 42] 2026-01-13 | John <john@ex.com> | Please review...
# [ 43] 2026-01-13 | Jane <jane@ex.com> | FYI: Notes from...
| User Says | Action |
|---|---|
| "Check my email" | python email_processor.py fetch && python email_processor.py list --actionable |
| "Any urgent emails?" | get_actionable_emails() |
| "Search for email about X" | search_emails("X") |
| "Show me that email from John" | search_emails("John") then get_email(ID) |
| "Reply to that email" / "Send email" | create_draft(...) + tell the user "Draft created, please send from Outlook" |
| "What did Sarah say about the budget?" | search_emails("Sarah budget") |
Actionable emails appear in daily briefs:
from brief import daily_brief
brief = daily_brief()
# Includes "## Actionable Emails" section
The scheduler can auto-fetch emails:
# Check scheduler configuration
python scheduler.py --config
# email_sync_interval_hours: 2
# Manual sync
python scheduler.py --run email
Emails are stored in the emails table:
| Column | Description |
|---|---|
| id | Database ID |
| message_id | Outlook message ID (unique) |
| subject | Email subject |
| sender | "Name " format |
| recipients | JSON array of recipient emails |
| body_preview | First 500 chars of body |
| body_full | Complete email content |
| is_actionable | Auto-detected actionability |
| action_taken | Notes on action taken |
| received_at | When email was received |
| processed_at | When PCP processed it |
result = fetch_new_emails()
if not result['success']:
error = result['error']
if 'not configured' in error.lower():
print("Run: python microsoft_graph.py configure ...")
elif 'not authenticated' in error.lower():
print("Run: python microsoft_graph.py auth-url")
else:
print(f"API Error: {error}")
Remember: Draft-only policy. Never send emails automatically. Always inform the user that a draft was created and needs manual sending.