Skip to main content

Email Channel

The Email channel enables ZeroClaw to communicate via email using IMAP for receiving messages and SMTP for sending replies, with support for IMAP IDLE for instant push notifications.

Overview

  • Channel Name: email
  • Transport: IMAP (receive) + SMTP (send)
  • Authentication: Username/password
  • Public Port Required: No
  • Supports: Text, HTML, attachments, allowlist filtering

Configuration

Required Settings

Complete Configuration

Provider-Specific Examples

Gmail

Note: Enable “Less secure app access” or create an App Password:
  1. Go to Google Account settings
  2. Security → 2-Step Verification
  3. App passwords → Generate new password
  4. Use generated password in config

Outlook/Office 365

Yahoo Mail

NetEase (163.com / 126.com)

Important: NetEase requires RFC 2971 IMAP ID extension. Without it, mailbox selection fails.

Features

IMAP IDLE (Push Mode)

The channel uses IMAP IDLE (RFC 2177) for instant push notifications: How it works:
  1. Connect to IMAP server with TLS
  2. Authenticate with username/password
  3. Select mailbox (default: INBOX)
  4. Check for existing unseen messages
  5. Enter IDLE mode
  6. Server pushes notifications when new mail arrives
  7. Fetch and process new messages
  8. Re-enter IDLE
Timeout Behavior:
  • Default: 1740 seconds (29 minutes)
  • RFC 2177 recommends clients restart IDLE every 29 minutes
  • Automatic reconnection on timeout
  • Exponential backoff on connection errors
Advantages over Polling:
  • Instant delivery (no delay)
  • Lower server load
  • Lower bandwidth usage
  • Standard protocol support

Allowlist Filtering

Empty List (Deny All)

Blocks all inbound emails.

Wildcard (Allow All)

Accepts emails from anyone (testing only).

Specific Email Addresses

Case-insensitive exact match.

Domain Matching

Accepts any sender from those domains:
  • user@example.com ✔️
  • admin@example.com ✔️
  • anyone@company.org ✔️

Mixed Rules

Message Processing

Text Extraction

Priority:
  1. Plain text body (MIME text/plain)
  2. HTML body (MIME text/html) - HTML tags stripped
  3. Text attachments
  4. Fallback: "(no readable content)"
HTML Stripping: Simple tag removal:

Subject Handling

Subject is prefixed to content:

IMAP ID Extension (RFC 2971)

Sends client identification after login:
Why it matters:
  • Some providers (NetEase) require it
  • Helps with debugging
  • Provider can optimize for known clients
Sent fields:
  • name - Client application name
  • version - Client version
  • vendor - Vendor/organization name
If disabled or fails, continues without ID (non-fatal).

Attachment Support

Current Implementation:
  • Text attachments inlined: [Attachment: file.txt]\ncontent
  • Other MIME types skipped
Future: Full attachment download and processing planned.

Reply Threading

Replies are sent to the sender’s address:
No threading support (each email is independent).

Implementation Details

Source Location

src/channels/email_channel.rs (1106 lines)

Key Components

EmailChannel Struct

EmailConfig

Connection Flow

IMAP (Receive)

  1. TCP Connect: TcpStream::connect(host:port)
  2. TLS Handshake: rustls with system root certificates
  3. IMAP Greeting: Wait for server hello
  4. LOGIN: LOGIN username password
  5. IMAP ID: Send RFC 2971 metadata (if enabled)
  6. SELECT: Open mailbox (INBOX)
  7. SEARCH: Find unseen messages: UID SEARCH UNSEEN
  8. FETCH: Download message bodies: UID FETCH ... RFC822
  9. STORE: Mark as seen: UID STORE ... +FLAGS (\Seen)
  10. IDLE: Enter idle mode: IDLE
  11. Wait: Block until server notification or timeout
  12. DONE: Exit idle: DONE
  13. Repeat from step 7

SMTP (Send)

  1. TCP Connect: (TLS port 465 or STARTTLS port 587)
  2. TLS: Establish encrypted connection
  3. EHLO: Identify client
  4. AUTH: Authenticate with credentials
  5. MAIL FROM: Set sender
  6. RCPT TO: Set recipient
  7. DATA: Send message body
  8. QUIT: Close connection

Message Deduplication

Prevents processing same email twice: Mechanism:
  • Tracks seen message IDs in memory: HashSet<String>
  • Message ID from Message-ID header or generated UUID
  • Persists across IDLE reconnections
  • Not persisted to disk (resets on restart)
Behavior on Restart:
  • Marks all unseen messages in inbox as seen
  • Processes them once
  • Future restarts see no unseen messages

Error Recovery

Connection Loss:
  1. Log error with backoff counter
  2. Wait 1 second
  3. Exponential backoff: 2s, 4s, 8s, …, max 60s
  4. Reconnect from scratch
  5. Resume listening
IDLE Timeout:
  1. Exit IDLE cleanly with DONE
  2. Check for new messages
  3. Re-enter IDLE

Error Handling

Common Errors

Authentication Failed:
Solution:
  • Verify username/password
  • Check if app passwords required
  • Enable IMAP access in provider settings
Connection Timeout:
Solution:
  • Check firewall rules
  • Verify IMAP port (993 for TLS)
  • Test with telnet: openssl s_client -connect imap.example.com:993
TLS Error:
Solution:
  • Update system root certificates
  • Check system time (affects cert validation)
Mailbox Selection Failed (NetEase):
Solution: Enable IMAP ID extension:
IDLE Not Supported:
Fallback to polling (future feature - currently returns error).

Runtime Commands

Not applicable - email operates asynchronously.

Best Practices

  1. Use App Passwords: For Gmail, Yahoo, etc.
  2. Allowlist Domains: Use @company.com for organizations
  3. Dedicated Account: Create separate email for bot
  4. Monitor Logs: Watch for connection errors
  5. IMAP ID: Enable for NetEase and other providers requiring it
  6. TLS Always: Never disable smtp_tls

Troubleshooting

No Messages Received

Check Allowlist:
Check Logs:
Look for:
  • Email IDLE listening on INBOX (instant push enabled)
  • Blocked email from ...
  • Email poll failed:
Check IMAP Access:

Messages Not Sending

Check SMTP Credentials: Same as IMAP username/password (usually) Check Port:
  • Port 465: SMTP over TLS (smtps)
  • Port 587: SMTP with STARTTLS
Check Firewall:
Test with CLI:

IDLE Keeps Disconnecting

Provider Limit: Some providers close IDLE after shorter timeout. Solution: Reduce timeout:
NAT Timeout: Router/firewall may close idle connections. Solution: Even shorter timeout:

Performance

Message Latency

IMAP IDLE:
  • Delivery: <5 seconds (instant push)
  • Processing: Depends on agent/provider
Polling (fallback):
  • Poll interval: Configurable (default: 60s)
  • Latency: 0-60 seconds

Optimization Tips

  1. IDLE Over Polling: Always preferred
  2. Reduce Timeout: Lower for flaky networks
  3. Dedicated Mailbox: Use separate folder if needed
  4. Allowlist: Reduces processing overhead

Security

Credential Protection

  • Stored in config file (protect with permissions: chmod 600)
  • Never logged
  • Transmitted over TLS only

TLS Configuration

  • IMAP: Port 993 (implicit TLS)
  • SMTP: Port 465 (implicit TLS) or 587 (STARTTLS)
  • Uses system root certificates (rustls + webpki-roots)
  • Certificate validation always enabled

Allowlist Enforcement

  • Checked before any processing
  • Case-insensitive for email addresses
  • Logged when blocked:

See Also