Skip to main content
Glama
bradsjm

mail-smtp-mcp

mail-smtp-mcp

A TypeScript MCP (Model Context Protocol) server for sending email via SMTP, designed for code agents. Exposes a compact, LLM-optimized tool surface with strict policy controls and validation.

Quick Start

Run directly via npx with your MCP client:

npx -y @bradsjm/mail-smtp-mcp

Configure the required environment variables before starting (see Configuration below).

Local Development

pnpm install
pnpm dev

Build for production:

pnpm build

Configuration

The server loads configuration from environment variables. A local .env file is also supported via dotenv (do not commit secrets).

Account Configuration

Configure one or more SMTP accounts using the following pattern:

MAIL_SMTP_<ACCOUNT_ID>_<SETTING>=value

Setting

Required

Default

Description

HOST

Yes

-

SMTP server hostname

PORT

No

587 (if SECURE=false), 465 (if SECURE=true)

SMTP server port

SECURE

No

false

Use SSL/TLS (true) or STARTTLS (false)

USER

Yes

-

SMTP authentication username

PASS

Yes

-

SMTP authentication password

FROM

No

-

Default sender email address

Example - Default Account:

MAIL_SMTP_DEFAULT_HOST=smtp.gmail.com
MAIL_SMTP_DEFAULT_PORT=587
MAIL_SMTP_DEFAULT_SECURE=false
MAIL_SMTP_DEFAULT_USER=you@gmail.com
MAIL_SMTP_DEFAULT_PASS=your-app-password
MAIL_SMTP_DEFAULT_FROM=you@gmail.com

Example - Multiple Accounts:

# Default account
MAIL_SMTP_DEFAULT_HOST=smtp.gmail.com
MAIL_SMTP_DEFAULT_USER=you@gmail.com
MAIL_SMTP_DEFAULT_PASS=app-password-1

# Work account
MAIL_SMTP_WORK_HOST=smtp.company.com
MAIL_SMTP_WORK_PORT=465
MAIL_SMTP_WORK_SECURE=true
MAIL_SMTP_WORK_USER=you@company.com
MAIL_SMTP_WORK_PASS=company-password
MAIL_SMTP_WORK_FROM=you@company.com

Send Gate

Sending is disabled by default for security. Enable with:

MAIL_SMTP_SEND_ENABLED=true

Allowlist Policy (Optional)

Restrict recipients to specific domains or email addresses:

MAIL_SMTP_ALLOWLIST_DOMAINS=example.com,example.org
MAIL_SMTP_ALLOWLIST_ADDRESSES=alice@example.com,bob@example.org

Policy Limits

Configure operational limits (defaults shown):

Variable

Default

Description

MAIL_SMTP_MAX_RECIPIENTS

10

Maximum recipients per message

MAIL_SMTP_MAX_MESSAGE_BYTES

2,500,000

Maximum total message size (~2.4 MB)

MAIL_SMTP_MAX_ATTACHMENTS

5

Maximum number of attachments

MAIL_SMTP_MAX_ATTACHMENT_BYTES

2,000,000

Maximum size per attachment (~1.9 MB)

MAIL_SMTP_MAX_TEXT_CHARS

20,000

Maximum characters in plain text body

MAIL_SMTP_MAX_HTML_CHARS

50,000

Maximum characters in HTML body

MAIL_SMTP_CONNECT_TIMEOUT_MS

10,000

SMTP connection timeout (ms)

MAIL_SMTP_SOCKET_TIMEOUT_MS

20,000

SMTP socket timeout (ms)

Tools Overview

Tool

Purpose

Requires Send Enabled?

smtp_list_accounts

List configured SMTP accounts

No

smtp_verify_account

Verify SMTP connectivity without sending email

No

smtp_send_message

Send or validate an outbound email

Yes (unless dry_run)

Tool Details

smtp_list_accounts

Lists configured SMTP accounts with non-sensitive metadata.

Input:

{
  "account_id": "default"  // Optional - filter by specific account
}

Response:

{
  "summary": "Found 2 configured SMTP account(s).",
  "data": {
    "accounts": [
      {
        "account_id": "default",
        "host": "smtp.gmail.com",
        "port": 587,
        "secure": false,
        "default_from": "you@gmail.com"
      },
      {
        "account_id": "work",
        "host": "smtp.company.com",
        "port": 465,
        "secure": true
      }
    ]
  },
  "_meta": {
    "send_enabled": true,
    "limits": {
      "max_recipients": 10,
      "max_message_bytes": 2500000,
      "max_attachments": 5,
      "max_attachment_bytes": 2000000
    }
  }
}

smtp_verify_account

Verifies that an SMTP account can connect and authenticate without sending an email.

Input:

{
  "account_id": "default"  // Defaults to "default"
}

Verification Flow:

┌─────────────────┐
│   Load Account  │
│   Config        │
└────────┬────────┘
         │
         ▼
┌─────────────────┐
│ Create SMTP     │
│ Transport       │
└────────┬────────┘
         │
         ▼
┌─────────────────┐
│ Verify Connect  │
│ & Authenticate  │
└────────┬────────┘
         │
         ▼
┌─────────────────┐
│ Return Status   │
│ (ok / error)    │
└─────────────────┘

Response:

{
  "summary": "SMTP account default verified successfully.",
  "data": {
    "account_id": "default",
    "status": "ok"
  }
}

smtp_send_message

Sends or validates an outbound email via SMTP with comprehensive validation.

Input:

{
  "account_id": "default",           // Defaults to "default"
  "from": "sender@example.com",      // Optional - override account default
  "to": ["recipient@example.com"],   // Required - string or array
  "cc": ["cc@example.com"],          // Optional
  "bcc": ["bcc@example.com"],        // Optional
  "reply_to": "reply@example.com",   // Optional
  "subject": "Test Email",           // Required
  "text_body": "Plain text here",    // Optional
  "html_body": "<p>HTML here</p>",  // Optional
  "attachments": [                   // Optional
    {
      "filename": "document.pdf",
      "content_base64": "JVBERi0xL...",
      "content_type": "application/pdf"
    }
  ],
  "dry_run": false                   // Optional - validate without sending
}

Send Flow:

┌──────────────────┐
│ Validate Input   │
│ - Email format   │
│ - Header inject. │
│ - Body lengths   │
└────────┬─────────┘
         │
         ▼
┌──────────────────┐
│ Enforce Policy   │
│ - Recipient      │
│   allowlist      │
│ - Size limits    │
│ - Attachment     │
│   limits         │
└────────┬─────────┘
         │
         ▼
┌──────────────────┐
│ Build Message    │
│ - Parse attach-  │
│   ments (base64) │
│ - Estimate size  │
└────────┬─────────┘
         │
         ▼
         ┌──────────┐
         │ dry_run? │
         └────┬─────┘
              │
         ┌────┴────┐
         │         │
        Yes       No
         │         │
         ▼         ▼
┌────────────┐  ┌──────────────┐
│ Return     │  │ Send via     │
│ Validation │  │ SMTP         │
│ Results    │  │ Transport    │
└────────────┘  └──────┬───────┘
                       │
                       ▼
              ┌────────────────┐
              │ Return Send    │
              │ Results        │
              └────────────────┘

Response (Success):

{
  "summary": "Sent message to 3 recipient(s).",
  "data": {
    "account_id": "default",
    "dry_run": false,
    "envelope": {
      "from": "sender@example.com",
      "to": ["recipient@example.com"],
      "cc": ["cc@example.com"],
      "bcc": ["bcc@example.com"]
    },
    "message_id": "<abc123@example.com>",
    "accepted": ["recipient@example.com", "cc@example.com", "bcc@example.com"],
    "rejected": []
  }
}

Response (Dry Run):

{
  "summary": "Validated message for 3 recipient(s).",
  "data": {
    "account_id": "default",
    "dry_run": true,
    "envelope": {
      "from": "sender@example.com",
      "to": ["recipient@example.com"],
      "cc": ["cc@example.com"],
      "bcc": ["bcc@example.com"]
    },
    "size_bytes_estimate": 12500
  }
}

Response Format

All tool responses use a consistent JSON structure returned as MCP text content:

{
  "summary": "Human-readable status message",
  "data": { /* Tool-specific structured data */ },
  "_meta": { /* Optional metadata (e.g., policy info) */ }
}

Hard Maximum Limits

The following absolute upper bounds cannot be exceeded regardless of policy settings:

Resource

Hard Limit

Recipients per message

50

Attachments per message

10

Attachment size

5,000,000 bytes (~4.8 MB)

Plain text body characters

100,000

HTML body characters

200,000

Subject characters

256

Security Notes

  • No HTTP Transport: This server only supports stdio transport for security. HTTP endpoints are intentionally not exposed.

  • Credential Handling: SMTP credentials are never logged or returned in tool responses.

  • Header Injection Protection: All email addresses and subject fields are validated to reject CR/LF characters that could be used for header injection.

  • Filename Safety: Attachment filenames are validated to prevent path traversal attacks.

  • Send Gate: Sending is disabled by default and must be explicitly enabled via MAIL_SMTP_SEND_ENABLED=true.

  • Dry Run Mode: Use dry_run: true to validate messages and policies without actually sending emails.

MCP Client Integration

Standard npx Configuration

Most MCP-enabled applications can spawn this server using:

{
  "command": "npx",
  "args": ["-y", "@bradsjm/mail-smtp-mcp"],
  "env": {
    "MAIL_SMTP_DEFAULT_HOST": "smtp.gmail.com",
    "MAIL_SMTP_DEFAULT_PORT": "587",
    "MAIL_SMTP_DEFAULT_SECURE": "false",
    "MAIL_SMTP_DEFAULT_USER": "you@gmail.com",
    "MAIL_SMTP_DEFAULT_PASS": "your-app-password",
    "MAIL_SMTP_DEFAULT_FROM": "you@gmail.com",
    "MAIL_SMTP_SEND_ENABLED": "true"
  }
}

Development Configuration

For local development without publishing:

{
  "command": "node",
  "args": ["/path/to/mail-smtp-mcp/dist/index.js"],
  "env": {
    "MAIL_SMTP_DEFAULT_HOST": "smtp.gmail.com",
    "MAIL_SMTP_DEFAULT_USER": "you@gmail.com",
    "MAIL_SMTP_DEFAULT_PASS": "your-app-password",
    "MAIL_SMTP_SEND_ENABLED": "true"
  }
}

Development

# Install dependencies
pnpm install

# Run in development mode (TypeScript)
pnpm dev

# Build for production
pnpm build

# Run tests
pnpm test

# Type checking
pnpm typecheck

# Linting
pnpm lint

# Format code
pnpm format:write

Run all quality checks:

pnpm check

License

See LICENSE file for details.

Related MCP Connectors

Appeared in Searches

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/bradsjm/mail-smtp-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server