simple-email-gw
A simple email gateway with IMAP/SMTP clients, connection pooling, and MCP server for AI assistant integration.
Note: This package provides both async and sync APIs. Async clients are recommended for async applications. Use sync wrapper clients (SyncIMAPClient, SyncSMTPClient) for simpler synchronous code.
Rationale
This project was built using an agentic workflow — agents created the implementation from architectural requirements. For the full story, see the rationale documentation <https://simple-email-gw.readthedocs.io/en/latest/rationale.html>_.
Features
- Async IMAP and SMTP clients (aioimaplib, aiosmtplib)
- Sync wrapper clients for simpler synchronous usage (SyncIMAPClient, SyncSMTPClient)
- Connection pooling with automatic management
- Token bucket rate limiting
- Audit logging for security compliance
- CRLF injection prevention
- Recipient whitelist enforcement
- TLS 1.2+ minimum encryption
- MCP server for AI assistant integration
Installation
Using pip
pip install simple-email-gw
Using uv
uv add simple-email-gw
Quick Start
MCP Server
Run the MCP server for AI assistant integration:
# Set environment variables
export EMAIL_IMAP_HOST=imap.gmail.com
export EMAIL_SMTP_HOST=smtp.gmail.com
export EMAIL_USERNAME=your-email@gmail.com
export EMAIL_PASSWORD=your-app-password
# Run server
uvx --from simple-email-gw email-gw-mcp-server
Programmatic Usage
import asyncio
from simple_email_gw import IMAPClient, SMTPClient, EmailAccount
# Create account configuration
account = EmailAccount(
name="work",
imap_host="imap.gmail.com",
smtp_host="smtp.gmail.com",
username="user@gmail.com",
password="app-password"
)
async def main():
# Use IMAP client
async with IMAPClient(account) as client:
folders = await client.list_folders()
messages = await client.search(folder="INBOX")
print(f"Found {len(messages)} messages")
# Use SMTP client
smtp = SMTPClient(account)
result = await smtp.send_email(
to=["recipient@example.com"],
subject="Test",
body="Hello world"
)
print(f"Sent: {result}")
asyncio.run(main())
Sync Client Usage
For simpler synchronous code, use the sync wrapper clients:
from simple_email_gw import SyncIMAPClient, SyncSMTPClient, EmailAccount
# Create account configuration
account = EmailAccount(
name="work",
imap_host="imap.gmail.com",
smtp_host="smtp.gmail.com",
username="user@gmail.com",
password="app-password"
)
# Sync IMAP usage
with SyncIMAPClient(account) as client:
folders = client.list_folders()
messages = client.search(folder="INBOX")
print(f"Found {len(messages)} messages")
# Sync SMTP usage
with SyncSMTPClient(account) as client:
result = client.send_email(
to=["recipient@example.com"],
subject="Test",
body="Hello world"
)
print(f"Sent: {result}")
Interactive CLI
Run the interactive CLI for managing email:
# Create .env file with your email account
cp .env.example .env
# Edit .env with your account details
# Run CLI
uv run email-gw-cli
# Or if installed globally
email-gw-cli
Getting Started:
none:INBOX> help # Show available commands
none:INBOX> accounts # List configured accounts
none:INBOX> use work # Connect to 'work' account
work:INBOX> folders # List folders
work:INBOX> ls # List emails
work:INBOX> show 42 # View email #42
work:INBOX> write --sent alice@example.com # Compose and save copy to Sent
work:INBOX> reply --sent 42 # Reply and save copy to Sent
work:INBOX> write --sent --sent-folder "Sent Items" alice@example.com # Custom Sent folder
work:INBOX> theme # Toggle light/dark theme
work:INBOX> quit # Exit CLI
The --sent flag (also --save-sent) enables opt-in auto-append to the IMAP Sent folder after a successful send. It triggers a Save a copy to Sent folder? (y/n) prompt and can be combined with --sent-folder to override the destination folder.
Features:
- Command history - Use ↑/↓ arrows to navigate previous commands
- Theme support - Switch between light and dark color themes
- Auto-completion - Tab completion for commands (coming soon)
- Rich formatting - Tables, panels, and syntax-highlighted output
See the CLI documentation for complete command reference.
Note: Sync clients use a dedicated event loop in a background thread (Strategy 2). They preserve all async client benefits including connection pooling, rate limiting, and security features. Use async clients in async contexts (FastAPI, asyncio, etc.) for better performance.
Configuration
Environment Variables
The CLI and MCP server automatically load environment variables from a .env file in the current directory. Copy .env.example to .env and configure your email accounts:
cp .env.example .env
# Edit .env with your email account details
Single account configuration:
EMAIL_IMAP_HOST=imap.gmail.com
EMAIL_SMTP_HOST=smtp.gmail.com
EMAIL_USERNAME=user@gmail.com
EMAIL_PASSWORD=app-password
Multiple accounts (JSON):
EMAIL_ACCOUNTS_JSON='[{"name":"work","imap_host":"imap.gmail.com","smtp_host":"smtp.gmail.com","username":"work@example.com","password":"secret"},{"name":"personal","imap_host":"imap.icloud.com","smtp_host":"smtp.icloud.com","username":"personal@icloud.com","password":"secret"}]'
See the configuration documentation <https://simple-email-gw.readthedocs.io/en/latest/configuration.html>_ for detailed options.
Rate Limiting
Default limits:
- IMAP: 60 requests per minute per account
- SMTP: 100 sends per hour per account
Recipient Whitelist
Restrict outgoing emails to specific domains or addresses:
EMAIL_RECIPIENT_WHITELIST_DOMAINS=gmail.com,icloud.com
EMAIL_RECIPIENT_WHITELIST_ADDRESSES=admin@company.com
Security Features
TLS 1.2+ Minimum
All connections require TLS 1.2 or higher. Connections with older TLS versions are rejected.
CRLF Injection Prevention
All email headers are sanitized to prevent CRLF injection attacks:
- Subject lines
- Message-IDs
- References headers
- Email addresses
Recipient Whitelist
Optional whitelist restricts outgoing emails to approved recipients.
Rate Limiting
Token bucket algorithm prevents abuse with separate limits per account.
Audit Logging
All operations are logged for security compliance.
See the security documentation <https://simple-email-gw.readthedocs.io/en/latest/security.html>_ for complete details.
MCP Tools
| Tool | Purpose |
|---|---|
list_accounts |
List configured email accounts |
list_folders |
List IMAP folders |
search_emails |
Search messages by criteria |
get_email |
Fetch single message |
download_attachment |
Download attachment to workspace |
send_email |
Send new email (optional auto-save to Sent) |
reply_email |
Reply to thread (optional auto-save to Sent) |
move_email |
Move between folders |
delete_email |
Delete message |
mark_email_read |
Mark message as read |
append_email |
Append a raw RFC822 message to an IMAP folder |
Auto-Save Sent Folder
send_email and reply_email support optional auto-append to the account's Sent folder:
append_to_sent: bool- Append a copy after a successful SMTP send (default:False).append_folder: str | None- Override the destination folder (default: auto-detected Sent folder).
The Sent folder is detected using the IMAP \Sent special-use flag when available, with a deterministic fallback to Sent, Sent Items, and Sent Messages. If auto-append fails, the send still succeeds and a warning is returned.
Append Email Tool
append_email performs a pure IMAP APPEND of a base64-encoded RFC822 message. The message is re-parsed, threading headers are sanitized, and flags are restricted to the allowlist \Seen, \Draft, \Answered, \Flagged.
See the API documentation <https://simple-email-gw.readthedocs.io/en/latest/api.html>_ for complete API reference.
Development
See the development documentation <https://simple-email-gw.readthedocs.io/en/latest/development.html>_ for development setup and contribution guidelines.
Quick commands:
make dev-env # Install development dependencies
make test # Run tests
make lint # Run linter
make typecheck # Run type checker
make all # Run all checks
make email-gw-mcp-server # Run the MCP server
License
MIT License - see LICENSE for details.
Metadata
Release files for simple-email-gw 0.3.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| simple_email_gw-0.3.1.tar.gz | 796.3 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| simple_email_gw-0.3.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 850.8 kB
Release files / simple_email_gw-0.3.1.tar.gz
| Download URL | simple_email_gw-0.3.1.tar.gz |
|---|---|
| Size | 796.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
48d64b7baa19818f7c0ce8283cf6d641764312998e66b200ea0aadfb9a73ade1
|
|
BLAKE2b-256 checksum How to use checksums |
1133b4047224e6224d49f7cef46e0f2a80b706ef4d58efc90dceb1796e534f06
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.11.15
|
Release files / simple_email_gw-0.3.1-py3-none-any.whl
| Download URL | simple_email_gw-0.3.1-py3-none-any.whl |
|---|---|
| Size | 54.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
adab433a51d88d051b506a0ac731a71b1cb45601521b95ea15be06710b804336
|
|
BLAKE2b-256 checksum How to use checksums |
f3bd1f0d7921648e51121eb6a14b0685958a66b47857fb4a6e93cee52e80c7f4
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.11.15
|