The relay connection only had `secure`, so with `secure: false` nodemailer still upgraded to STARTTLS whenever the server advertised it, and there was no way to talk cleartext to such a server. Pass nodemailer's `ignoreTLS` through as `ignoreTLS` on the relay config, wired to --outgoing-ignore-tls / MAILDEV_OUTGOING_IGNORE_TLS / `outgoingIgnoreTls`.
337 lines
14 KiB
Markdown
337 lines
14 KiB
Markdown
# MailDev
|
|
|
|
[](https://www.npmjs.com/package/maildev)
|
|
[](https://www.npmjs.com/package/maildev)
|
|
[](https://hub.docker.com/r/maildev/maildev)
|
|
[](/LICENSE)
|
|
[](https://www.typescriptlang.org/)
|
|
|
|
> [!IMPORTANT]
|
|
> MailDev 3.0 has now been released which includes a complete re-write and re-structuring of the entire project while minimizing breaking changes. Read [the upgrade guide from v2](https://maildev.github.io/maildev/docs/guides/upgrading/).
|
|
|
|
If you run into any issues, please install the latest [v2](https://github.com/maildev/maildev/tree/v2) release.
|
|
|
|
**MailDev** is a simple way to test your project's generated email during development, with an easy to use web interface that runs on your machine built on top of [Node.js](http://www.nodejs.org).
|
|
|
|

|
|
|
|
## Install
|
|
|
|
```bash
|
|
npm install -g maildev
|
|
```
|
|
|
|
## Docker Run
|
|
|
|
If you want to use MailDev with [Docker](https://www.docker.com/), you can use the
|
|
[**maildev/maildev** image on Docker Hub](https://hub.docker.com/r/maildev/maildev).
|
|
For a guide for usage with Docker,
|
|
[checkout the docs](https://github.com/maildev/maildev/blob/main/docs/docker.md).
|
|
|
|
```bash
|
|
docker run -p 1080:1080 -p 1025:1025 maildev/maildev
|
|
```
|
|
|
|
## Usage
|
|
|
|
```
|
|
Usage: maildev [options]
|
|
```
|
|
|
|
| Options | Environment variable | Description |
|
|
| -------------------------------- | -------------------------- | ----------------------------------------------------------------------------------------- |
|
|
| `-s, --smtp <port>` | `MAILDEV_SMTP_PORT` | SMTP port to catch mail (default: 1025) |
|
|
| `-w, --web <port>` | `MAILDEV_WEB_PORT` | Port to run the Web GUI (default: 1080) |
|
|
| `--ip <ip address>` | `MAILDEV_IP` | IP Address to bind SMTP service to (default: `::`) |
|
|
| `--web-ip <ip address>` | `MAILDEV_WEB_IP` | IP Address to bind HTTP service to (default: `0.0.0.0`) |
|
|
| `--mail-directory <path>` | `MAILDEV_MAIL_DIRECTORY` | Directory for persisting mail |
|
|
| `--max-emails <count>` | `MAILDEV_MAX_EMAILS` | Maximum emails to keep; oldest are discarded with their files (default: 0 = unlimited) |
|
|
| `--https` | `MAILDEV_HTTPS` | Switch from http to https protocol |
|
|
| `--https-key <file>` | `MAILDEV_HTTPS_KEY` | The file path to the ssl private key |
|
|
| `--https-cert <file>` | `MAILDEV_HTTPS_CERT` | The file path to the ssl cert file |
|
|
| `--incoming-user <user>` | `MAILDEV_INCOMING_USER` | SMTP user for incoming mail |
|
|
| `--incoming-pass <pass>` | `MAILDEV_INCOMING_PASS` | SMTP password for incoming mail |
|
|
| `--incoming-secure` | `MAILDEV_INCOMING_SECURE` | Use SMTP SSL for incoming emails |
|
|
| `--incoming-cert <path>` | `MAILDEV_INCOMING_CERT` | Cert file location for incoming SSL |
|
|
| `--incoming-key <path>` | `MAILDEV_INCOMING_KEY` | Key file location for incoming SSL |
|
|
| `--outgoing-host <host>` | `MAILDEV_OUTGOING_HOST` | SMTP host for outgoing mail |
|
|
| `--outgoing-port <port>` | `MAILDEV_OUTGOING_PORT` | SMTP port for outgoing mail |
|
|
| `--outgoing-user <user>` | `MAILDEV_OUTGOING_USER` | SMTP user for outgoing mail |
|
|
| `--outgoing-pass <password>` | `MAILDEV_OUTGOING_PASS` | SMTP password for outgoing mail |
|
|
| `--outgoing-secure` | `MAILDEV_OUTGOING_SECURE` | Use SMTP SSL for outgoing mail |
|
|
| `--outgoing-ignore-tls` | `MAILDEV_OUTGOING_IGNORE_TLS` | Never use STARTTLS for outgoing mail, even if the server offers it |
|
|
| `--auto-relay [email]` | `MAILDEV_AUTO_RELAY` | Use auto-relay mode. Optional relay email address |
|
|
| `--auto-relay-rules <file>` | `MAILDEV_AUTO_RELAY_RULES` | Filter rules for auto relay mode |
|
|
| `--web-user <user>` | `MAILDEV_WEB_USER` | HTTP user for GUI |
|
|
| `--web-pass <password>` | `MAILDEV_WEB_PASS` | HTTP password for GUI |
|
|
| `--base-pathname <path>` | `MAILDEV_BASE_PATHNAME` | Base path for URLs |
|
|
| `--disable-web` | `MAILDEV_DISABLE_WEB` | Disable the use of the web interface |
|
|
| `--hide-extensions <extensions>` | `MAILDEV_HIDE_EXTENSIONS` | Comma separated list of SMTP extensions to NOT advertise |
|
|
| `--max-message-size <bytes>` | `MAILDEV_MAX_MESSAGE_SIZE` | Max accepted message size in bytes; larger messages are rejected. 0 disables (default: 52428800) |
|
|
| `--mcp` | `MAILDEV_MCP` | Enable MCP server for Claude integration |
|
|
| `--config <file>` | | Path to configuration file |
|
|
| `-v, --verbose` | | Enable verbose logging |
|
|
| `--silent` | | Disable all output |
|
|
| `--log-mail-contents` | | Log a JSON representation of each incoming mail |
|
|
|
|
## Storage limit
|
|
|
|
MailDev keeps every email by default (`--max-emails 0`), preserving its
|
|
historical behaviour and keeping persisted mail durable across restarts. Set a
|
|
positive limit to cap the store: when a new email arrives and the limit is
|
|
reached, the oldest is discarded — along with its `.eml` file and attachments,
|
|
so a persisted mail directory stays bounded as well. Any backlog left in the
|
|
mail directory by earlier runs is trimmed to the same limit at startup.
|
|
|
|
```bash
|
|
maildev --max-emails 1000 # keep the newest 1000
|
|
maildev --max-emails 0 # keep everything (the default)
|
|
```
|
|
|
|
Leaving the limit unset keeps everything. Be aware that memory use and the mail
|
|
directory then grow with the inbox; with typical messages, 10,000 emails is
|
|
around 150 MB of heap, so set a limit for long-running or high-volume use.
|
|
|
|
## Configuration File
|
|
|
|
MailDev supports configuration files. Create a `maildev.config.js`, `maildev.config.ts`, or `.maildevrc.json` file:
|
|
|
|
```javascript
|
|
// maildev.config.js
|
|
export default {
|
|
smtp: 1025,
|
|
web: 1080,
|
|
verbose: true,
|
|
mcp: true,
|
|
}
|
|
```
|
|
|
|
```json
|
|
// .maildevrc.json
|
|
{
|
|
"smtp": 1025,
|
|
"web": 1080,
|
|
"verbose": true
|
|
}
|
|
```
|
|
|
|
Configuration priority: CLI args > Environment variables > Config file > Defaults
|
|
|
|
## API
|
|
|
|
MailDev can be used in your Node.js application. For more info view the
|
|
[API docs](https://github.com/maildev/maildev/blob/main/docs/api.md).
|
|
|
|
```typescript
|
|
import { MailDev } from 'maildev'
|
|
|
|
const maildev = new MailDev({
|
|
smtp: 1025,
|
|
web: 1080,
|
|
})
|
|
|
|
const { smtp } = await maildev.start()
|
|
|
|
smtp.on('new', (email) => {
|
|
console.log('New email:', email.subject)
|
|
})
|
|
|
|
// When done
|
|
await maildev.stop()
|
|
```
|
|
|
|
MailDev also has a **REST API**. For more info
|
|
[view the docs](https://github.com/maildev/maildev/blob/main/docs/rest.md).
|
|
|
|
## AI Agent Integration (MCP)
|
|
|
|
MailDev includes a Model Context Protocol (MCP) server so AI agents can work with
|
|
your dev inbox. It works with any MCP client — Claude (Desktop and Code), Cursor,
|
|
Codex, Windsurf, and more. Enable it with `--mcp`:
|
|
|
|
```bash
|
|
maildev --mcp
|
|
```
|
|
|
|
This exposes an MCP endpoint at `/mcp` that lets an agent:
|
|
- Search and retrieve emails
|
|
- Extract verification links and tokens
|
|
- Analyze email content
|
|
- Monitor email delivery
|
|
|
|
For detailed setup instructions — both transports, client config, and the
|
|
available tools, resources, and prompts — [see the MCP docs](https://github.com/maildev/maildev/blob/main/docs/mcp.md).
|
|
|
|
## Outgoing Email
|
|
|
|
MailDev optionally supports selectively relaying emails to an outgoing SMTP server. If you configure outgoing
|
|
email with the `--outgoing-*` options you can click "Relay" on an individual email to relay through MailDev out
|
|
to a real SMTP service that will actually send the email to the recipient.
|
|
|
|
Example:
|
|
|
|
```bash
|
|
maildev --outgoing-host smtp.gmail.com \
|
|
--outgoing-secure \
|
|
--outgoing-user 'you@gmail.com' \
|
|
--outgoing-pass '<pass>'
|
|
```
|
|
|
|
MailDev upgrades a non-secure relay connection with STARTTLS whenever the server offers it. Add
|
|
`--outgoing-ignore-tls` to keep it on cleartext, e.g. for a relay on port 587 that does not support TLS.
|
|
|
|
### Auto Relay Mode
|
|
|
|
Enabling the auto relay mode will automatically send each email to its recipient
|
|
without the need to click the "Relay" button mentioned above.
|
|
The outgoing email options are required to enable this feature.
|
|
|
|
Optionally, you can specify a single email address to which MailDev will forward
|
|
all emails instead of the original recipient. For example, using
|
|
`--auto-relay you@example.com` will forward all emails to that address
|
|
automatically.
|
|
|
|
Additionally, you can pass a valid json file with additional configuration for
|
|
which email addresses you would like to `allow` or `deny`. The last matching
|
|
rule in the array will be the rule MailDev will follow.
|
|
|
|
Example:
|
|
|
|
```bash
|
|
maildev --outgoing-host smtp.gmail.com \
|
|
--outgoing-secure \
|
|
--outgoing-user 'you@gmail.com' \
|
|
--outgoing-pass '<pass>' \
|
|
--auto-relay \
|
|
--auto-relay-rules file.json
|
|
```
|
|
|
|
Rules example file:
|
|
|
|
```json
|
|
[
|
|
{ "allow": "*" },
|
|
{ "deny": "*@test.com" },
|
|
{ "allow": "ok@test.com" },
|
|
{ "deny": "*@utah.com" },
|
|
{ "allow": "johnny@utah.com" }
|
|
]
|
|
```
|
|
|
|
This would allow `angelo@fbi.gov`, `ok@test.com`, `johnny@utah.com`, but deny
|
|
`bodhi@test.com`.
|
|
|
|
## Configure Your Project
|
|
|
|
Configure your application to send emails via port `1025` and open `localhost:1080` in your browser.
|
|
|
|
**Nodemailer (Node.js)**
|
|
|
|
```javascript
|
|
const nodemailer = require('nodemailer')
|
|
|
|
const transport = nodemailer.createTransport({
|
|
host: 'localhost',
|
|
port: 1025,
|
|
})
|
|
|
|
transport.sendMail({
|
|
from: 'sender@example.com',
|
|
to: 'recipient@example.com',
|
|
subject: 'Test Email',
|
|
text: 'Hello from MailDev!',
|
|
})
|
|
```
|
|
|
|
**Django** -- Add `EMAIL_PORT = 1025` in your settings file [[source]](https://docs.djangoproject.com/en/dev/ref/settings/#std:setting-EMAIL_PORT)
|
|
|
|
**Rails** -- config settings:
|
|
|
|
```ruby
|
|
config.action_mailer.delivery_method = :smtp
|
|
config.action_mailer.smtp_settings = {
|
|
address: "localhost",
|
|
port: 1025,
|
|
enable_starttls_auto: false
|
|
}
|
|
```
|
|
|
|
**Spring Boot** -- in application.properties:
|
|
|
|
```properties
|
|
spring.mail.host=localhost
|
|
spring.mail.port=1025
|
|
```
|
|
|
|
## Features
|
|
|
|
- Modern React-based web interface
|
|
- Toggle between HTML, plain text views and email headers
|
|
- Test responsive emails with resizable preview pane
|
|
- Receive and view email attachments
|
|
- Real-time updates via WebSocket
|
|
- Relay email to an upstream SMTP server
|
|
- MCP integration for Claude AI assistant
|
|
- Configuration file support
|
|
- Full TypeScript support
|
|
|
|
## Ideas
|
|
|
|
If you're using MailDev and you have a great idea, I'd love to hear it. If you're not using MailDev because it lacks a feature, I'd love to hear that too. Add an issue to the repo [here](https://github.com/maildev/maildev/issues/new).
|
|
|
|
## Contributing
|
|
|
|
Any help on MailDev would be awesome. There is plenty of room for improvement. Feel free to [create a Pull Request](https://github.com/maildev/maildev/pulls).
|
|
|
|
MailDev v3 is a TypeScript monorepo using pnpm workspaces:
|
|
|
|
```
|
|
packages/
|
|
core/ # Storage and shared types
|
|
smtp/ # SMTP server
|
|
api/ # REST API and WebSocket server
|
|
ui/ # React web interface
|
|
mcp/ # MCP server for Claude
|
|
cli/ # CLI and orchestration
|
|
```
|
|
|
|
To run **MailDev** during development:
|
|
|
|
```bash
|
|
pnpm install
|
|
pnpm dev
|
|
```
|
|
|
|
To send test emails:
|
|
|
|
```bash
|
|
node scripts/send.js
|
|
```
|
|
|
|
To run the test suite:
|
|
|
|
```bash
|
|
pnpm test
|
|
```
|
|
|
|
## [Changelog](https://github.com/maildev/maildev/releases)
|
|
|
|
## Thanks
|
|
|
|
**MailDev** is built using great open source projects including
|
|
[React](https://react.dev/),
|
|
[Fastify](https://fastify.dev/),
|
|
[Tailwind CSS](https://tailwindcss.com/),
|
|
and two great projects from [Andris Reinman](https://github.com/andris9):
|
|
[smtp-server](https://github.com/nodemailer/smtp-server)
|
|
and [mailparser](https://github.com/nodemailer/mailparser).
|
|
Many thanks to Andris as his projects are the backbone of this app and to
|
|
[MailCatcher](http://mailcatcher.me/) for the inspiration.
|
|
|
|
Additionally, thanks to all the awesome [contributors](https://github.com/maildev/maildev/graphs/contributors)
|
|
to the project.
|
|
|
|
## License
|
|
|
|
MIT
|