Tech

Smart Email Triage dengan AI — Inbox Zero Tanpa Sakit Kepala

Filter email penting dari spam dalam sekejap. AI triage yang belajar preferensi kamu.

👤 Zainul Fanani📅 11 Maret 2026⏱ 1 min read

📎 Source:smart-email-triage.md — view on GitHub & star ⭐

Smart Email Triage

AI-powered inbox management that auto-sorts, prioritizes, and drafts responses.


📧 Email Classification Flow

A New Email Arrives  B AI Classifier
A New Email Arrives B AI Classifier
}}%% flowchart TD A📨 New Email Arrives --> B🤖 AI Classifier style A fill:#e1f5fe,stroke:#01579b,stroke-width:2px style B fill:#f3e5f5,stroke:#6a1b9a,stroke-width:2px

B --> C{Category?} style C fill:#fff3e0,stroke:#e65100,stroke-width:2px C -->|🔴 URGENT| D[⭐ Star Message] C -->|📰 NEWSLETTER| E[📂 Archive + Label] C -->|💬 FOLLOW-UP| F[📝 Add to Tasks] C -->|📢 FYI| G[👁️ Mark as Read] C -->|🗑️ SPAM| H[🚫 Delete/Mute] style D fill:#ffcdd2,stroke:#c62828,stroke-width:2px style E fill:#c8e6c9,stroke:#2e7d32,stroke-width:2px style F fill:#fff8e1,stroke:#f57f17,stroke-width:2px style G fill:#e1f5fe,stroke:#0288d1,stroke-width:2px style H fill:#cfd8dc,stroke:#455a64,stroke-width:2px D --> I[🔔 Send Alert] E --> J[✅ Done] F --> K[💡 Draft Reply] G --> J H --> J style I fill:#ffccbc,stroke:#d84315,stroke-width:2px style J fill:#a5d6a7,stroke:#388e3c,stroke-width:2px style K fill:#e1bee7,stroke:#8e24aa,stroke-width:2px K --> J I --> J'}

🔄 Email Triage Sequence

participant Cron as Cron 30min
participant Cron as Cron 30min
}}%% sequenceDiagram participant Cron as Cron (30min) participant Script as Triage Script participant AI as AI Classifier participant Gmail as Gmail API participant TG as Telegram

Cron->>Script: Trigger processing Script->>Gmail: Fetch unread emails Gmail-->>Script: List of messages loop Each Email Script->>AI: Classify email content AI->>AI: Analyze sender, subject, body AI-->>Script: Category + Action alt URGENT Script->>Gmail: Add STARRED label Script->>TG: Send urgent alert 🚨 else NEWSLETTER Script->>Gmail: Archive + Add label else FOLLOW-UP Script->>Script: Add to task list Script->>Gmail: Star message else FYI Script->>Gmail: Mark as read end end Script->>Script: Update stats'}

📊 Daily Digest Architecture

A 800 AM Daily  B Fetch ImportantbrStarredUnread
A 800 AM Daily B Fetch ImportantbrStarredUnread
}}%% flowchart LR A⏰ 8:00 AM Daily --> B📧 Fetch Important
Starred/Unread
style A fill:#ffebee,stroke:#c62828,stroke-width:2px style B fill:#e3f2fd,stroke:#1565c0,stroke-width:2px

B --> C[📊 Aggregate Stats] style C fill:#f3e5f5,stroke:#6a1b9a,stroke-width:2px C --> D{Priority<br/>Emails?} style D fill:#fff3e0,stroke:#e65100,stroke-width:2px D -->|Yes| E[⭐ List Top 5<br/>Important] D -->|No| F[✓ No urgent items] style E fill:#ffcdd2,stroke:#d32f2f,stroke-width:2px style F fill:#c8e6c9,stroke:#388e3c,stroke-width:2px E --> G[📝 Generate<br/>Digest Message] F --> G style G fill:#e1bee7,stroke:#7b1fa2,stroke-width:2px G --> H[📤 Send to Telegram] H --> I[👤 User Receives<br/>Morning Briefing] style H fill:#b3e5fc,stroke:#0288d1,stroke-width:2px style I fill:#a5d6a7,stroke:#43a047,stroke-width:2px'}

Overview

Inbox overflowing? This automation:

  • Classifies emails by urgency (urgent, newsletter, follow-up, spam)
  • Auto-archives low-priority mail
  • Stars important messages
  • Drafts quick replies for common requests
  • Sends daily digest of what needs attention

Before: 200+ unread emails, important messages buried
After: Inbox zero, urgent items flagged, newsletters archived

Architecture

[New email arrives] ↓ [AI classification] - Urgent (client, boss, deadline) - Newsletter (marketing, updates) - Follow-up (waiting for reply) - FYI (info only) - Spam (unwanted) ↓ [Auto-actions] - Urgent → Star + Notify - Newsletter → Archive + Label - Follow-up → Add to task list - FYI → Mark read ↓ [Draft responses] - Common requests - Meeting scheduling - Status updates ↓ [Daily digest] - Summary to Telegram - Action items highlighted

Prerequisites

  • OpenClaw installed
  • gog CLI (Gmail access)
  • Telegram bot (for notifications)

Step 1: Email Classifier

scripts/email-triage/classify.py:

#!/usr/bin/env python3 """ Classify emails using AI Usage: python3 classify.py <email_json> """ import json import sys def classify_email(email_data): """Use AI to classify email""" prompt = f"""Classify this email into one category: From: {email_data['from']} Subject: {email_data['subject']} Body: {email_data['body'][:500]} Categories: 1. URGENT - Needs immediate attention (client, boss, deadline, problem) 2. NEWSLETTER - Marketing, updates, subscriptions 3. FOLLOW_UP - Waiting for your reply or follow-up needed 4. FYI - Information only, no action needed 5. SPAM - Unwanted, promotional Respond in JSON format: {{ "category": "urgent|newsletter|follow_up|fyi|spam", "confidence": 0-100, "reason": "why this category", "action": "star|archive|reply|read|delete", "priority": "high|medium|low", "suggested_response": "draft reply if applicable" }}""" # Call AI model result = call_ai_model(prompt) return json.loads(result) def main(): # Read email from stdin or file if len(sys.argv) > 1: with open(sys.argv[1]) as f: email = json.load(f) else: email = json.load(sys.stdin) classification = classify_email(email) print(json.dumps(classification, indent=2)) if __name__ == "__main__": main()

Step 2: Fetch and Process

scripts/email-triage/process-inbox.sh:

#!/bin/bash # Process inbox and auto-triage emails LOG_FILE="/var/log/email-triage.log" log() { echo "[$(date)] $1" | tee -a "$LOG_FILE" } process_emails() { log "🔍 Checking inbox..." # Fetch unread emails emails=$(gog gmail search "is:unread" --max=50 --json) count=$(echo "$emails" | python3 -c "import sys,json; print(len(json.load(sys.stdin)))") log "📧 Found $count unread emails" # Process each email echo "$emails" | python3 -c " import sys import json import subprocess emails = json.load(sys.stdin) results = {'urgent': 0, 'newsletter': 0, 'follow_up': 0, 'fyi': 0, 'spam': 0} for email in emails: # Classify result = subprocess.run( ['python3', 'scripts/email-triage/classify.py'], input=json.dumps(email), capture_output=True, text=True ) classification = json.loads(result.stdout) category = classification['category'] results[category] += 1 # Take action msg_id = email['id'] action = classification['action'] if action == 'star': subprocess.run(['gog', 'gmail', 'modify', msg_id, '--add-label', 'STARRED']) elif action == 'archive': subprocess.run(['gog', 'gmail', 'modify', msg_id, '--remove-label', 'INBOX']) elif action == 'read': subprocess.run(['gog', 'gmail', 'modify', msg_id, '--remove-label', 'UNREAD']) print(f'Processed: {email[\"subject\"][:50]}... → {category}') print(json.dumps(results)) " } # Run processing process_emails log "✅ Processing complete"

Step 3: Daily Digest

scripts/email-triage/daily-digest.py:

#!/usr/bin/env python3 """ Generate daily email digest Usage: python3 daily-digest.py """ import subprocess import json from datetime import datetime def fetch_important_emails(): """Fetch starred/important emails""" result = subprocess.run( ["gog", "gmail", "search", "is:starred OR is:important", "--max=20", "--json"], capture_output=True, text=True ) return json.loads(result.stdout) def fetch_todays_emails(): """Fetch today's emails""" result = subprocess.run( ["gog", "gmail", "search", "newer_than:1d", "--max=50", "--json"], capture_output=True, text=True ) return json.loads(result.stdout) def generate_digest(): """Generate digest message""" important = fetch_important_emails() today = fetch_todays_emails() message = f"📧 *Email Digest - {datetime.now().strftime('%A, %d %B')}*\n\n" # Important emails if important: message += f"⭐ *Important ({len(important)}):*\n" for email in important[:5]: sender = email['from'].split('<')[0].strip() subject = email['subject'][:40] message += f"• {subject} - _{sender}_\n" message += "\n" # Today's summary message += f"📊 *Today's Summary:*\n" message += f"• Total received: {len(today)}\n" message += f"• Important: {len(important)}\n" message += f"• Need reply: {len([e for e in today if 'Re:' not in e['subject']])}\n" return message def send_to_telegram(message): """Send digest to Telegram""" import os import requests token = os.getenv("TELEGRAM_BOT_TOKEN") chat_id = os.getenv("TELEGRAM_CHAT_ID") url = f"https://api.telegram.org/bot{token}/sendMessage" requests.post(url, data={ "chat_id": chat_id, "text": message, "parse_mode": "Markdown" }) if __name__ == "__main__": digest = generate_digest() print(digest) send_to_telegram(digest)

Step 4: Auto-Reply Drafts

scripts/email-triage/draft-replies.py:

#!/usr/bin/env python3 """ Draft replies for common email types """ import json import subprocess def draft_reply(email, classification): """Generate draft reply using AI""" prompt = f"""Draft a professional email reply: Original email: From: {email['from']} Subject: {email['subject']} Body: {email['body'][:300]} Category: {classification['category']} Draft a concise, professional reply. Keep it brief but helpful.""" reply = call_ai_model(prompt) return reply def create_draft(email_id, reply_body): """Create Gmail draft""" subprocess.run([ "gog", "gmail", "draft", "--reply-to", email_id, "--body", reply_body ]) # Usage: Process emails marked for reply

Step 5: Complete Setup

scripts/email-triage/setup.sh:

#!/bin/bash # Setup email triage automation echo "📧 Setting up Smart Email Triage..." # Create directories mkdir -p scripts/email-triage mkdir -p /var/log # Make scripts executable chmod +x scripts/email-triage/*.py chmod +x scripts/email-triage/*.sh # Add cron jobs echo "Adding cron schedules..." ( crontab -l 2>/dev/null cat << 'EOF' # Email triage - every 30 minutes */30 * * * * /root/.openclaw/workspace/scripts/email-triage/process-inbox.sh >> /var/log/email-triage.log 2>&1 # Daily digest - 8 AM 0 8 * * * /usr/bin/python3 /root/.openclaw/workspace/scripts/email-triage/daily-digest.py >> /var/log/email-triage.log 2>&1 EOF ) | crontab - echo "✅ Setup complete!" echo "📊 Check logs: tail -f /var/log/email-triage.log"

Example Output

Telegram Digest:

📧 *Email Digest - Monday, 08 March* ⭐ *Important (3):* • Project proposal feedback needed - _Client ABC_ • Q1 review meeting tomorrow - _Boss_ • Invoice payment reminder - _Finance_ 📊 *Today's Summary:* • Total received: 23 • Important: 3 • Need reply: 7

Processing Log:

[2026-03-08 09:00:01] 🔍 Checking inbox... [2026-03-08 09:00:03] 📧 Found 12 unread emails Processed: Newsletter: March Updates → newsletter Processed: RE: Project Timeline → follow_up Processed: 🚨 URGENT: Server Down → urgent Processed: Your Amazon order... → fyi [2026-03-08 09:00:15] ✅ Processing complete

Advanced Features

Sender-based Rules

VIP_SENDERS = ['boss@company.com', 'client@vip.com'] def check_vip(email): if any(vip in email['from'] for vip in VIP_SENDERS): return {'category': 'urgent', 'action': 'star'}

Thread Tracking

def is_follow_up(email): # Check if email is part of existing thread if 'Re:' in email['subject'] or email.get('threadId'): return True

Conclusion

You now have automated email management that:

  • ✅ Classifies emails with AI
  • ✅ Auto-archives newsletters
  • ✅ Stars urgent messages
  • ✅ Sends daily digests

Next Steps:

  • Add calendar integration for meeting emails
  • Build unsubscribe automation
  • Create email analytics dashboard

Tutorial created for OpenClaw Sumopod

Ada Pertanyaan? Yuk Ngobrol!

Butuh bantuan setup OpenClaw, konsultasi IT, atau mau diskusi project engineering? Book a call langsung — gratis.

Book a Call — Gratis

via Cal.com • WITA (UTC+8)

F

Zainul Fanani

Founder, Radian Group. Engineering & tech enthusiast.

Radian Group

Engineering Excellence Across Indonesia

Perusahaan

  • CV Radian Fokus Mandiri — Balikpapan
  • PT UNO Solusi Teknik — Balikpapan
  • PT Reka Formasi Elektrika — Jakarta
  • PT Raya Fokus Solusi — Sidoarjo
© 2026 Radian Group. All rights reserved.