Back to Tools
Script

Obsidian Gmail

Sync labeled Gmail emails to your Obsidian vault as searchable markdown notes

Overview

The Obsidian Gmail script automatically syncs your labeled Gmail emails to your Obsidian vault as formatted markdown notes. It uses Gmail's IMAP interface with OAuth 2.0 for secure authentication, including support for Google Workspace SSO.

What You'll Get

  • Automatic Email Ingestion - Labeled emails are saved as markdown in your vault
  • Deduplication - Never creates duplicate notes; updates in-place when content changes
  • Rich Metadata - YAML frontmatter with sender, recipients, date, labels, and Gmail link
  • Organized Structure - Emails organized by year and quarter (e.g., Emails/2025/Q425/)
  • Slack Thread Support - Special handling for Slack notification emails

How It Works

  1. Label Emails - Apply a "Save" or "AI/Ingest" label to emails you want to capture
  2. Run the Script - The script fetches labeled emails via IMAP
  3. Convert to Markdown - Emails are converted to clean markdown with frontmatter
  4. Save to Obsidian - Notes are saved to your vault's Emails folder

Installation

Ready to set up Obsidian Gmail?

This setup requires Gmail OAuth credentials and takes about 10-15 minutes. You'll need to create a Google Cloud project with IMAP access.

Usage

Basic Usage

Run the script to sync emails with the "Save" label:

python3 ~/scripts/ai_scripts/imap_ingest_md_only.py

Command Line Options

# Sync with specific labels
python3 ~/scripts/ai_scripts/imap_ingest_md_only.py --labels "Save" "Important"

# Sync emails from the last 30 days
python3 ~/scripts/ai_scripts/imap_ingest_md_only.py --since 30d

# Dry run (show what would be synced without creating files)
python3 ~/scripts/ai_scripts/imap_ingest_md_only.py --dry-run

# Limit to 100 emails
python3 ~/scripts/ai_scripts/imap_ingest_md_only.py --max 100

# Use a different vault
python3 ~/scripts/ai_scripts/imap_ingest_md_only.py --vault-root ~/Obsidian/WorkVault

Output Format

The generated Obsidian note follows this structure:

---
type: email
source: imap/gmail
gmail:
  x_gm_msgid: "1234567890"
  x_gm_thrid: "1234567890"
  message_id: "unique-message-id@mail.gmail.com"
subject: "Meeting Follow-up: Q4 Planning"
from: {"name": "Jane Smith", "email": "jane@example.com"}
to: [{"name": "You", "email": "you@gmail.com"}]
cc: []
date: 2025-12-15T10:30:00-05:00
labels: ["Save", "Work"]
attachments: []
checksum: "sha256:abc123..."
ingested_at: 2025-12-15T15:45:00Z
canonical_url: "https://mail.google.com/mail/u/0/#inbox/1234567890"
---

Hi,

Following up on our Q4 planning meeting...

Best,
Jane

Gmail Labels

The script recognizes these Gmail labels:

  • Save or AI/Ingest - Standard email ingestion
  • Slack-Thread or AI/Slack-Thread - Slack notification emails (marked as type: slack)

Create these labels in Gmail and apply them to emails you want to sync.

Configuration

Script Configuration

Edit the script to customize these settings:

# Line 38: Your Gmail address
os.environ['GMAIL_USER'] = 'your-email@gmail.com'

# Line 40: Your Obsidian vault root
DEFAULT_VAULT_ROOT = "~/Obsidian/YourVault"

# Line 41-42: Folder structure
EMAILS_DIR = "Emails"
ASSETS_DIR = "Assets/Emails"

Automation with cron

Run automatically every hour:

# Edit crontab
crontab -e

# Add this line (runs every hour)
0 * * * * /usr/bin/python3 ~/scripts/ai_scripts/imap_ingest_md_only.py >> ~/logs/gmail-sync.log 2>&1

Downloads

Prefer to install manually? Download the script directly:

Troubleshooting

Error: Credentials file not found

Ensure your OAuth client file is at ~/scripts/ai_scripts/client_secret.json. Download it from the Google Cloud Console.

Error: Token refresh failed

Delete ~/scripts/ai_scripts/gmail_oauth_token.json and run the script again to re-authenticate.

Error: GMAIL_USER not set

Either edit line 38 in the script to set your email, or set the environment variable: export GMAIL_USER='your-email@gmail.com'

No emails found

Make sure you've applied the "Save" label to emails in Gmail. The script only syncs labeled emails.

Duplicate files appearing

The script uses deduplication based on Gmail message IDs. If you see duplicates, delete .imap_ingest_index.json in your vault root and run again.