fix: wire email platform into toolset mappings + add documentation

Post-merge fixes for the email gateway (PR #797):

1. Add Platform.EMAIL to all 4 platform-to-toolset/config mapping
   dicts in gateway/run.py. Without this, email sessions silently
   fell back to the Telegram toolset because these dicts were added
   after the PR branched off main.

2. Add email (and signal) to hermes_cli/tools_config.py and
   hermes_cli/skills_config.py PLATFORMS dicts so they appear in
   'hermes tools' and 'hermes skills' CLI commands.

3. Add full email setup documentation:
   - website/docs/user-guide/messaging/email.md — setup guide with
     Gmail/Outlook instructions, configuration, troubleshooting,
     security advice, and env var reference
   - Update messaging/index.md — add email to architecture diagram,
     platform toolset table, security examples, and next steps
This commit is contained in:
teknium1
2026-03-11 06:34:32 -07:00
parent 184aa5b2b3
commit eac5f8f40f
5 changed files with 197 additions and 10 deletions

View File

@@ -2023,6 +2023,7 @@ class GatewayRunner:
Platform.SLACK: "hermes-slack",
Platform.SIGNAL: "hermes-signal",
Platform.HOMEASSISTANT: "hermes-homeassistant",
Platform.EMAIL: "hermes-email",
}
platform_toolsets_config = {}
try:
@@ -2043,6 +2044,7 @@ class GatewayRunner:
Platform.SLACK: "slack",
Platform.SIGNAL: "signal",
Platform.HOMEASSISTANT: "homeassistant",
Platform.EMAIL: "email",
}.get(source.platform, "telegram")
config_toolsets = platform_toolsets_config.get(platform_config_key)
@@ -2835,6 +2837,7 @@ class GatewayRunner:
Platform.SLACK: "hermes-slack",
Platform.SIGNAL: "hermes-signal",
Platform.HOMEASSISTANT: "hermes-homeassistant",
Platform.EMAIL: "hermes-email",
}
# Try to load platform_toolsets from config
@@ -2858,6 +2861,7 @@ class GatewayRunner:
Platform.SLACK: "slack",
Platform.SIGNAL: "signal",
Platform.HOMEASSISTANT: "homeassistant",
Platform.EMAIL: "email",
}.get(source.platform, "telegram")
# Use config override if present (list of toolsets), otherwise hardcoded default

View File

@@ -22,6 +22,8 @@ PLATFORMS = {
"discord": "💬 Discord",
"slack": "💼 Slack",
"whatsapp": "📱 WhatsApp",
"signal": "📡 Signal",
"email": "📧 Email",
}
# ─── Config Helpers ───────────────────────────────────────────────────────────

View File

@@ -108,6 +108,8 @@ PLATFORMS = {
"discord": {"label": "💬 Discord", "default_toolset": "hermes-discord"},
"slack": {"label": "💼 Slack", "default_toolset": "hermes-slack"},
"whatsapp": {"label": "📱 WhatsApp", "default_toolset": "hermes-whatsapp"},
"signal": {"label": "📡 Signal", "default_toolset": "hermes-signal"},
"email": {"label": "📧 Email", "default_toolset": "hermes-email"},
}

View File

@@ -0,0 +1,176 @@
---
sidebar_position: 7
title: "Email"
description: "Set up Hermes Agent as an email assistant via IMAP/SMTP"
---
# Email Setup
Hermes can receive and reply to emails using standard IMAP and SMTP protocols. Send an email to the agent's address and it replies in-thread — no special client or bot API needed. Works with Gmail, Outlook, Yahoo, Fastmail, or any provider that supports IMAP/SMTP.
:::info No External Dependencies
The Email adapter uses Python's built-in `imaplib`, `smtplib`, and `email` modules. No additional packages or external services are required.
:::
---
## Prerequisites
- **A dedicated email account** for your Hermes agent (don't use your personal email)
- **IMAP enabled** on the email account
- **An app password** if using Gmail or another provider with 2FA
### Gmail Setup
1. Enable 2-Factor Authentication on your Google Account
2. Go to [App Passwords](https://myaccount.google.com/apppasswords)
3. Create a new App Password (select "Mail" or "Other")
4. Copy the 16-character password — you'll use this instead of your regular password
### Outlook / Microsoft 365
1. Go to [Security Settings](https://account.microsoft.com/security)
2. Enable 2FA if not already active
3. Create an App Password under "Additional security options"
4. IMAP host: `outlook.office365.com`, SMTP host: `smtp.office365.com`
### Other Providers
Most email providers support IMAP/SMTP. Check your provider's documentation for:
- IMAP host and port (usually port 993 with SSL)
- SMTP host and port (usually port 587 with STARTTLS)
- Whether app passwords are required
---
## Step 1: Configure Hermes
The easiest way:
```bash
hermes gateway setup
```
Select **Email** from the platform menu. The wizard prompts for your email address, password, IMAP/SMTP hosts, and allowed senders.
### Manual Configuration
Add to `~/.hermes/.env`:
```bash
# Required
EMAIL_ADDRESS=hermes@gmail.com
EMAIL_PASSWORD=abcd efgh ijkl mnop # App password (not your regular password)
EMAIL_IMAP_HOST=imap.gmail.com
EMAIL_SMTP_HOST=smtp.gmail.com
# Security (recommended)
EMAIL_ALLOWED_USERS=your@email.com,colleague@work.com
# Optional
EMAIL_IMAP_PORT=993 # Default: 993 (IMAP SSL)
EMAIL_SMTP_PORT=587 # Default: 587 (SMTP STARTTLS)
EMAIL_POLL_INTERVAL=15 # Seconds between inbox checks (default: 15)
EMAIL_HOME_ADDRESS=your@email.com # Default delivery target for cron jobs
```
---
## Step 2: Start the Gateway
```bash
hermes gateway # Run in foreground
hermes gateway install # Install as a system service
```
On startup, the adapter:
1. Tests IMAP and SMTP connections
2. Marks all existing inbox messages as "seen" (only processes new emails)
3. Starts polling for new messages
---
## How It Works
### Receiving Messages
The adapter polls the IMAP inbox for UNSEEN messages at a configurable interval (default: 15 seconds). For each new email:
- **Subject line** is included as context (e.g., `[Subject: Deploy to production]`)
- **Reply emails** (subject starting with `Re:`) skip the subject prefix — the thread context is already established
- **Attachments** are cached locally:
- Images (JPEG, PNG, GIF, WebP) → available to the vision tool
- Documents (PDF, ZIP, etc.) → available for file access
- **HTML-only emails** have tags stripped for plain text extraction
- **Self-messages** are filtered out to prevent reply loops
### Sending Replies
Replies are sent via SMTP with proper email threading:
- **In-Reply-To** and **References** headers maintain the thread
- **Subject line** preserved with `Re:` prefix (no double `Re: Re:`)
- **Message-ID** generated with the agent's domain
- Responses are sent as plain text (UTF-8)
### File Attachments
The agent can send file attachments in replies. Include `MEDIA:/path/to/file` in the response and the file is attached to the outgoing email.
---
## Access Control
Email access follows the same pattern as all other Hermes platforms:
1. **`EMAIL_ALLOWED_USERS` set** → only emails from those addresses are processed
2. **No allowlist set** → unknown senders get a pairing code
3. **`EMAIL_ALLOW_ALL_USERS=true`** → any sender is accepted (use with caution)
:::warning
**Always configure `EMAIL_ALLOWED_USERS`.** Without it, anyone who knows the agent's email address could send commands. The agent has terminal access by default.
:::
---
## Troubleshooting
| Problem | Solution |
|---------|----------|
| **"IMAP connection failed"** at startup | Verify `EMAIL_IMAP_HOST` and `EMAIL_IMAP_PORT`. Ensure IMAP is enabled on the account. For Gmail, enable it in Settings → Forwarding and POP/IMAP. |
| **"SMTP connection failed"** at startup | Verify `EMAIL_SMTP_HOST` and `EMAIL_SMTP_PORT`. Check that your password is correct (use App Password for Gmail). |
| **Messages not received** | Check `EMAIL_ALLOWED_USERS` includes the sender's email. Check spam folder — some providers flag automated replies. |
| **"Authentication failed"** | For Gmail, you must use an App Password, not your regular password. Ensure 2FA is enabled first. |
| **Duplicate replies** | Ensure only one gateway instance is running. Check `hermes gateway status`. |
| **Slow response** | The default poll interval is 15 seconds. Reduce with `EMAIL_POLL_INTERVAL=5` for faster response (but more IMAP connections). |
| **Replies not threading** | The adapter uses In-Reply-To headers. Some email clients (especially web-based) may not thread correctly with automated messages. |
---
## Security
:::warning
**Use a dedicated email account.** Don't use your personal email — the agent stores the password in `.env` and has full inbox access via IMAP.
:::
- Use **App Passwords** instead of your main password (required for Gmail with 2FA)
- Set `EMAIL_ALLOWED_USERS` to restrict who can interact with the agent
- The password is stored in `~/.hermes/.env` — protect this file (`chmod 600`)
- IMAP uses SSL (port 993) and SMTP uses STARTTLS (port 587) by default — connections are encrypted
---
## Environment Variables Reference
| Variable | Required | Default | Description |
|----------|----------|---------|-------------|
| `EMAIL_ADDRESS` | Yes | — | Agent's email address |
| `EMAIL_PASSWORD` | Yes | — | Email password or app password |
| `EMAIL_IMAP_HOST` | Yes | — | IMAP server host (e.g., `imap.gmail.com`) |
| `EMAIL_SMTP_HOST` | Yes | — | SMTP server host (e.g., `smtp.gmail.com`) |
| `EMAIL_IMAP_PORT` | No | `993` | IMAP server port |
| `EMAIL_SMTP_PORT` | No | `587` | SMTP server port |
| `EMAIL_POLL_INTERVAL` | No | `15` | Seconds between inbox checks |
| `EMAIL_ALLOWED_USERS` | No | — | Comma-separated allowed sender addresses |
| `EMAIL_HOME_ADDRESS` | No | — | Default delivery target for cron jobs |
| `EMAIL_ALLOW_ALL_USERS` | No | `false` | Allow all senders (not recommended) |

View File

@@ -1,12 +1,12 @@
---
sidebar_position: 1
title: "Messaging Gateway"
description: "Chat with Hermes from Telegram, Discord, Slack, WhatsApp, or Signal — architecture and setup overview"
description: "Chat with Hermes from Telegram, Discord, Slack, WhatsApp, Signal, or Email — architecture and setup overview"
---
# Messaging Gateway
Chat with Hermes from Telegram, Discord, Slack, WhatsApp, or Signal. The gateway is a single background process that connects to all your configured platforms, handles sessions, runs cron jobs, and delivers voice messages.
Chat with Hermes from Telegram, Discord, Slack, WhatsApp, Signal, or Email. The gateway is a single background process that connects to all your configured platforms, handles sessions, runs cron jobs, and delivers voice messages.
## Architecture
@@ -15,12 +15,12 @@ Chat with Hermes from Telegram, Discord, Slack, WhatsApp, or Signal. The gateway
│ Hermes Gateway │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌────────┐ │
│ │ Telegram │ │ Discord │ │ WhatsApp │ │ Slack │ │ Signal │ │
│ │ Adapter │ │ Adapter │ │ Adapter │ │ Adapter │ │ Adapter│
│ └────┬─────┘ └────┬─────┘ └────┬─────┘ └────┬─────┘ └───┬────┘ │
│ │ │ │ │ │
│ └─────────────┼────────────┼─────────────┼───────────┘
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌────────┐ ┌────────┐ ┌───────┐
│ │ Telegram │ │ Discord │ │ WhatsApp │ │ Slack │ │ Signal │ │ Email ││
│ │ Adapter │ │ Adapter │ │ Adapter │ │Adapter AdapterAdapter││
│ └────┬─────┘ └────┬─────┘ └────┬─────┘ └───────┘ └───┬────┘ └──┬────┘
│ │ │ │
│ └─────────────┼────────────┼────────────┼──────────┼─────────
│ │ │
│ ┌────────▼────────┐ │
│ │ Session Store │ │
@@ -114,9 +114,10 @@ Configure per-platform overrides in `~/.hermes/gateway.json`:
# Restrict to specific users (recommended):
TELEGRAM_ALLOWED_USERS=123456789,987654321
DISCORD_ALLOWED_USERS=123456789012345678
SIGNAL_ALLOWED_USERS=+15551234567,+15559876543
SIGNAL_ALLOWED_USERS=+155****4567,+155****6543
EMAIL_ALLOWED_USERS=trusted@example.com,colleague@work.com
# Or allow specific users across all platforms (comma-separated user IDs):
# Or allow
GATEWAY_ALLOWED_USERS=123456789,987654321
# Or explicitly allow all users (NOT recommended for bots with terminal access):
@@ -202,6 +203,7 @@ Each platform has its own toolset:
| WhatsApp | `hermes-whatsapp` | Full tools including terminal |
| Slack | `hermes-slack` | Full tools including terminal |
| Signal | `hermes-signal` | Full tools including terminal |
| Email | `hermes-email` | Full tools including terminal |
## Next Steps
@@ -210,3 +212,4 @@ Each platform has its own toolset:
- [Slack Setup](slack.md)
- [WhatsApp Setup](whatsapp.md)
- [Signal Setup](signal.md)
- [Email Setup](email.md)