An AI-powered email management application built with the Claude Agent SDK for Elixir.
This example demonstrates how to build an intelligent email agent that integrates IMAP email access with Claude AI for natural language email queries and management.
- IMAP Integration: Connecting to email servers via IMAP protocol
- SQLite Storage: Local email persistence without Ecto
- Claude Agent SDK: AI-powered natural language email search
- GenServer Patterns: Process supervision and connection management
- Automation Rules: File-based email processing rules
+------------------+ +------------------+ +------------------+
| | | | | |
| IMAP Server |<--->| IMAP.Connection |<--->| Storage |
| (Gmail, etc) | | GenServer | | (SQLite) |
| | | | | |
+------------------+ +------------------+ +------------------+
^
|
v
+------------------+ +------------------+
| | | |
| Claude Agent |<--->| Rules Engine |
| (SDK) | | (JSON) |
| | | |
+------------------+ +------------------+
| Module | Description |
|---|---|
EmailAgent |
Main API module |
EmailAgent.IMAP.Connection |
GenServer for IMAP connection management |
EmailAgent.Storage |
SQLite-based email persistence |
EmailAgent.Agent |
Claude SDK integration for AI queries |
EmailAgent.Rules |
File-based automation rules engine |
EmailAgent.EmailParser |
RFC 5322 email parsing |
- Elixir 1.19+
- Erlang/OTP 26+
- Claude CLI authenticated (
claude login) - Email account with IMAP access
cd examples/email_agent
mix deps.getCopy the example environment file:
cp .env.example .envEdit .env with your credentials:
# Required
ANTHROPIC_API_KEY=sk-ant-your-api-key
IMAP_HOST=imap.gmail.com
IMAP_PORT=993
EMAIL_ADDRESS=your-email@gmail.com
EMAIL_PASSWORD=your-app-password
# Optional
MAX_EMAILS_TO_FETCH=50
SYNC_INTERVAL_SECONDS=300For Gmail users:
- Enable 2-Factor Authentication on your Google account
- Generate an App Password:
- Go to Google Account Security
- Under "2-Step Verification", click "App passwords"
- Generate a new password for "Mail"
- Use the 16-character App Password (not your regular password)
# Start with IEx shell
iex -S mix
# Or run in production mode
MIX_ENV=prod mix run --no-halt# Sync emails from IMAP server
EmailAgent.sync_emails()
# List recent emails
{:ok, emails} = EmailAgent.list_emails(limit: 10)
# Search emails
{:ok, results} = EmailAgent.search("quarterly report")
# Ask Claude about your emails
{:ok, response} = EmailAgent.ask("Find emails from John about the project")
# Apply automation rules
{:ok, processed_count} = EmailAgent.apply_rules()The agent understands natural language:
EmailAgent.ask("What are my unread emails about?")
EmailAgent.ask("Summarize emails from last week")
EmailAgent.ask("Find important emails with attachments")
EmailAgent.ask("Which emails need a response?")Rules are defined in priv/rules.json:
{
"rules": [
{
"name": "Label newsletters",
"condition": {
"from_contains": "newsletter"
},
"action": {
"type": "label",
"label": "newsletters"
}
},
{
"name": "Star urgent emails",
"condition": {
"subject_contains": "urgent"
},
"action": {
"type": "star"
}
}
]
}from_contains: Sender address contains stringsubject_contains: Subject contains stringhas_attachment: Email has attachments (boolean)older_than_days: Email is older than N days
label: Add a label to the emailmove: Move to a foldermark_read: Mark as readstar: Star the email
# Run all tests
mix test
# Run with coverage
mix coveralls
# Run specific test file
mix test test/email_agent/storage_test.exsThis is a demonstration application for local development only.
- Credentials Storage: Credentials are stored in plain text in
.envfiles - No Authentication: The application has no user authentication
- Local Only: Not designed for production deployment
- Database Security: SQLite database is unencrypted
- Never commit
.envfiles to version control - Use app-specific passwords (not your main password)
- Run only on trusted networks
- Delete the database when done testing
email_agent/
├── config/
│ ├── config.exs
│ ├── dev.exs
│ ├── test.exs
│ └── prod.exs
├── lib/
│ └── email_agent/
│ ├── application.ex # OTP Application
│ ├── agent.ex # Claude SDK integration
│ ├── email.ex # Email struct
│ ├── email_parser.ex # RFC 5322 parsing
│ ├── rules.ex # Automation engine
│ ├── storage.ex # SQLite storage
│ └── imap/
│ ├── client.ex # Real IMAP client
│ ├── connection.ex # GenServer
│ └── connection_behaviour.ex
├── priv/
│ └── rules.json # Automation rules
├── test/
│ ├── email_agent/
│ │ ├── agent_test.exs
│ │ ├── email_parser_test.exs
│ │ ├── rules_test.exs
│ │ ├── storage_test.exs
│ │ └── imap/
│ │ └── connection_test.exs
│ └── test_helper.exs
├── .env.example
├── .gitignore
├── mix.exs
└── README.md
| Package | Purpose |
|---|---|
claude_agent_sdk |
Claude AI integration |
mail |
IMAP protocol support |
exqlite |
SQLite database |
dotenvy |
Environment variable loading |
mox |
Test-only interface doubles |
credo |
Code analysis |
dialyxir |
Type checking |
# Check if IMAP is configured
System.get_env("IMAP_HOST")
# Start in storage-only mode
# (Just don't set IMAP environment variables)- Ensure 2FA is enabled
- Use App Password, not regular password
- Check for spaces in the password
# Reset the database
mix db.resetThis example is inspired by the claude-agent-sdk-demos/email-agent TypeScript demo.
MIT License - See the main Claude Agent SDK repository for details.