---
title: "Deploy Mailpit | (Just Updated) Email Testing SMTP Server with REST API, Login Preset, Data Survives Redeploys"
description: "Mailpit email testing server: SMTP inbox, web UI and REST API"
category: "Other"
url: https://railway.com/deploy/mailpit-or-just-updated-email-testing-sm
---

# Deploy Mailpit | (Just Updated) Email Testing SMTP Server with REST API, Login Preset, Data Survives Redeploys

Mailpit email testing server: SMTP inbox, web UI and REST API

**[Deploy Mailpit | (Just Updated) Email Testing SMTP Server with REST API, Login Preset, Data Survives Redeploys on Railway](https://railway.com/template/mailpit-or-just-updated-email-testing-sm)**

Machine-readable deploy manifest (JSON, validated by TemplateCI): https://railway.com/deploy/mailpit-or-just-updated-email-testing-sm/manifest.json

- **Creator:** SuperSlowSloth
- **Category:** Other

## Template content

### mailpit

- **Image:** axllent/mailpit:v1.33.0@sha256:9b3a463be15354c0f0eba91697d80e3e0d8a5623ef0e627cacc836bc17fd5231
- **Start command:** `/bin/sh -c 'export MP_UI_BIND_ADDR="0.0.0.0:${PORT:-8080}" MP_SMTP_BIND_ADDR=0.0.0.0:1025 MP_DATABASE=/data/mailpit.db MP_MAX_MESSAGES=5000 MP_SMTP_AUTH_ALLOW_INSECURE=true MP_UI_AUTH="admin:$MAILPIT_UI_PASSWORD" MP_SMTP_AUTH="mailpit:$MAILPIT_SMTP_PASSWORD"; echo "[boot] data dir owner=$(stat -c %u:%g /data) ui=$MP_UI_BIND_ADDR smtp=$MP_SMTP_BIND_ADDR"; exec /mailpit'`
- **Health check:** /livez
- **Public domain:** Yes

## Documentation

# Deploy and Host Mailpit on Railway

**Built for an LLM agent to deploy and use.** There is no setup page to open: the web UI and SMTP logins are created from generated passwords on first boot, and the contract below lists every address, variable name and one script that sends a message through the REST API and reads it back.

Mailpit is an open source email testing server. Your application sends mail to its SMTP port instead of a real provider, and every message lands in a web inbox and a REST API, with HTML and text bodies, headers, attachments, link checks and search. It is a single Go binary that idles at under 10 MB of memory.

## About Hosting Mailpit

This template runs one service: the official `axllent/mailpit` v1.33.0 image, pinned by digest, with a volume on `/data`. The volume holds the SQLite message store, so the inbox survives redeploys. The web UI and REST API share one port and sit behind HTTP Basic auth as the user `admin`. The SMTP listener (port 1025) requires a login as the user `mailpit`. Both passwords are generated per deploy.

The SMTP port is reachable on Railway's private network only (`mailpit.railway.internal:1025`), which is where test mail comes from: services in the same project. It is not exposed to the internet, because Railway cannot give one service both an HTTP healthcheck and a public TCP proxy. The start command moves the web UI from Mailpit's default port 8025 to Railway's injected `PORT` so the healthcheck and the public domain reach it, and keeps the newest 5000 messages.

### Agent contract

- Public URL: `MAILPIT_PUBLIC_URL` (`https://` plus the service's `RAILWAY_PUBLIC_DOMAIN`). The web UI is at `/`, the REST API under `/api/v1/`.
- Private URLs: web and API `http://mailpit.railway.internal:8080` (`MAILPIT_PRIVATE_URL`); SMTP `mailpit.railway.internal` port `1025`, plain text with login, ready-made as `MAILPIT_SMTP_URL` (`smtp://mailpit:PASSWORD@mailpit.railway.internal:1025`).
- Credentials: `MAILPIT_UI_PASSWORD` (user `admin`, web UI and API) and `MAILPIT_SMTP_PASSWORD` (user `mailpit`, SMTP).
- Auth: the API takes HTTP Basic auth (`curl -u admin:$MAILPIT_UI_PASSWORD`). SMTP uses AUTH PLAIN or LOGIN with `mailpit` and the SMTP password; set the client to "no TLS" or "STARTTLS optional", since the private network is the transport.
- Health: `GET /livez` returns 200 without credentials.
- API: `GET /api/v1/messages`, `GET /api/v1/message/{id}`, `GET /api/v1/search?query=...`, `POST /api/v1/send`, `DELETE /api/v1/messages`.

```bash
# run with MAILPIT_PUBLIC_URL and MAILPIT_UI_PASSWORD set
U="$MAILPIT_PUBLIC_URL"; A="admin:$MAILPIT_UI_PASSWORD"
curl -s -o /dev/null -w "livez: %{http_code}\n" "$U/livez"
curl -s -o /dev/null -w "no auth: %{http_code}\n" "$U/api/v1/messages"
curl -s -u "$A" -H "Content-Type: application/json" \
  -d '{"From":{"Email":"app@example.com"},"To":[{"Email":"user@example.com"}],"Subject":"hello from an agent","Text":"sent through the API"}' \
  "$U/api/v1/send"; echo
curl -s -u "$A" "$U/api/v1/search?query=subject:hello" | sed -n 's/.*"messages_count":\([0-9]*\).*/found: \1/p'
curl -s -u "$A" -X DELETE "$U/api/v1/messages"; echo
```

A fresh deploy prints `livez: 200`, `no auth: 401`, a JSON object with the new message `ID`, `found: 1`, and `ok` for the delete.

To send over SMTP from another service in the same project, point it at `MAILPIT_SMTP_URL` (or host `mailpit.railway.internal`, port `1025`, user `mailpit`, password `MAILPIT_SMTP_PASSWORD`) and read the result back with the same API calls.

## Why Deploy Mailpit on Railway?

Railway is a singular platform to deploy your infrastructure stack. Railway will host your infrastructure so you don't have to deal with configuration, while allowing you to vertically and horizontally scale it.

By deploying Mailpit on Railway, you are one step closer to supporting a complete full-stack application with minimal burden. Host your servers, databases, AI agents, and more on Railway.

- **Agent-ready** - generated logins, contract block and one working script; nothing to type into the deploy form.
- **Locked from boot** - the inbox and the SMTP port both need a login, so test mail with real-looking content is not public.
- **State survives redeploys** - the message store lives on a volume, and the image is pinned by digest.
- **A healthcheck that works** - `/livez` passes without credentials, so a bad deploy is caught instead of served.
- **One light service** - no database to run alongside, under 10 MB of memory when idle.

## Common Use Cases

- **Staging mail catcher** - point a staging app's SMTP settings at `MAILPIT_SMTP_URL` and read password resets and order emails in the web UI.
- **End-to-end tests** - a test run sends mail, then polls `/api/v1/search` for the message and extracts the link or code.
- **Agent email checks** - an AI agent verifies that the mail its code sends renders, has the right headers and links, and is deleted afterwards.

## Dependencies for Mailpit Hosting

- One Railway volume on `/data`, created by the template.

### Deployment Dependencies

- [Mailpit repository](https://github.com/axllent/mailpit)
- [Official image](https://hub.docker.com/r/axllent/mailpit)
- [Mailpit documentation](https://mailpit.axllent.org/docs/)

### Implementation Details

| Variable | Purpose |
| --- | --- |
| `MAILPIT_UI_PASSWORD` | Password of the `admin` user for the web UI and REST API. Generated per deploy. |
| `MAILPIT_SMTP_PASSWORD` | Password of the `mailpit` SMTP user. Generated per deploy. |
| `MAILPIT_PUBLIC_URL` | HTTPS address of the web UI and API. |
| `MAILPIT_PRIVATE_URL` | Web UI and API address on the private network. |
| `MAILPIT_SMTP_URL` | SMTP connection string on the private network, password included. |

The start command exports `MP_UI_BIND_ADDR` from `PORT`, the database path, the message limit, `MP_UI_AUTH` and `MP_SMTP_AUTH` (built from the two passwords), then runs the image's own `/mailpit`.


## Similar templates

- [Rocky Linux](https://railway.com/deploy/rocky-linux) — Hosted Rocky Linux 9 workspace with SSH and persistent storage. 🚀
- [Foundry Virtual Tabletop](https://railway.com/deploy/X5tR6G) — A Self-Hosted & Modern Roleplaying Platform
- [Letta Code Remote](https://railway.com/deploy/letta-code-remote) — Run a Letta Code agent 24/7. No inbound ports, just deploy.

Open this page in a browser: https://railway.com/deploy/mailpit-or-just-updated-email-testing-sm
