Skip to content

Latest commit

 

History

121 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

OwlMail

🦉 A Go mail development and testing server with MailDev-style workflow compatibility and OwlMail-specific APIs

Go Version License MailDev Workflows Go Report Card codecov

🌍 Languages / 语言 / Sprachen / Langues / Lingue / 言語 / 언어


OwlMail is an SMTP server and web interface for development and testing environments. It supports common MailDev workflows while providing its own versioned API, native WebSocket protocol, webhooks, and browser notifications. Review the documented compatibility boundary before migrating API or Socket.IO clients.

📸 Preview

OwlMail Preview

🎥 Demo Video

Demo Video

✨ Features

Core Features

  • SMTP Server - Receives and stores all sent emails (default port 1025)
  • Web Interface - View and manage emails through a browser (default port 1080)
  • Email Persistence - Emails saved as .eml files, supports loading from directory
  • Email Relay - Supports forwarding emails to real SMTP servers
  • Auto Relay - Supports automatically forwarding all emails with rule filtering
  • Webhook Forwarding - Sends matching new emails to generic HTTP webhooks with custom payload templates
  • ⚠️ Inbound SMTP Authentication - Configuration flags exist, but unauthenticated senders are not currently rejected
  • TLS/STARTTLS - Supports encrypted connections
  • SMTPS - Supports direct TLS connection on port 465 when SMTP TLS is enabled

Enhanced Features

  • 🆕 Batch Operations - Batch delete, batch mark as read
  • 🆕 Browser Notifications - Optional live notifications for newly received email
  • 🆕 Email Statistics - Get email statistics
  • 🆕 Email Preview - Lightweight email preview API
  • 🆕 Email Export - Export emails as ZIP files
  • 🆕 Configuration Management API - Complete configuration management (GET/PUT/PATCH)
  • 🆕 Powerful Search - Full-text search, date range filtering, sorting
  • 🆕 Improved RESTful API - More standardized API design (/api/v1/*)
  • 🆕 Built-in Help - Local bilingual guide available from the inbox or at /help

Compatibility

  • MailDev-style Workflow Routes - Common email, relay, configuration, and health workflows have OwlMail routes
  • Selected MailDev Environment Aliases - Supported MAILDEV_* names are listed in the configuration table
  • Auto Relay Rules - Supports MailDev-style JSON allow/deny rules
  • ⚠️ Documented Differences - API prefixes and payloads, read side effects, and live-event protocols are not identical

Deployment Characteristics

  • Single Binary - Compiled executable with the UI and help assets embedded
  • No Language Runtime - The deployed binary does not require Node.js or Go
  • Explicit Concurrency Controls - Webhook delivery can be bounded or intentionally unlimited

The repository does not publish a reproducible cross-project benchmark. Measure startup, memory, and throughput with your own mail volume, storage, TLS, and webhook targets before making capacity claims.

🚀 Quick Start

Installation

Build from Source

# Clone repository
git clone https://github.com/soulteary/owlmail.git
cd owlmail

# Build
go build -o owlmail ./cmd/owlmail

# Run
./owlmail

Install with Go

go install github.com/soulteary/owlmail/cmd/owlmail@latest
owlmail

Basic Usage

# Start with default configuration (SMTP: 1025, Web: 1080)
./owlmail

# Custom ports
./owlmail -smtp 1025 -web 1080

# Use environment variables
export MAILDEV_SMTP_PORT=1025
export MAILDEV_WEB_PORT=1080
./owlmail

Open http://localhost:1080 for the inbox. The Help button opens the local guide at http://localhost:1080/help. Both pages and their assets are embedded in the executable, so installed binaries do not need a separate web folder.

Docker Usage

Pull from GitHub Container Registry (Recommended)

The easiest way to use OwlMail is to pull the pre-built image from GitHub Container Registry:

# Pull release 0.5.0
docker pull ghcr.io/soulteary/owlmail:0.5.0

# Pull an image for one exact commit (example)
docker pull ghcr.io/soulteary/owlmail:sha-b130f33

# Run container
docker run -d \
  -p 1025:1025 \
  -p 1080:1080 \
  --name owlmail \
  ghcr.io/soulteary/owlmail:0.5.0

Available Tags:

  • 0.5.0 - Exact release tag; 0.5 and 0 move with later releases in those series
  • sha-<commit> - Image for a specific short commit SHA (for example, sha-b130f33)
  • main - Moving image from the latest main branch build
  • latest - Moving default-branch image; it is not a stable-release selector

Multi-Architecture Support: The image supports both linux/amd64 and linux/arm64 architectures. Docker will automatically pull the correct image for your platform.

View all available images: GitHub Packages

Build from Source

Basic Build (Single Architecture)
# Build image for current architecture
docker build -t owlmail .

# Run container
docker run -d \
  -p 1025:1025 \
  -p 1080:1080 \
  --name owlmail \
  owlmail
Multi-Architecture Build

For aarch64 (ARM64) or other architectures, use Docker Buildx:

# Enable buildx (if not already enabled)
docker buildx create --use --name multiarch-builder

# Build for multiple architectures
docker buildx build \
  --platform linux/amd64,linux/arm64 \
  -t owlmail:latest \
  --load .

# Or build and push to registry
docker buildx build \
  --platform linux/amd64,linux/arm64 \
  -t your-registry/owlmail:latest \
  --push .

# Build for specific architecture (e.g., aarch64/arm64)
docker buildx build \
  --platform linux/arm64 \
  -t owlmail:latest \
  --load .

Note: The Dockerfile now supports multi-architecture builds using TARGETOS and TARGETARCH build arguments, which are automatically set by Docker Buildx.

Browser Notifications

Browser notifications are off by default. Click Notifications off in the inbox header to request permission and enable them. The preference is stored in that browser and can be switched off from the same button. Only messages arriving through the live WebSocket after notifications are enabled create a notification; loading existing messages does not.

The Notifications API requires HTTPS or a trusted local origin such as http://localhost. If permission was denied, allow OwlMail in the browser's site settings before trying again. Notifications show the subject and sender but not the message body; clicking one focuses OwlMail and opens the message.

📖 Configuration Options

Command Line Arguments

Argument Environment Variable Default Description
-smtp MAILDEV_SMTP_PORT / OWLMAIL_SMTP_PORT 1025 SMTP port
-ip MAILDEV_IP / OWLMAIL_SMTP_HOST localhost SMTP host
-web MAILDEV_WEB_PORT / OWLMAIL_WEB_PORT 1080 Web API port
-web-ip MAILDEV_WEB_IP / OWLMAIL_WEB_HOST localhost Web API host
-mail-directory MAILDEV_MAIL_DIRECTORY / OWLMAIL_MAIL_DIR - Mail storage directory
-web-user MAILDEV_WEB_USER / OWLMAIL_WEB_USER - HTTP Basic Auth username
-web-password MAILDEV_WEB_PASS / OWLMAIL_WEB_PASSWORD - HTTP Basic Auth password
-https MAILDEV_HTTPS / OWLMAIL_HTTPS_ENABLED false Enable HTTPS
-https-cert MAILDEV_HTTPS_CERT / OWLMAIL_HTTPS_CERT - HTTPS certificate file
-https-key MAILDEV_HTTPS_KEY / OWLMAIL_HTTPS_KEY - HTTPS private key file
-outgoing-host MAILDEV_OUTGOING_HOST / OWLMAIL_OUTGOING_HOST - Outgoing SMTP host
-outgoing-port MAILDEV_OUTGOING_PORT / OWLMAIL_OUTGOING_PORT 587 Outgoing SMTP port
-outgoing-user MAILDEV_OUTGOING_USER / OWLMAIL_OUTGOING_USER - Outgoing SMTP username
-outgoing-pass MAILDEV_OUTGOING_PASS / OWLMAIL_OUTGOING_PASSWORD - Outgoing SMTP password
-outgoing-secure MAILDEV_OUTGOING_SECURE / OWLMAIL_OUTGOING_SECURE false Outgoing SMTP TLS
-auto-relay MAILDEV_AUTO_RELAY / OWLMAIL_AUTO_RELAY false Enable auto relay
-auto-relay-addr MAILDEV_AUTO_RELAY_ADDR / OWLMAIL_AUTO_RELAY_ADDR - Auto relay address
-auto-relay-rules MAILDEV_AUTO_RELAY_RULES / OWLMAIL_AUTO_RELAY_RULES - Auto relay rules file
-webhook-config OWLMAIL_WEBHOOK_CONFIG - JSON webhook forwarding configuration file
-webhook-max-concurrency OWLMAIL_WEBHOOK_MAX_CONCURRENCY 8 Concurrent email webhook deliveries; 0 disables the limit
-smtp-user MAILDEV_INCOMING_USER / OWLMAIL_SMTP_USER - Inbound SMTP username setting; not currently enforced
-smtp-password MAILDEV_INCOMING_PASS / OWLMAIL_SMTP_PASSWORD - Inbound SMTP password setting; not currently enforced
-tls MAILDEV_INCOMING_SECURE / OWLMAIL_TLS_ENABLED false Enable SMTP TLS
-tls-cert MAILDEV_INCOMING_CERT / OWLMAIL_TLS_CERT - SMTP TLS certificate file
-tls-key MAILDEV_INCOMING_KEY / OWLMAIL_TLS_KEY - SMTP TLS private key file
-log-level MAILDEV_VERBOSE / MAILDEV_SILENT / OWLMAIL_LOG_LEVEL normal Log level
-use-uuid-for-email-id OWLMAIL_USE_UUID_FOR_EMAIL_ID false Use UUID for email IDs (default: 8-character random string)

When HTTP Basic Auth is enabled, browser API and WebSocket requests are limited to OwlMail's own origin. Command-line and server-to-server clients that omit the browser Origin header continue to work normally.

Web authentication also fails closed when only one credential is configured:

Configured values Effective credentials
Neither value Authentication disabled
Username only The username plus a cryptographically random 32-character temporary password, printed once to stderr at startup
Password only Username admin plus the configured password
Both values The configured username and password

A generated password changes on every restart. Read it from the process output (docker logs owlmail for the container example), or configure both values for stable credentials. Startup fails if the generated password cannot be written to stderr. Basic Auth credentials should only be used over localhost or HTTPS.

Environment Variable Compatibility

OwlMail supports the MailDev environment aliases shown in the table above, preferring them over the corresponding OWLMAIL_* variables. Options that are not listed are not supported automatically.

# Use MailDev environment variables directly (recommended)
export MAILDEV_SMTP_PORT=1025
export MAILDEV_WEB_PORT=1080
export MAILDEV_OUTGOING_HOST=smtp.gmail.com
./owlmail

# Or use OwlMail environment variables
export OWLMAIL_SMTP_PORT=1025
export OWLMAIL_WEB_PORT=1080
./owlmail

📡 API Documentation

API Response Format

OwlMail uses a standardized API response format:

Success Response:

{
  "code": "EMAIL_DELETED",
  "message": "Email deleted",
  "data": { ... }
}

Error Response:

{
  "code": "EMAIL_NOT_FOUND",
  "error": "EMAIL_NOT_FOUND",
  "message": "Email not found"
}

The code field contains standardized error/success codes that can be used for internationalization. The message field provides English text for backward compatibility.

Email ID Format

OwlMail supports two email ID formats, and all API endpoints are compatible with both:

  • 8-character random string: Default format, e.g., aB3dEfGh
  • UUID format: 36-character standard UUID, e.g., 550e8400-e29b-41d4-a716-446655440000

When using the :id parameter in API requests, you can use either format. For example:

  • GET /email/aB3dEfGh - Using random string ID
  • GET /email/550e8400-e29b-41d4-a716-446655440000 - Using UUID ID

MailDev-style Compatibility API

OwlMail retains unversioned routes for common MailDev-style workflows. They are not exact current MailDev API equivalents; see the compatibility boundary in the API reference.

Email Operations

  • GET /email - Get all emails (supports pagination and filtering)
    • Query parameters:
      • limit (default: 50, max: 1000) - Number of emails to return
      • offset (default: 0) - Number of emails to skip
      • q - Full-text search query
      • from - Filter by sender email address
      • to - Filter by recipient email address
      • dateFrom - Filter by date from (YYYY-MM-DD format)
      • dateTo - Filter by date to (YYYY-MM-DD format)
      • read - Filter by read status (true/false)
      • sortBy - Sort by field (time, subject, from, size)
      • sortOrder - Sort order (asc, desc, default: desc)
    • Example: GET /email?limit=20&offset=0&q=test&sortBy=time&sortOrder=desc
  • GET /email/:id - Get single email
  • DELETE /email/:id - Delete single email
  • DELETE /email/all - Delete all emails
  • PATCH /email/read-all - Mark all emails as read
  • PATCH /email/:id/read - Mark single email as read

Email Content

  • GET /email/:id/html - Get email HTML content
  • GET /email/:id/attachment/:filename - Download attachment
  • GET /email/:id/download - Download raw .eml file
  • GET /email/:id/source - Get email raw source

Email Relay

  • POST /email/:id/relay - Relay email to configured SMTP server
  • POST /email/:id/relay/:relayTo - Relay email to specific address

Configuration and System

  • GET /config - Get configuration information
  • GET /healthz - Health check
  • GET /reloadMailsFromDirectory - Reload emails from directory
  • GET /socket.io - WebSocket connection (standard WebSocket, not Socket.IO)

OwlMail Enhanced API

Email Statistics and Preview

  • GET /email/stats - Get email statistics
  • GET /email/preview - Get email preview (lightweight)

Batch Operations

  • POST /email/batch/delete - Batch delete emails
  • POST /email/batch/read - Batch mark as read

Email Export

  • GET /email/export - Export emails as ZIP file

Configuration Management

  • GET /config/outgoing - Get outgoing configuration
  • PUT /config/outgoing - Update outgoing configuration
  • PATCH /config/outgoing - Partially update outgoing configuration

Improved RESTful API (/api/v1/*)

OwlMail provides a more standardized RESTful API design:

  • GET /api/v1/emails - Get all emails (plural resource)
    • Query parameters: Same as GET /email (limit, offset, q, from, to, dateFrom, dateTo, read, sortBy, sortOrder)
    • Example: GET /api/v1/emails?limit=20&offset=0&q=test&sortBy=time&sortOrder=desc
  • GET /api/v1/emails/:id - Get single email
  • DELETE /api/v1/emails/:id - Delete single email
  • DELETE /api/v1/emails - Delete all emails
  • DELETE /api/v1/emails/batch - Batch delete
  • PATCH /api/v1/emails/read - Mark all emails as read
  • PATCH /api/v1/emails/:id/read - Mark single email as read
  • PATCH /api/v1/emails/batch/read - Batch mark as read
  • GET /api/v1/emails/stats - Email statistics
  • GET /api/v1/emails/preview - Email preview
  • GET /api/v1/emails/export - Export emails
  • POST /api/v1/emails/reload - Reload emails
  • GET /api/v1/settings - Get all settings
  • GET /api/v1/settings/outgoing - Get outgoing configuration
  • PUT /api/v1/settings/outgoing - Update outgoing configuration
  • PATCH /api/v1/settings/outgoing - Partially update outgoing configuration
  • GET /api/v1/health - Health check
  • GET /api/v1/version - Version info
  • GET /api/v1/ws - WebSocket connection

For the current contract, including sub-resources, authentication, response shapes, and WebSocket events, see the API Reference.

🔧 Usage Examples

Basic Usage

# Start OwlMail
./owlmail -smtp 1025 -web 1080

# Configure SMTP in your application
SMTP_HOST=localhost
SMTP_PORT=1025

Configure Email Relay

# Relay to Gmail SMTP
./owlmail \
  -outgoing-host smtp.gmail.com \
  -outgoing-port 587 \
  -outgoing-user your-email@gmail.com \
  -outgoing-pass your-password \
  -outgoing-secure

Auto Relay Mode

# Create auto relay rules file (relay-rules.json)
cat > relay-rules.json <<EOF
[
  { "allow": "*" },
  { "deny": "*@test.com" },
  { "allow": "ok@test.com" }
]
EOF

# Start auto relay
./owlmail \
  -outgoing-host smtp.gmail.com \
  -outgoing-port 587 \
  -outgoing-user your-email@gmail.com \
  -outgoing-pass your-password \
  -auto-relay \
  -auto-relay-rules relay-rules.json

Webhook Forwarding

# Terminal 1: local test receiver
go run ./examples/webhooks/receiver

# Terminal 2: forward every new email with the default JSON payload
./owlmail -webhook-config ./examples/webhooks/minimal.json

Webhook targets support case-insensitive wildcard rules, custom JSON-safe body templates, environment-backed secrets, HMAC-SHA256 signatures, timeouts, and bounded retries. See the scenario examples for filtering, custom APIs, multiple targets, plain text, and a runnable soulteary/webhook stack. The Webhook forwarding guide is the complete reference.

Using HTTPS

./owlmail \
  -https \
  -https-cert /path/to/cert.pem \
  -https-key /path/to/key.pem \
  -web 1080

Inbound SMTP Authentication Limitation

Warning

-smtp-user and -smtp-password currently populate configuration, but the SMTP session does not reject unauthenticated senders. Do not expose the SMTP listener to untrusted networks or rely on these flags as an access-control boundary; use interface binding, firewall rules, or a private tunnel.

Using TLS

./owlmail \
  -tls \
  -tls-cert /path/to/cert.pem \
  -tls-key /path/to/key.pem \
  -smtp 1025

Note: When TLS is enabled, OwlMail automatically starts an SMTPS server on port 465 in addition to the regular SMTP server. The SMTPS server uses direct TLS connection (no STARTTLS required).

Using UUID for Email IDs

OwlMail supports two email ID formats:

  1. Default format: 8-character random string (e.g., aB3dEfGh)
  2. UUID format: 36-character standard UUID (e.g., 550e8400-e29b-41d4-a716-446655440000)

Using UUID format provides better uniqueness and traceability, especially useful for integration with external systems.

# Enable UUID using command line flag
./owlmail -use-uuid-for-email-id

# Enable UUID using environment variable
export OWLMAIL_USE_UUID_FOR_EMAIL_ID=true
./owlmail

# Use with other configurations
./owlmail \
  -use-uuid-for-email-id \
  -smtp 1025 \
  -web 1080

Notes:

  • Default uses 8-character random string, compatible with MailDev behavior
  • When UUID is enabled, all newly received emails will use UUID format IDs
  • The API supports both ID formats, allowing normal query, delete, and operation of emails
  • Existing email ID formats will not change; only new emails will use the new ID format

🔄 Migrating from MailDev

OwlMail covers common MailDev workflows, but current MailDev clients may require small, explicit adaptations. Follow the migration guide.

1. Environment Variable Compatibility

OwlMail accepts the MailDev environment variables listed in the configuration table. Verify every variable used by your deployment:

# MailDev configuration
export MAILDEV_SMTP_PORT=1025
export MAILDEV_WEB_PORT=1080
export MAILDEV_OUTGOING_HOST=smtp.gmail.com

# These listed variables can also be read by OwlMail
./owlmail

2. API Compatibility

API paths and payloads differ in current MailDev. Use OwlMail's versioned API for new integrations and adapt existing clients deliberately:

# Current MailDev API
curl http://localhost:1080/api/email

# OwlMail API
curl http://localhost:1080/api/v1/emails

3. WebSocket Adaptation

If using WebSocket, you need to change from Socket.IO to standard WebSocket:

// MailDev (Socket.IO)
const socket = io('/socket.io');
socket.on('newMail', (email) => { /* ... */ });

// OwlMail (Standard WebSocket)
const ws = new WebSocket('ws://localhost:1080/socket.io');
ws.onmessage = (event) => {
  const data = JSON.parse(event.data);
  if (data.type === 'new') { /* ... */ }
};

For detailed migration guide, see: OwlMail × MailDev: Full Feature & API Comparison and Migration White Paper

🧪 Testing

# Run all tests
go test ./...

# Run tests with coverage
go test -cover ./...

# Run tests for specific packages
go test ./internal/api/...
go test ./internal/mailserver/...

📦 Project Structure

OwlMail/
├── cmd/
│   └── owlmail/          # Main program entry
├── internal/
│   ├── api/              # Web API implementation
│   ├── common/           # Common utilities (logging, error handling)
│   ├── maildev/          # MailDev compatibility layer
│   ├── mailserver/       # SMTP server implementation
│   ├── outgoing/         # Email relay implementation
│   ├── types/            # Type definitions
│   └── webhook/          # Webhook filtering, templates, signing, and delivery
├── docs/                 # API, operations, webhook, and migration documentation
├── examples/             # Runnable integration examples
├── tests/                # Browser and documentation contract tests
├── web/                  # Embedded web frontend and local help assets
├── go.mod                # Go module definition
└── README.md             # This document

🤝 Contributing

Contributions are welcome! Please follow these steps:

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/AmazingFeature)
  3. Commit your changes (git commit -m 'Add some AmazingFeature')
  4. Push to the branch (git push origin feature/AmazingFeature)
  5. Open a Pull Request

📄 License

This project is licensed under the MIT License - see the LICENSE file for details.

🙏 Acknowledgments

📚 Related Documentation

🐛 Issue Reporting

If you encounter any issues or have suggestions, please submit them in GitHub Issues.

⭐ Star History

If this project helps you, please give it a Star ⭐!


OwlMail - A Go mail development and testing server with documented MailDev migration paths 🦉

About

OwlMail is an SMTP server and web interface for development and testing environments that captures and displays all sent emails.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

73 stars

Watchers

2 watching

Forks

Releases

Packages

Contributors

Languages