Enables sending and receiving emails through Gmail using SMTP and IMAP/POP3 protocols, with support for attachments, HTML content, and filtering unread messages.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Email Send/Receive MCP Serversend an email to john@example.com about the meeting tomorrow"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Email Send/Receive MCP Server
A Model Context Protocol (MCP) server for sending and receiving emails via SMTP, POP3, and IMAP. Built with FastMCP 2.0, this server enables AI assistants like Claude to interact with email services, making it easy to automate email workflows, check inboxes, and send messages programmatically.
π― What is MCP?
The Model Context Protocol (MCP) is an open standard that enables AI applications to securely connect to external data sources and tools. This server implements MCP to give AI assistants the ability to:
Send emails with attachments, CC/BCC support
Receive and read emails from IMAP/POP3 servers
Search and filter email messages
Work with multiple email providers (Gmail, Outlook, Yahoo, etc.)
Perfect for integration with AI assistants like Claude Desktop, this server acts as a bridge between conversational AI and your email infrastructure.
β¨ Features
π€ Email Sending (SMTP)
β Send emails with validated recipient addresses
β Support for CC (Carbon Copy) and BCC (Blind Carbon Copy)
β HTML and plain text email bodies
β File attachments support with size validation
β Configurable sender information (name and email)
β Batch email validation for multiple recipients
β Smart TLS/SSL connection handling
π₯ Email Receiving (IMAP/POP3)
β Retrieve emails from IMAP servers with full folder support
β POP3 protocol support for simple email retrieval
β Filter by mailbox/folder (INBOX, Sent, Drafts, etc.)
β Unread emails filtering
β Attachment information extraction
β Email metadata parsing (sender, subject, date, etc.)
β Body preview with length limiting
π Email Validation & Security
β RFC-compliant email address validation
β Automatic email normalization
β Batch validation for multiple recipients
β App Password support for major providers
β TLS/SSL encryption for all connections
β Secure credential management via environment variables
π Table of Contents
π Quick Start
Get started in 5 minutes! Follow these steps:
# 1. Clone and install
git clone https://github.com/bedro96/email-send-mcp.git
cd email-send-mcp
pip install -e .
# 2. Configure email credentials
cp .env.example .env
# Edit .env with your email provider settings
# 3. Run the server
python main.pyFor detailed quick start instructions, see QUICKSTART.md.
π¦ Installation
Prerequisites
Python 3.11 or higher - Download Python
Email account with SMTP/IMAP access (Gmail, Outlook, Yahoo, etc.)
App Password for your email provider (for Gmail, Outlook, Yahoo)
Method 1: Using uv (Recommended)
uv is a fast Python package manager that simplifies dependency management.
# Install uv if you haven't already
curl -LsSf https://astral.sh/uv/install.sh | sh
# Clone the repository
git clone https://github.com/bedro96/email-send-mcp.git
cd email-send-mcp
# Install dependencies
uv pip install -e .
# For development with testing tools
uv pip install -e ".[dev]"Method 2: Using pip
# Clone the repository
git clone https://github.com/bedro96/email-send-mcp.git
cd email-send-mcp
# Install dependencies
pip install -e .
# For development (optional)
pip install -e ".[dev]"Verify Installation
# Check if dependencies are installed
python -c "import fastmcp; print('FastMCP version:', fastmcp.__version__)"βοΈ Configuration
Step 1: Create Environment File
Copy the example environment file:
cp .env.example .envEdit
.envwith your email server credentials:
# SMTP Configuration (for sending emails)
SMTP_SERVER=smtp.gmail.com
SMTP_PORT=587
SMTP_USERNAME=your-email@example.com
SMTP_PASSWORD=your-app-password
SMTP_USE_TLS=true
# IMAP Configuration (for receiving emails)
IMAP_SERVER=imap.gmail.com
IMAP_PORT=993
IMAP_USERNAME=your-email@example.com
IMAP_PASSWORD=your-app-password
IMAP_USE_SSL=true
# POP3 Configuration (alternative for receiving emails)
POP3_SERVER=pop.gmail.com
POP3_PORT=995
POP3_USERNAME=your-email@example.com
POP3_PASSWORD=your-app-password
POP3_USE_SSL=true
# Email Settings
DEFAULT_FROM_EMAIL=your-email@example.com
DEFAULT_FROM_NAME=MCP Email Server
MAX_ATTACHMENT_SIZE_MB=25
# Server Configuration
LOG_LEVEL=INFO
DEBUG=falseStep 2: Email Provider Setup
Gmail Setup (Most Common)
For Gmail, you'll need to:
Enable 2-Factor Authentication
Go to Google Account Security
Enable 2-Step Verification
Generate an App Password
Visit App Passwords
Select "Mail" and your device
Copy the generated 16-character password
Use this password in your
.envfile
Enable IMAP Access (for receiving emails)
Open Gmail β Settings β See all settings
Go to "Forwarding and POP/IMAP" tab
Enable IMAP
Save Changes
Gmail Configuration:
SMTP_SERVER=smtp.gmail.com
SMTP_PORT=587
SMTP_USERNAME=your-email@gmail.com
SMTP_PASSWORD=xxxx xxxx xxxx xxxx # 16-character app password
SMTP_USE_TLS=true
IMAP_SERVER=imap.gmail.com
IMAP_PORT=993
IMAP_USERNAME=your-email@gmail.com
IMAP_PASSWORD=xxxx xxxx xxxx xxxx # Same app password
IMAP_USE_SSL=true
DEFAULT_FROM_EMAIL=your-email@gmail.comOther Email Providers
For configuration details for Outlook, Yahoo, ProtonMail, iCloud, and custom SMTP servers, see EMAIL_PROVIDERS.md.
Configuration Parameters Explained
Parameter | Description | Default | Required |
| SMTP server hostname | smtp.gmail.com | Yes (for sending) |
| SMTP server port (587 for TLS, 465 for SSL) | 587 | Yes (for sending) |
| SMTP authentication username (usually email) | - | Yes (for sending) |
| SMTP authentication password (use app password) | - | Yes (for sending) |
| Use STARTTLS for SMTP (recommended for port 587) | true | No |
| IMAP server hostname | imap.gmail.com | Yes (for receiving) |
| IMAP server port (993 for SSL) | 993 | Yes (for receiving) |
| IMAP authentication username | - | Yes (for receiving) |
| IMAP authentication password | - | Yes (for receiving) |
| Use SSL for IMAP | true | No |
| POP3 server hostname | pop.gmail.com | No |
| POP3 server port (995 for SSL) | 995 | No |
| POP3 authentication username | - | No |
| POP3 authentication password | - | No |
| Use SSL for POP3 | true | No |
| Default sender email address | - | Yes |
| Default sender display name | MCP Email Server | No |
| Maximum attachment size in MB | 25 | No |
| Logging level (DEBUG, INFO, WARNING, ERROR) | INFO | No |
| Enable debug mode | false | No |
Security Best Practices
β οΈ Important Security Notes:
Never commit
.envfiles with real credentials to version controlAlways use App Passwords instead of your main account password
Enable 2-Factor Authentication on your email account
Use TLS/SSL for all email connections
Store secrets securely in production (Azure Key Vault, AWS Secrets Manager, etc.)
Rotate passwords regularly and revoke unused app passwords
Limit permissions to only what's necessary
π οΈ MCP Tools (Functions)
This server exposes 3 powerful MCP tools that AI assistants can use to interact with email services. Each tool is thoroughly documented below.
1. send_email - Send Emails via SMTP
Send emails with full support for attachments, CC/BCC, and HTML formatting.
Function Signature:
async def send_email(
recipient: str, # Required: Primary recipient email
subject: str, # Required: Email subject/title
body: str, # Required: Email body content
attachments: List[str] = None, # Optional: File paths to attach
cc: List[str] = None, # Optional: CC recipients
bcc: List[str] = None, # Optional: BCC recipients
is_html: bool = False # Optional: HTML formatting flag
) -> strParameters:
Parameter | Type | Required | Description |
|
| β Yes | Primary recipient email address (validated against RFC standards) |
|
| β Yes | Email subject line |
|
| β Yes | Email body content (plain text or HTML) |
|
| β No | List of absolute file paths to attach (validates size and existence) |
|
| β No | List of carbon copy recipient email addresses |
|
| β No | List of blind carbon copy recipient email addresses |
|
| β No | Set to |
Returns:
Success: Formatted confirmation message with delivery details
Error: Error message explaining what went wrong
Example Usage in Claude:
Please send an email to john@example.com with the subject "Project Update"
and body "The quarterly report is attached." Attach the file /path/to/report.pdfExample Response:
β
Email sent successfully!
Recipient: john@example.com
Subject: Project Update
CC: None
BCC: None
Attachments: 1Features:
β Automatic email address validation and normalization
β File attachment with size validation (default max: 25MB)
β Support for multiple CC and BCC recipients
β HTML email support with proper MIME encoding
β Smart SMTP connection handling (TLS/SSL)
β Detailed error messages for troubleshooting
2. receive_emails_imap - Retrieve Emails via IMAP
Retrieve and read emails from IMAP servers with advanced filtering options.
Function Signature:
async def receive_emails_imap(
mailbox: str = "INBOX", # Mailbox/folder to read from
limit: int = 10, # Maximum emails to retrieve
unread_only: bool = False # Filter for unread only
) -> strParameters:
Parameter | Type | Required | Default | Description |
|
| β No |
| Mailbox/folder name (INBOX, Sent, Drafts, etc.) |
|
| β No |
| Maximum number of emails to retrieve (1-100) |
|
| β No |
| Only retrieve unread messages |
Returns:
Formatted list of emails with metadata and body previews
Each email includes: ID, From, To, Subject, Date, Body Preview, Attachments
Example Usage in Claude:
Please check my inbox and show me the last 5 unread emailsExample Response:
π¬ Retrieved 5 email(s):
--- Email 1 ---
ID: 12345
From: alice@company.com
To: you@example.com
Subject: Meeting Tomorrow
Date: Mon, 10 Nov 2025 10:30:00 +0000
Attachments: 1
- agenda.pdf (application/pdf)
Body Preview: Hi, just a reminder about our meeting tomorrow at 2 PM.
I've attached the agenda for your review...
Body Length: 450 characters
--- Email 2 ---
[...]Features:
β Support for all IMAP folders (INBOX, Sent, Drafts, custom folders)
β Unread-only filtering
β Attachment detection and metadata extraction
β Email body preview (first 200 characters)
β Full metadata parsing (sender, recipient, date, subject)
β Handles multiple encodings and international characters
β Secure SSL/TLS connection
Supported Mailbox Names:
INBOX- Primary inboxSent- Sent emailsDrafts- Draft messagesTrash- Deleted itemsSpamorJunk- Spam folderCustom folders created by the user
3. receive_emails_pop3 - Retrieve Emails via POP3
Retrieve emails using the simpler POP3 protocol (note: POP3 is less feature-rich than IMAP).
Function Signature:
def receive_emails_pop3(
limit: int = 10 # Maximum emails to retrieve
) -> strParameters:
Parameter | Type | Required | Default | Description |
|
| β No |
| Maximum number of emails to retrieve |
Returns:
Formatted list of emails (similar to IMAP output)
Example Usage in Claude:
Fetch my last 10 emails using POP3Features:
β Simple email retrieval
β Attachment detection
β Email metadata parsing
β SSL/TLS support
Note: POP3 has limitations compared to IMAP:
β No folder support (only retrieves from main inbox)
β No unread filtering
β Less efficient for large mailboxes
β Use IMAP when possible for better features
Tool Comparison
Feature |
|
|
|
Primary Function | Send emails | Receive emails | Receive emails |
Protocol | SMTP | IMAP | POP3 |
Attachments Support | β Send | β Detect | β Detect |
HTML Support | β Yes | β Yes | β Yes |
Folder Support | N/A | β Yes | β No |
Unread Filtering | N/A | β Yes | β No |
CC/BCC Support | β Yes | N/A | N/A |
Use Case | Sending automated emails | Full email management | Simple email retrieval |
π‘ Usage Examples
Running the MCP Server
Start the server in HTTP mode (for MCP client connections):
python main.pyThe server will:
Load configuration from
.envfileInitialize SMTP, IMAP, and POP3 services
Start listening on
http://0.0.0.0:8888/mcpExpose MCP tools for AI assistants to use
Log all activities to console and log files
Server Output:
2025-11-10 15:57:03 - email-send-mcp - INFO - Starting Email Send/Receive MCP Server...
2025-11-10 15:57:03 - email-send-mcp - INFO - Configuration values set from environment variables.
2025-11-10 15:57:03 - email-send-mcp - INFO - EmailSender service initialized.
2025-11-10 15:57:03 - email-send-mcp - INFO - EmailReceiver service initialized.
2025-11-10 15:57:03 - email-send-mcp - INFO - Server running on http://0.0.0.0:8888/mcpExample 1: Send a Simple Text Email
Natural Language Request (via Claude):
Please send an email to colleague@company.com with the subject "Team Meeting"
and tell them the meeting is scheduled for tomorrow at 2 PM.What Happens:
Claude uses the
send_emailtoolEmail address is validated
Email is sent via configured SMTP server
Confirmation is returned
MCP Tool Call (Behind the Scenes):
send_email(
recipient="colleague@company.com",
subject="Team Meeting",
body="The meeting is scheduled for tomorrow at 2 PM."
)Response:
β
Email sent successfully!
Recipient: colleague@company.com
Subject: Team Meeting
CC: None
BCC: None
Attachments: 0Example 2: Send HTML Email with Attachments
Natural Language Request:
Send an email to team@company.com with subject "Quarterly Report"
and include the report.pdf file. Use HTML formatting with a professional header.MCP Tool Call:
send_email(
recipient="team@company.com",
subject="Quarterly Report",
body="""
<html>
<body>
<h1>Quarterly Report - Q4 2025</h1>
<p>Dear Team,</p>
<p>Please find attached the quarterly report for your review.</p>
<p>Best regards,<br>Management</p>
</body>
</html>
""",
attachments=["/path/to/report.pdf"],
is_html=True
)Example 3: Send Email with CC and BCC
Natural Language Request:
Email the project update to john@company.com, CC alice@company.com
and bob@company.com, and BCC the manager@company.comMCP Tool Call:
send_email(
recipient="john@company.com",
subject="Project Update",
body="The project is on track and will be completed by the deadline.",
cc=["alice@company.com", "bob@company.com"],
bcc=["manager@company.com"]
)Example 4: Check Unread Emails
Natural Language Request:
Show me my unread emails from the last weekMCP Tool Call:
receive_emails_imap(
mailbox="INBOX",
limit=20,
unread_only=True
)Response:
π¬ Retrieved 3 email(s):
--- Email 1 ---
ID: 12345
From: client@example.com
To: you@company.com
Subject: Question about Invoice
Date: Mon, 09 Nov 2025 14:30:00 +0000
Body Preview: Hi, I have a question about invoice #12345. Could you please clarify the charges for...
Body Length: 320 characters
[More emails...]Example 5: Check Specific Email Folder
Natural Language Request:
Check my Sent folder and show me the last 5 emails I sentMCP Tool Call:
receive_emails_imap(
mailbox="Sent",
limit=5,
unread_only=False
)Example 6: Retrieve Emails with Attachments
Natural Language Request:
Show me emails with attachments from my inboxMCP Tool Call:
receive_emails_imap(
mailbox="INBOX",
limit=10,
unread_only=False
)Response (showing attachment info):
π¬ Retrieved 2 email(s):
--- Email 1 ---
ID: 98765
From: partner@company.com
To: you@example.com
Subject: Contract Documents
Date: Tue, 08 Nov 2025 16:45:00 +0000
Attachments: 2
- contract.pdf (application/pdf)
- terms.docx (application/vnd.openxmlformats-officedocument.wordprocessingml.document)
Body Preview: Please review the attached contract documents...Example 7: Using POP3 for Simple Retrieval
Natural Language Request:
Get my last 5 emails using POP3MCP Tool Call:
receive_emails_pop3(limit=5)Programmatic Usage (Python)
If you want to use the email services directly in Python (without MCP):
import asyncio
from src.services.email_sender import EmailSender
from src.services.email_receiver import EmailReceiver
async def main():
# Send an email
sender = EmailSender()
result = await sender.send_email(
recipient="user@example.com",
subject="Test Email",
body="This is a test message"
)
print(result)
# Receive emails
receiver = EmailReceiver()
result = await receiver.receive_emails_imap(
mailbox="INBOX",
limit=5,
unread_only=True
)
print(result)
if __name__ == "__main__":
asyncio.run(main())For more examples, see examples.py in the repository.
π§ͺ Testing
This project includes comprehensive test coverage for validators, configuration, and core functionality.
Running Tests
Run All Tests
# Basic test run
pytest tests/ -v
# Run with detailed output
pytest tests/ -vv
# Run tests with coverage report
pytest tests/ --cov=src --cov-report=html --cov-report=term
# Run tests in parallel (faster)
pytest tests/ -n autoRun Specific Test Files
# Test email validators only
pytest tests/test_validators.py -v
# Test configuration management
pytest tests/test_config.py -v
# Test specific function
pytest tests/test_validators.py::TestEmailValidation::test_validate_valid_email -vTest Coverage
The project includes tests for:
β
Email Validation (tests/test_validators.py)
Valid email address validation
Invalid email detection (missing @, invalid domain, etc.)
Email normalization
Batch email validation
Email formatting with names
β
Configuration Management (tests/test_config.py)
Settings loading from environment
Default value validation
Port number validation
Field type validation
β
SMTP Testing (test_smtp.py, test_smtp_variations.py)
SMTP connection testing
Email sending variations
Different provider configurations
β
Integration Tests (test_kakao_specific.py)
Provider-specific testing
Real-world scenarios
Example Test Output
$ pytest tests/ -v
============================= test session starts ==============================
tests/test_validators.py::TestEmailValidation::test_validate_valid_email PASSED
tests/test_validators.py::TestEmailValidation::test_validate_invalid_email_no_at PASSED
tests/test_validators.py::TestEmailValidation::test_validate_email_with_dots PASSED
tests/test_validators.py::TestEmailValidation::test_validate_email_with_plus PASSED
tests/test_validators.py::TestEmailValidation::test_validate_multiple_emails PASSED
tests/test_validators.py::TestEmailValidation::test_format_email_with_name PASSED
tests/test_config.py::TestSettings::test_default_values PASSED
tests/test_config.py::TestSettings::test_port_validation PASSED
============================== 8 passed in 0.45s ===============================Writing New Tests
When adding new features, include tests following this pattern:
# tests/test_my_feature.py
import pytest
from src.services.my_service import MyService
class TestMyFeature:
"""Test suite for my new feature."""
def test_basic_functionality(self):
"""Test basic feature operation."""
service = MyService()
result = service.do_something()
assert result is not None
@pytest.mark.asyncio
async def test_async_functionality(self):
"""Test async feature operation."""
service = MyService()
result = await service.do_something_async()
assert result["status"] == "success"Integration Testing
For testing with real email servers:
Create a test email account (don't use your primary account)
Set up test credentials in
.env.test:SMTP_SERVER=smtp.gmail.com SMTP_PORT=587 SMTP_USERNAME=test-account@gmail.com SMTP_PASSWORD=test-app-passwordRun integration tests (not included in default test suite):
pytest tests/integration/ -v --env-file=.env.test
Manual Testing
You can test the MCP server manually:
Start the server:
python main.pyTest with curl (health check):
curl http://localhost:8888/api/health # Expected: {"status":"ok"}Test email sending (using examples.py):
python examples.py
Testing Checklist
Before submitting code:
All existing tests pass (
pytest tests/ -v)New tests added for new features
Code coverage maintained or improved
Tests follow naming conventions (
test_*.py,Test*classes)Async tests use
@pytest.mark.asynciodecoratorIntegration tests are marked separately
Continuous Integration
This project is ready for CI/CD integration. Example GitHub Actions workflow:
name: Tests
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
with:
python-version: '3.11'
- name: Install dependencies
run: |
pip install -e ".[dev]"
- name: Run tests
run: |
pytest tests/ -v --cov=src --cov-report=xml
- name: Upload coverage
uses: codecov/codecov-action@v3π Integration with MCP Clients
This server is compatible with any MCP client. Below are detailed instructions for popular clients.
Claude Desktop Integration
Claude Desktop is Anthropic's official desktop app that supports MCP servers.
Setup Instructions
Locate Claude Desktop Configuration File
The configuration file location varies by operating system:
macOS:
~/Library/Application Support/Claude/claude_desktop_config.jsonWindows:
%APPDATA%\Claude\claude_desktop_config.jsonLinux:
~/.config/Claude/claude_desktop_config.json
Add Email MCP Server to Configuration
Option A: Using Environment Variables (Recommended)
{ "mcpServers": { "email": { "command": "python", "args": ["/absolute/path/to/email-send-mcp/main.py"], "env": { "SMTP_SERVER": "smtp.gmail.com", "SMTP_PORT": "587", "SMTP_USERNAME": "your-email@gmail.com", "SMTP_PASSWORD": "your-app-password", "IMAP_SERVER": "imap.gmail.com", "IMAP_PORT": "993", "IMAP_USERNAME": "your-email@gmail.com", "IMAP_PASSWORD": "your-app-password", "DEFAULT_FROM_EMAIL": "your-email@gmail.com" } } } }Option B: Using .env File (Simpler)
{ "mcpServers": { "email": { "command": "python", "args": ["/absolute/path/to/email-send-mcp/main.py"], "cwd": "/absolute/path/to/email-send-mcp" } } }This option assumes you have a
.envfile in the project directory.Restart Claude Desktop
After updating the configuration, fully quit and restart Claude Desktop.
Verify Integration
In Claude Desktop, you should see email tools available. Try asking:
Can you help me send an email?Claude should recognize it has access to the
send_emailtool.
Using Email Tools in Claude Desktop
Once configured, you can use natural language to interact with emails:
Sending Emails:
"Send an email to john@example.com with subject 'Meeting' and tell him about tomorrow's meeting"
"Email the team about the project update"
"Send an email with the quarterly report attached"
Receiving Emails:
"Check my inbox for unread emails"
"Show me the last 10 emails I received"
"What emails with attachments do I have?"
"Check my Sent folder"
Other MCP Clients
This server works with any MCP-compatible client:
Custom MCP Client
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client
async def main():
server_params = StdioServerParameters(
command="python",
args=["/path/to/email-send-mcp/main.py"],
env={
"SMTP_SERVER": "smtp.gmail.com",
# ... other env vars
}
)
async with stdio_client(server_params) as (read, write):
async with ClientSession(read, write) as session:
# Initialize the connection
await session.initialize()
# List available tools
tools = await session.list_tools()
print("Available tools:", tools)
# Call send_email tool
result = await session.call_tool(
"send_email",
arguments={
"recipient": "user@example.com",
"subject": "Test",
"body": "Hello from MCP client!"
}
)
print(result)
if __name__ == "__main__":
import asyncio
asyncio.run(main())HTTP MCP Client
The server also supports HTTP transport for web-based integrations:
// JavaScript/Node.js example
const response = await fetch('http://localhost:8888/mcp', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
jsonrpc: '2.0',
method: 'tools/call',
params: {
name: 'send_email',
arguments: {
recipient: 'user@example.com',
subject: 'Test Email',
body: 'Hello from HTTP client!'
}
},
id: 1
})
});
const result = await response.json();
console.log(result);Environment Variable Reference for MCP Clients
When configuring MCP clients, these environment variables are required:
Minimum Required Variables:
{
"SMTP_SERVER": "smtp.gmail.com",
"SMTP_PORT": "587",
"SMTP_USERNAME": "your-email@gmail.com",
"SMTP_PASSWORD": "your-app-password",
"DEFAULT_FROM_EMAIL": "your-email@gmail.com"
}For Email Receiving (Optional):
{
"IMAP_SERVER": "imap.gmail.com",
"IMAP_PORT": "993",
"IMAP_USERNAME": "your-email@gmail.com",
"IMAP_PASSWORD": "your-app-password"
}Troubleshooting MCP Integration
Issue: Tools not appearing in Claude Desktop
Solution: Verify the config file path is correct
Solution: Check that the Python path is absolute
Solution: Restart Claude Desktop after configuration changes
Issue: "Module not found" errors
Solution: Ensure dependencies are installed (
pip install -e .)Solution: Use the full Python path (e.g.,
/usr/local/bin/python3)
Issue: Authentication errors
Solution: Verify environment variables are set correctly
Solution: Check that app passwords are used (not regular passwords)
Solution: Verify SMTP/IMAP credentials are correct
Issue: Server not starting
Solution: Check logs in the
logs/directorySolution: Verify
.envfile exists and is readableSolution: Test server manually:
python main.py
π³ Docker Deployment
Docker provides a containerized way to run the Email MCP Server, ensuring consistency across different environments.
Prerequisites
Docker installed (Get Docker)
Docker Compose (optional, for multi-container setups)
Quick Start with Docker
Step 1: Build the Docker Image
docker build -t email-send-mcp .This creates a Docker image with all dependencies installed.
Step 2: Run the Container
Option A: Using Environment Variables
docker run -d \
--name email-mcp \
-p 8888:8888 \
-e SMTP_SERVER=smtp.gmail.com \
-e SMTP_PORT=587 \
-e SMTP_USERNAME=your-email@gmail.com \
-e SMTP_PASSWORD=your-app-password \
-e IMAP_SERVER=imap.gmail.com \
-e IMAP_PORT=993 \
-e IMAP_USERNAME=your-email@gmail.com \
-e IMAP_PASSWORD=your-app-password \
-e DEFAULT_FROM_EMAIL=your-email@gmail.com \
email-send-mcpOption B: Using .env File (Recommended)
docker run -d \
--name email-mcp \
-p 8888:8888 \
--env-file .env \
email-send-mcpStep 3: Verify Container is Running
# Check container status
docker ps
# View logs
docker logs email-mcp
# Follow logs in real-time
docker logs -f email-mcp
# Test health endpoint
curl http://localhost:8888/api/healthDocker Compose Setup
For easier management, use Docker Compose:
docker-compose.yml:
version: '3.8'
services:
email-mcp:
build: .
container_name: email-send-mcp
ports:
- "8888:8888"
env_file:
- .env
restart: unless-stopped
volumes:
- ./logs:/app/logs
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8888/api/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40sStart with Docker Compose:
# Start in background
docker-compose up -d
# View logs
docker-compose logs -f
# Stop
docker-compose down
# Rebuild and restart
docker-compose up -d --buildDocker Management Commands
# Stop the container
docker stop email-mcp
# Start the container
docker start email-mcp
# Restart the container
docker restart email-mcp
# Remove the container
docker rm email-mcp
# Remove the image
docker rmi email-send-mcp
# View container logs
docker logs email-mcp --tail 100
# Execute commands inside container
docker exec -it email-mcp /bin/bash
# Inspect container
docker inspect email-mcpProduction Docker Best Practices
Use Multi-Stage Builds (already in Dockerfile)
Run as Non-Root User (already configured)
Use Health Checks (see Docker Compose example)
Mount Logs as Volumes for persistence
Use Secrets Management for production credentials
Set Resource Limits:
docker run -d \
--name email-mcp \
--memory="512m" \
--cpus="0.5" \
--env-file .env \
email-send-mcpβοΈ Azure Container Apps Deployment
Deploy the Email MCP Server to Azure Container Apps for scalable, serverless hosting.
Prerequisites
Azure account with active subscription
Azure CLI installed (Install Azure CLI)
Docker installed
Deployment Steps
Step 1: Login to Azure
az login
az account set --subscription <your-subscription-id>Step 2: Create Resource Group
az group create \
--name email-mcp-rg \
--location eastusStep 3: Create Azure Container Registry (ACR)
# Create ACR
az acr create \
--resource-group email-mcp-rg \
--name emailmcpacr \
--sku Basic
# Login to ACR
az acr login --name emailmcpacrStep 4: Build and Push Image to ACR
# Build and push in one command
az acr build \
--registry emailmcpacr \
--image email-send-mcp:latest \
.
# Or build locally and push
docker build -t emailmcpacr.azurecr.io/email-send-mcp:latest .
docker push emailmcpacr.azurecr.io/email-send-mcp:latestStep 5: Create Container Apps Environment
# Create environment
az containerapp env create \
--name email-mcp-env \
--resource-group email-mcp-rg \
--location eastusStep 6: Deploy Container App
az containerapp create \
--name email-send-mcp \
--resource-group email-mcp-rg \
--environment email-mcp-env \
--image emailmcpacr.azurecr.io/email-send-mcp:latest \
--target-port 8888 \
--ingress external \
--registry-server emailmcpacr.azurecr.io \
--cpu 0.5 \
--memory 1Gi \
--min-replicas 1 \
--max-replicas 3 \
--secrets \
smtp-password=<your-app-password> \
imap-password=<your-app-password> \
--env-vars \
SMTP_SERVER=smtp.gmail.com \
SMTP_PORT=587 \
SMTP_USERNAME=secretref:smtp-password \
SMTP_PASSWORD=secretref:smtp-password \
IMAP_SERVER=imap.gmail.com \
IMAP_PORT=993 \
IMAP_USERNAME=secretref:imap-password \
IMAP_PASSWORD=secretref:imap-password \
DEFAULT_FROM_EMAIL=your-email@gmail.comStep 7: Get Application URL
az containerapp show \
--name email-send-mcp \
--resource-group email-mcp-rg \
--query properties.configuration.ingress.fqdnAzure Container Apps Features
β Auto-scaling: Automatically scales based on HTTP traffic β Zero Downtime: Seamless deployments with rolling updates β Built-in Load Balancing: Distributes traffic across replicas β HTTPS by Default: Automatic SSL/TLS certificates β Secrets Management: Secure credential storage β Monitoring: Integrated with Azure Monitor and Application Insights
Update Deployment
# Update with new image
az containerapp update \
--name email-send-mcp \
--resource-group email-mcp-rg \
--image emailmcpacr.azurecr.io/email-send-mcp:v2
# Update environment variables
az containerapp update \
--name email-send-mcp \
--resource-group email-mcp-rg \
--set-env-vars LOG_LEVEL=DEBUGMonitoring and Logs
# View logs
az containerapp logs show \
--name email-send-mcp \
--resource-group email-mcp-rg \
--follow
# View metrics
az monitor metrics list \
--resource /subscriptions/<subscription-id>/resourceGroups/email-mcp-rg/providers/Microsoft.App/containerApps/email-send-mcp \
--metric-names HttpRequestsCountCost Optimization
Use consumption plan (pay only for what you use)
Set appropriate min/max replicas
Configure scale rules based on metrics
Use reserved capacity for predictable workloads
Security Best Practices
Use Azure Key Vault for secrets
Enable Managed Identity for ACR authentication
Use Private Endpoints for internal-only access
Configure CORS policies
Enable Azure AD authentication for API access
Use VNet integration for enhanced security
ποΈ Architecture
System Architecture
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β MCP Client Layer β
β (Claude Desktop, Custom Clients, Web Applications) β
ββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββ
β MCP Protocol (HTTP/Stdio)
β
ββββββββββββββββββββββββββΌβββββββββββββββββββββββββββββββββββββ
β FastMCP Server (main.py) β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β MCP Tools Router β β
β β β’ send_email β β
β β β’ receive_emails_imap β β
β β β’ receive_emails_pop3 β β
β βββββββββββββββββββ¬ββββββββββββββββββββββββββββββββββββ β
ββββββββββββββββββββββΌββββββββββββββββββββββββββββββββββββββββ
β
ββββββββββββββ΄βββββββββββββ
β β
βββββββββΌβββββββββ ββββββββββΌβββββββββ
β EmailSender β β EmailReceiver β
β (SMTP) β β (IMAP/POP3) β
βββββββββ¬βββββββββ ββββββββββ¬βββββββββ
β β
β ββββββββββββββββββββββββ΄βββββ
β β Validators & Utils β
β β β’ Email validation β
β β β’ Normalization β
β β β’ Formatting β
β ββββββββββββββββββββββββββββ¬β
β β
ββββββββββββββββββ¬ββββββββββββ
β
ββββββββββββββββββΌββββββββββββββββ
β Email Service Providers β
β β’ Gmail (SMTP/IMAP) β
β β’ Outlook (SMTP/IMAP) β
β β’ Yahoo (SMTP/IMAP) β
β β’ Custom SMTP/IMAP Servers β
ββββββββββββββββββββββββββββββββββProject Structure
email-send-mcp/
βββ main.py # Entry point - initializes and runs FastMCP server
βββ src/
β βββ __init__.py # Package initialization
β βββ config.py # Configuration management with Pydantic Settings
β βββ server.py # FastMCP server setup and MCP tools definition
β βββ services/
β β βββ __init__.py
β β βββ email_sender.py # SMTP email sending service
β β βββ email_receiver.py # IMAP/POP3 email receiving service
β βββ utils/
β βββ __init__.py
β βββ validators.py # Email validation and formatting utilities
βββ tests/ # Test suite
β βββ __init__.py
β βββ test_config.py # Configuration tests
β βββ test_validators.py # Email validation tests
β βββ ...
βββ logs/ # Application logs (auto-created)
βββ Dockerfile # Container configuration
βββ docker-compose.yml # Docker Compose setup (optional)
βββ pyproject.toml # Project dependencies and metadata
βββ .env.example # Example environment configuration
βββ .env # Actual environment configuration (not in git)
βββ README.md # This file
βββ QUICKSTART.md # Quick start guide
βββ EMAIL_PROVIDERS.md # Provider-specific configurations
βββ CONTRIBUTING.md # Contribution guidelines
βββ LICENSE # MIT License
βββ examples.py # Usage examples
Component Details
1. main.py - Application Entry Point
Loads environment variables from
.envConfigures logging (console + file)
Initializes FastMCP server
Sets up SMTP, IMAP, POP3 services
Starts HTTP server on port 8888
2. src/config.py - Configuration Management
Uses Pydantic Settings for type-safe configuration
Loads settings from environment variables
Validates port numbers and required fields
Provides singleton pattern for settings access
Supports multiple email providers
3. src/server.py - MCP Server
Defines MCP tools using
@mcp.tool()decoratorIntegrates EmailSender and EmailReceiver services
Handles tool parameter validation
Formats responses for AI assistants
Provides health check endpoint
4. src/services/email_sender.py - SMTP Service
Async SMTP client using
aiosmtplibSupports TLS (port 587) and SSL (port 465)
Validates all email addresses before sending
Handles file attachments with size limits
Supports CC, BCC, and HTML emails
Smart MIME message construction
5. src/services/email_receiver.py - IMAP/POP3 Service
Async IMAP client using
aioimaplibSync POP3 client using
poplibFolder/mailbox support (IMAP)
Unread filtering (IMAP)
Email parsing with proper encoding handling
Attachment metadata extraction
6. src/utils/validators.py - Email Utilities
RFC-compliant email validation using
email-validatorEmail normalization and formatting
Batch email validation
Display name formatting
Technology Stack
Component | Technology | Purpose |
MCP Framework | FastMCP 2.0 | Model Context Protocol server implementation |
SMTP Client | aiosmtplib | Async SMTP email sending |
IMAP Client | aioimaplib | Async IMAP email receiving |
POP3 Client | poplib (stdlib) | Sync POP3 email receiving |
Email Validation | email-validator | RFC-compliant email address validation |
Settings Management | Pydantic Settings | Type-safe configuration |
Environment Vars | python-dotenv | .env file support |
HTTP Server | FastAPI (via FastMCP) | HTTP transport for MCP |
Package Manager | uv | Fast Python package management |
Testing | pytest, pytest-asyncio | Test framework |
Code Quality | black, isort, mypy, ruff | Code formatting and linting |
Data Flow
Sending an Email
1. MCP Client β send_email tool call
2. FastMCP Server β validates parameters
3. EmailSender β validates recipient addresses
4. EmailSender β constructs MIME message
5. EmailSender β connects to SMTP server (TLS/SSL)
6. EmailSender β authenticates with credentials
7. EmailSender β sends email
8. EmailSender β returns success/error status
9. FastMCP Server β formats response
10. Response β returns to MCP ClientReceiving Emails
1. MCP Client β receive_emails_imap tool call
2. FastMCP Server β validates parameters
3. EmailReceiver β connects to IMAP server (SSL)
4. EmailReceiver β authenticates with credentials
5. EmailReceiver β selects mailbox/folder
6. EmailReceiver β searches for emails (filtered)
7. EmailReceiver β fetches email messages
8. EmailReceiver β parses email content
9. EmailReceiver β extracts metadata and attachments
10. EmailReceiver β returns formatted email list
11. FastMCP Server β formats response
12. Response β returns to MCP ClientLogging and Monitoring
Log Location:
logs/email-send-mcp_YYYYMMDD.logLog Rotation: Daily (midnight)
Log Format:
YYYY-MM-DD HH:MM:SS - logger_name - LEVEL - messageLog Levels: DEBUG, INFO, WARNING, ERROR
Console Output: Enabled for development
Structured Logging: JSON-compatible format for cloud environments
Security Architecture
Credential Storage: Environment variables (never hardcoded)
TLS/SSL: Enforced for all email connections
Input Validation: All emails validated before processing
Attachment Validation: File size and existence checks
Error Handling: Sensitive data not exposed in errors
Logging: Passwords and secrets never logged
π§ Troubleshooting
Common Issues and Solutions
Issue: "Authentication failed" or "Invalid credentials"
Symptoms:
Error message: "535 Authentication failed" or similar
Cannot connect to SMTP/IMAP server
Solutions:
Use App Password instead of regular password
For Gmail: Create App Password
For Yahoo: Account Security β Generate app password
For Outlook: May need app-specific password or OAuth
Verify credentials in
.envfile# Check your .env file cat .env | grep -E "USERNAME|PASSWORD"Ensure 2FA is enabled (required for app passwords)
Check IMAP/SMTP access is enabled
Gmail: Settings β See all settings β Forwarding and POP/IMAP β Enable IMAP
Outlook: Settings β Sync email β POP and IMAP
Issue: "Connection timeout" or "Connection refused"
Symptoms:
Server doesn't respond
Timeout errors after 60+ seconds
Solutions:
Check firewall settings
# Test SMTP connectivity telnet smtp.gmail.com 587 # Test IMAP connectivity telnet imap.gmail.com 993Verify server addresses and ports
SMTP: Usually port 587 (TLS) or 465 (SSL)
IMAP: Usually port 993 (SSL)
POP3: Usually port 995 (SSL)
Check if your ISP blocks SMTP/IMAP ports
Some ISPs block port 25, 587
Try using VPN or alternative network
Verify TLS/SSL settings match your provider
# For port 587, use: SMTP_USE_TLS=true # For port 465, use: SMTP_USE_TLS=true # aiosmtplib handles this automatically
Issue: Gmail "Less secure app access" error
Symptoms:
"Please log in via your web browser" error
Account access blocked
Solutions:
Enable 2-Factor Authentication
Go to Google Account Security
Turn on 2-Step Verification
Generate and use App Password
Visit App Passwords
Select "Mail" and your device
Copy the 16-character password
Use in
.envfile (remove spaces)
Never use "Less secure app access" (deprecated and insecure)
Issue: "Module not found" errors
Symptoms:
ModuleNotFoundError: No module named 'fastmcp'
ModuleNotFoundError: No module named 'dotenv'Solutions:
# Reinstall dependencies
pip install -e .
# Or with uv
uv pip install -e .
# For development dependencies
pip install -e ".[dev]"
# Verify installation
python -c "import fastmcp; print('FastMCP OK')"
python -c "import dotenv; print('dotenv OK')"Issue: "Permission denied" or "File not found" (attachments)
Symptoms:
"Attachment file not found: /path/to/file.pdf"
Permission errors when reading attachment files
Solutions:
Use absolute paths for attachments
# β Good attachments=["/home/user/documents/report.pdf"] # β Bad attachments=["report.pdf"]Verify file exists and is readable
ls -la /path/to/file.pdf # Should show readable permissionsCheck file size
# Default max is 25MB du -h /path/to/file.pdf
Issue: "Tools not appearing in Claude Desktop"
Symptoms:
MCP server configured but tools don't show up
Claude doesn't recognize email commands
Solutions:
Verify config file path is correct
macOS:
~/Library/Application Support/Claude/claude_desktop_config.jsonWindows:
%APPDATA%\Claude\claude_desktop_config.json
Use absolute paths in configuration
{ "mcpServers": { "email": { "command": "python", "args": ["/absolute/path/to/email-send-mcp/main.py"] } } }Restart Claude Desktop completely
Quit application (not just close window)
Restart from Applications/Start Menu
Check server logs
# View logs to see if server started tail -f logs/email-send-mcp_*.log
Issue: Email sends but recipient doesn't receive it
Symptoms:
"Email sent successfully" message
But recipient never receives the email
Solutions:
Check recipient's spam/junk folder
Verify sender email is correct
DEFAULT_FROM_EMAIL=your-actual-email@gmail.comCheck email provider's sent folder
Verify recipient email address is valid
# Test email validation from src.utils.validators import validate_email_address is_valid, result = validate_email_address("recipient@example.com") print(f"Valid: {is_valid}, Result: {result}")Check for bounce-back emails in your inbox
Issue: "Maximum attachment size exceeded"
Symptoms:
Error about attachment size limit
Solutions:
Check file size
du -h attachment.pdfIncrease limit in
.envMAX_ATTACHMENT_SIZE_MB=50 # Default is 25Compress large files before attaching
Use cloud storage links for very large files
Issue: Cannot receive emails / Empty inbox
Symptoms:
"No emails found" message
IMAP returns empty results
Solutions:
Verify IMAP credentials are correct
IMAP_USERNAME=your-email@gmail.com IMAP_PASSWORD=your-app-passwordCheck mailbox name is correct
# Common mailbox names receive_emails_imap(mailbox="INBOX") # β receive_emails_imap(mailbox="Sent") # β receive_emails_imap(mailbox="inbox") # β Case-sensitiveVerify emails exist in that folder
Check via web interface
Try different folder: "Sent", "Drafts", etc.
Increase limit parameter
receive_emails_imap(limit=50) # Default is 10
Debugging Tips
Enable Debug Logging
Add to .env:
LOG_LEVEL=DEBUG
DEBUG=trueRestart server and check logs:
tail -f logs/email-send-mcp_$(date +%Y%m%d).logTest SMTP Connection Manually
import asyncio
from src.services.email_sender import EmailSender
async def test():
sender = EmailSender()
result = await sender.send_email(
recipient="test@example.com",
subject="Test",
body="Testing SMTP connection"
)
print(result)
asyncio.run(test())Test IMAP Connection Manually
import asyncio
from src.services.email_receiver import EmailReceiver
async def test():
receiver = EmailReceiver()
result = await receiver.receive_emails_imap(limit=1)
print(result)
asyncio.run(test())Check Environment Variables
# Verify .env is being loaded
python -c "from src.config import get_settings; s = get_settings(); print(f'SMTP: {s.SMTP_SERVER}:{s.SMTP_PORT}')"Getting Help
If you're still experiencing issues:
Check existing issues: GitHub Issues
Search discussions: GitHub Discussions
Open a new issue:
Include error messages
Include relevant logs (remove sensitive data)
Include your configuration (without passwords)
Include steps to reproduce
π₯ Contributing
We welcome contributions! Here's how you can help:
Quick Start for Contributors
Fork and clone the repository
git clone https://github.com/YOUR_USERNAME/email-send-mcp.git cd email-send-mcpInstall development dependencies
pip install -e ".[dev]"Create a branch
git checkout -b feature/your-feature-nameMake your changes and add tests
Run tests and linting
# Run tests pytest tests/ -v # Format code black src/ tests/ main.py isort src/ tests/ main.py # Type checking mypy src/ # Linting ruff check src/ tests/Commit and push
git commit -m "Add feature: description" git push origin feature/your-feature-nameCreate Pull Request
Contribution Guidelines
Code Style: Follow PEP 8, use Black formatter
Tests: Add tests for new features
Documentation: Update README and docstrings
Commits: Write clear commit messages
Issues: Link PRs to related issues
For detailed guidelines, see CONTRIBUTING.md.
π Additional Resources
QUICKSTART.md - Get started in 5 minutes
EMAIL_PROVIDERS.md - Provider-specific configurations
CONTRIBUTING.md - Contribution guidelines
examples.py - Code examples
FastMCP Documentation - MCP framework docs
Model Context Protocol - MCP specification
π License
This project is licensed under the MIT License - see the LICENSE file for details.
π Acknowledgments
FastMCP - Excellent MCP framework by @jlowin
Anthropic - Model Context Protocol specification
Contributors - Thank you to all contributors!
π Support
Issues: GitHub Issues
Discussions: GitHub Discussions
Email: For private inquiries only
β Star this repo if you find it useful!
Made with β€οΈ for the MCP community
This server cannot be installed
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.