smtp4dev
Overview
smtp4dev is a fake, developer-focused SMTP server with a modern web interface. It catches every message your application sends, stores each one, and shows it in a web UI. There you can read the HTML, plain text and raw source, inspect headers and attachments, and run HTML validation and compatibility checks.
Because smtp4dev never delivers mail externally, it is safe to point your development and staging applications at it. Nothing ever reaches a real inbox. A built-in IMAP server also lets a standard mail client browse the captured messages.
The SecureAnyCloud image installs the pinned smtp4dev 3.15.0 release on the ASP.NET Core 10 runtime and runs it as a dedicated smtp4dev system user under systemd. It fronts the web UI on port 80 with an nginx reverse proxy configured for the WebSocket that the live message list uses.
What you get:
smtp4dev3.15.0 running as the smtp4dev systemd service on the ASP.NET Core 10 runtime- A fake SMTP server on
:25that captures every message your apps send and never delivers externally - An IMAP server on
:143so a standard mail client can browse the captured mail - The smtp4dev web UI on
:80, fronted by nginx with the WebSocket upgrade proxied - HTTP Basic Auth protecting the web UI and REST API, with a unique password generated on first boot
- A dedicated Azure data disk at
/var/lib/smtp4devholding the SQLite message store, separate from the operating system disk smtp4dev.serviceandnginx.serviceas systemd units, enabled and active- An unauthenticated
/healthzendpoint for Azure Load Balancer health probes - 24/7 SecureAnyCloud support
Prerequisites
- An active Azure subscription, an SSH key pair, and a VNet plus subnet in the target region
- Standard_B2s (2 vCPU / 4 GiB RAM) is a comfortable starting point, because smtp4dev is light on resources
- NSG inbound rules:
22/tcpfrom your management network and80/tcpfor the web UI 25/tcpfrom the networks that run the applications under test, so they can deliver mail to smtp4dev143/tcpif you want to browse captured mail from an IMAP client
smtp4dev serves plain HTTP on port 80. If you use it beyond a trusted network, terminate TLS in front of it with your own domain (see Maintenance).
Step 1 - Deploy from the Azure Marketplace
Sign in to the Azure Portal, choose Create a resource, search the Marketplace for smtp4dev by SecureAnyCloud, and select Create.
On Basics, pick your subscription, resource group, region and size. Under Administrator account, choose SSH public key and paste your key. Under Inbound port rules, allow SSH (22) and HTTP (80).
After creation, add inbound NSG rules for SMTP (25) from your application networks and, if you want IMAP access, IMAP (143). Review the dedicated data disk on the Disks tab, then choose Review + create and Create.
Step 2 - Deploy from the Azure CLI
# Accept the Marketplace terms once per subscription (required before the first CLI deploy)
az vm image terms accept --urn sac1647283583153:smtp4dev-ubuntu-24-04:default:latest
az vm create \
--resource-group <your-rg> \
--name smtp4dev \
--image sac1647283583153:smtp4dev-ubuntu-24-04:default:latest \
--size Standard_B2s \
--admin-username azureuser \
--ssh-key-values ~/.ssh/id_ed25519.pub \
--vnet-name <your-vnet> --subnet <your-subnet> \
--public-ip-sku Standard
az vm open-port --resource-group <your-rg> --name smtp4dev --port 80 --priority 1010
az vm open-port --resource-group <your-rg> --name smtp4dev --port 25 --priority 1020
az vm open-port --resource-group <your-rg> --name smtp4dev --port 143 --priority 1030Step 3 - Connect to your VM
ssh azureuser@<vm-public-ip>Step 4 - Confirm the services are running
systemctl is-active smtp4dev.service nginx.serviceBoth services report active. smtp4dev serves its web UI and REST API on the loopback connector 127.0.0.1:5000. It listens for SMTP on 0.0.0.0:25 and IMAP on 0.0.0.0:143.
nginx fronts the UI on port 80 with the WebSocket upgrade that the live message list requires. smtp4dev's SQLite message store lives on the dedicated Azure data disk mounted at /var/lib/smtp4dev.
Step 5 - Retrieve your web UI password
smtp4dev protects its web UI and REST API with HTTP Basic Auth. The username is admin. A unique password is generated on the first boot of your VM and written to a root-only file:
sudo cat /root/smtp4dev-credentials.txtThis file contains SMTP4DEV_USERNAME, SMTP4DEV_PASSWORD, the SMTP4DEV_URL to open in a browser, and the SMTP4DEV_SMTP and SMTP4DEV_IMAP host:port values that your applications and mail clients should use.
The password is stored only in the per-VM override at /var/lib/smtp4dev/appsettings.json (mode 0600), so no shared password ships in the image. Store the password somewhere safe.
Step 6 - Confirm the health endpoint
nginx serves an unauthenticated health endpoint for load balancers and probes:
curl -s http://localhost/healthzIt returns ok. This endpoint never requires authentication, so you can use it for an Azure Load Balancer health probe.
Step 7 - Confirm authentication and SMTP capture
Because a password is set on first boot, an unauthenticated request to the web UI returns HTTP 401, so nobody reaches your captured mail without the password. The commands below read the per-VM password from the credentials file and prove the round trip. An unauthenticated request is rejected, and the correct password authenticates:
PW=$(sudo grep '^SMTP4DEV_PASSWORD=' /root/smtp4dev-credentials.txt | cut -d= -f2-)
echo "unauth: $(curl -s -o /dev/null -w '%{http_code}' http://127.0.0.1/)"
echo "authed: $(curl -s -o /dev/null -w '%{http_code}' -u admin:$PW http://127.0.0.1/)"The output is unauth: 401 followed by authed: 200. Every message your applications send to port 25 is captured and readable through the authenticated REST API at /api/Messages.
Step 8 - Sign in to the web UI
Browse to http://<vm-public-ip>/. Your browser prompts for a username and password. Enter admin and the password from Step 5.
smtp4dev opens on the inbox, which lists everything your applications have sent. Each row shows the received time, sender and recipient.
Step 9 - Read a captured message
Click any message to open it. smtp4dev renders the email as a mail client would, with the From, To and Subject headers at the top. Tabs switch between the rendered View, Analysis, raw Source, full Headers and MIME Parts.
Step 10 - Inspect the message source and headers
Switch to the Source tab, or to Headers or Parts, to see the exact MIME your application produced. This is invaluable when you are debugging templating, encoding or deliverability issues.
Step 11 - Review the server settings
Open Settings (the gear icon, top right) to review the server configuration. The SMTP Server, IMAP Server and POP3 Server tabs show the ports and options for each protocol. Users manages the web and mailbox accounts, and Mailboxes defines how incoming mail is routed.
On the SecureAnyCloud image, Require Authentication (web, API) is enabled by default, so your captured mail is never exposed without the per-VM password.
Step 12 - Point your application's SMTP at smtp4dev
Configure your application's outbound SMTP settings to use this VM on port 25. No username, password or TLS is required by default, which matches how most frameworks send to a local development mail catcher:
- Host: the VM's private or public IP (the
SMTP4DEV_SMTPvalue from Step 5) - Port: 25
- Encryption / auth: none
Every email the application then sends is captured by smtp4dev and appears instantly in the web UI. Nothing is ever delivered to a real recipient, so you can exercise password resets, order confirmations, notification digests and any other mail flow against production-like data.
Step 13 - Browse captured mail over IMAP
smtp4dev also runs an IMAP server on port 143. Point a standard mail client (Thunderbird, Outlook, mutt) at the VM and browse the captured messages as an ordinary mailbox:
- Host: the VM's IP (the
SMTP4DEV_IMAPvalue from Step 5) - Port: 143
- Connection security: none
The default mailbox holds every captured message. This is useful when you want to test how your own mail client renders the messages your application produced.
Step 14 - Confirm data lives on the dedicated disk
smtp4dev's SQLite message store is kept under /var/lib/smtp4dev on the dedicated Azure data disk. Your captured messages survive OS changes, and you can resize the disk independently:
findmnt /var/lib/smtp4devThe mount is backed by a separate Azure data disk captured into the image and re-provisioned on every VM.
Maintenance
- Password: the web UI password is set on first boot and stored in the per-VM override
/var/lib/smtp4dev/appsettings.jsonunderServerOptions:Users. To change it, edit that file as root and runsudo systemctl restart smtp4dev. - Retention: smtp4dev keeps the most recent messages and prunes automatically. Adjust
# of Messages to Keepin the Settings dialog, orServerOptions:NumberOfMessagesToKeepin the override file. - Relaying mail: to forward a captured message to a real recipient, configure a relay SMTP server under Settings > Message Relay. Then use the Relay action on a message.
- Upgrades: smtp4dev is published under
/opt/smtp4devand runs on the apt-managed ASP.NET Core 10 runtime. To upgrade, download a newer pinned release, verify its checksum, replace the contents of/opt/smtp4devand runsudo systemctl restart smtp4dev. Your message store under/var/lib/smtp4devis preserved. - Storage: all smtp4dev state lives under
/var/lib/smtp4devon the data disk. Back up that volume to protect your captured messages. - TLS: smtp4dev serves plain HTTP on port 80. Front it with TLS (for example certbot with your own domain) before exposing it beyond a trusted network.
- Security patches: unattended-upgrades remains enabled so the OS and the ASP.NET Core runtime continue to receive security updates automatically.
Support
SecureAnyCloud provides 24/7 expert support for this image. Contact sales@secureanycloud.com.
Deploy on Azure
Launch smtp4dev on Ubuntu 24.04 LTS on Azure with 24/7 support from SecureAnyCloud.
View this image
Need Help?
Our support team is available 24/7.
sales@secureanycloud.com
Overview
smtp4dev is a fake SMTP server for development and testing. It accepts the mail your applications send, stores it locally, and presents every captured message in a modern web UI inbox instead of delivering it to real recipients.
Because smtp4dev never delivers mail externally, you can safely point a development, test or staging environment straight at it. You can then inspect exactly what your application would have sent: rendered HTML, plain text and raw source, attachments, every header, and smtp4dev's HTML compatibility analysis.
What you get:
smtp4devas an ASP.NET Core application, running as the dedicated smtp4dev system user under systemd- SMTP on port 25 and IMAP on port 143
- The web UI and REST API on the loopback interface at
127.0.0.1:5000, fronted by nginx as a reverse proxy on port 80 (and 443 once you add TLS), with the WebSocket upgrade for the live-updating message list already configured - A .NET runtime installed from the operating system's own package archive, so routine system updates keep the runtime patched rather than freezing it inside the application bundle
- A SQLite message database on a dedicated EBS data volume mounted at
/var/lib/smtp4dev, separate from the operating system disk and independently resizable - A web password unique to each instance, generated on first boot by a one-shot service. It is written into an override configuration file that enables HTTP basic authentication for both the web UI and the REST API, and recorded in
/root/smtp4dev-credentials.txtwith mode 0600 - No shared or default credentials in the image. The health endpoint used by load balancers stays open, while the web UI and API require the generated password
Before first boot records the password, it proves the result. It confirms that an unauthenticated request is refused, that a wrong password is refused, and that the newly generated password is accepted, both directly and through the reverse proxy.
Connecting to your instance
Connect over SSH as the default login user for your operating system variant. This listing currently ships the following variant:
- Ubuntu 24.04 LTS, with SSH login user ubuntu
Prerequisites
Before you deploy this image you need:
- An Amazon Web Services account where you can launch EC2 instances
- IAM permissions to launch instances, create security groups, and subscribe to AWS Marketplace products
- An EC2 key pair in the target Region for SSH access to the instance
- A VPC and subnet in the target Region
- A security group allowing inbound port 22 from your management network, and inbound ports 80 and 443 from the networks your operators will reach the smtp4dev UI on
- Inbound port 25 from the application hosts that will send test mail, and inbound port 143 if you want to browse captured mail over IMAP
- The AWS CLI (version 2) installed locally if you plan to deploy from the command line
Launch the Instance from the AWS Marketplace
Sign in to the AWS Management Console, open the EC2 service, and select Launch instance. Under Application and OS Images, choose AWS Marketplace AMIs and search for smtp4dev. Select the SecureAnyCloud listing and choose Select, then Continue on the subscription summary.
Choose an instance type (the listing recommends m5.large), select your key pair, and configure a security group as described in the prerequisites.
Leave the storage at the defaults. The AMI carries a dedicated data volume for the captured-mail database in addition to the operating system disk. Choose Launch instance.
Launch the Instance from the AWS CLI
To deploy from the command line, first find the AMI ID for the listing in your Region. Then launch it, replacing the example values with your own.
aws ec2 run-instances \
--image-id ami-xxxxxxxxxxxxxxxxx \
--instance-type m5.large \
--key-name your-key-pair \
--security-group-ids sg-xxxxxxxxxxxxxxxxx \
--subnet-id subnet-xxxxxxxxxxxxxxxxx \
--metadata-options 'HttpTokens=required,HttpEndpoint=enabled' \
--tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=smtp4dev}]' \
--region us-east-1The instance metadata options require IMDSv2 (HttpTokens=required). The first-boot service uses IMDSv2 to discover the instance's public IP address for the credentials file.
Connect and Retrieve the Web Password
Once the instance has finished its first boot, connect over SSH as the login user for your variant. For the Ubuntu 24.04 variant this is ubuntu. Then read the generated credentials file:
ssh -i your-key.pem ubuntu@<public-ip>
sudo cat /root/smtp4dev-credentials.txtThe file contains the web URL, the admin username, the per-instance password, and the SMTP and IMAP endpoints:
SMTP4DEV_URL=http://<public-ip>/ SMTP4DEV_USERNAME=admin SMTP4DEV_PASSWORD=<generated-password> SMTP4DEV_SMTP=<public-ip>:25 SMTP4DEV_IMAP=<public-ip>:143Confirm from the shell that the stack is healthy. The service and reverse proxy are both active, and the health endpoint answers without authentication. The UI itself returns 401 until you sign in:
systemctl status smtp4dev nginx --no-pager curl -s http://127.0.0.1/healthz
# -> ok curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1/
# -> 401You can also confirm the listeners. smtp4dev serves the web UI on loopback 127.0.0.1:5000 and accepts SMTP on 0.0.0.0:25 and IMAP on *:143. nginx listens on port 80:
sudo ss -tlnp | grep -E ':25|:80|:143|:5000'First Sign-in
Open the web URL from the credentials file in your browser (http://<public-ip>/). The browser prompts for HTTP basic authentication. Sign in with the username admin and the generated password.
The message list loads and updates live as new mail arrives, because nginx proxies the WebSocket connection that smtp4dev uses to push new messages to the browser.
Point Your Application at the SMTP Port
Point your application's outbound SMTP settings at the instance on port 25. smtp4dev accepts mail without authentication or TLS by default, as a development mail sink should, so the SMTP side needs no credentials:
- SMTP host:
<public-ip> - SMTP port: 25
- Authentication: none
- TLS: none required
smtp4dev captures every message your application sends and never forwards it to a real recipient. To confirm capture from the shell, send a test message and watch it appear through the authenticated REST API:
swaks --to test@example.com --from app@example.com \
--server <public-ip>:25 --header "Subject: hello from my app"
PW=$(sudo grep '^SMTP4DEV_PASSWORD=' /root/smtp4dev-credentials.txt | cut -d= -f2-)
curl -s -u "admin:$PW" http://127.0.0.1/api/Messages \
| python3 -c 'import sys,json;print("messages:",json.load(sys.stdin)["rowCount"])'Inspect a Captured Message
Select any message in the list to open it. The View tab renders the HTML part as a mail client would show it, so you see the message as your recipients would.
The Parts tab lets you download attachments and inspect each MIME part. The Source tab shows the complete raw message as it was received on the wire.
Read the Headers
The Headers tab lists every header on the captured message, including Date, From, To, Subject, Message-Id and the sending mailer. This is invaluable when you are debugging addressing, threading or deliverability metadata.
Run the HTML Compatibility Check
The Analysis tab scores a captured HTML message for email-client support. It flags each HTML or CSS feature that is only partially supported and names the specific clients affected. This is the fastest way to catch rendering problems before a template ships.
Browse Captured Mail Over IMAP
Because smtp4dev also speaks IMAP, you can browse the captured mailbox from any standard mail client, instead of or in addition to the web UI. Point your mail client at the instance on port 143 and sign in with the same admin username and per-instance password:
- IMAP host:
<public-ip> - IMAP port: 143
- Username: admin
- Password: the per-instance password from the credentials file
Review the Server Settings
The settings dialog (the gear icon in the top bar) shows the running server configuration. Require Authentication (web, API) is enabled, which protects the web UI and REST API with the per-instance password. SMTP intake is deliberately left open, so applications under test can send without credentials.
Enable HTTPS with Let's Encrypt
To serve the web UI over HTTPS, point a DNS name at the instance, open port 443 in the security group, and install a certificate with certbot. On the Ubuntu variant:
sudo apt-get update
sudo apt-get install -y certbot python3-certbot-nginx
sudo certbot --nginx -d your-smtp4dev-host.example.comcertbot obtains a certificate, edits the nginx site to serve TLS on port 443, and sets up automatic renewal. The reverse proxy configuration that fronts smtp4dev, including the WebSocket upgrade, is preserved.
Change the Web Password
The per-instance password lives in the override configuration file on the data volume. To change it, edit the Password value for the admin user, then restart smtp4dev:
sudo nano /var/lib/smtp4dev/appsettings.json
sudo systemctl restart smtp4devThe relevant section looks like this:
{ "ServerOptions": { "WebAuthenticationRequired": true, "Users": [ { "Username": "admin", "Password": "your-new-password" } ] } }Backups and Maintenance
The captured-mail database and the per-instance override configuration both live under /var/lib/smtp4dev on the dedicated data volume. To back up the captured mail, stop the service, copy the data directory and start the service again:
sudo systemctl stop smtp4dev
sudo tar czf /tmp/smtp4dev-backup.tgz -C /var/lib/smtp4dev .
sudo systemctl start smtp4devBecause the data volume is a separate EBS volume, you can take an EBS snapshot of it for point-in-time backups. You can also grow it independently of the operating system disk if you keep a large volume of captured mail.
Routine operating system updates keep both the ASP.NET Core runtime and nginx patched, because both are installed from the distribution's package archive.
Scaling and Operations
smtp4dev is a single-instance mail sink. Point your development, test and staging environments at it rather than running it as a highly available cluster.
For a shared team instance, place it behind a load balancer that health-checks the unauthenticated /healthz endpoint. Keep the web UI and IMAP ports reachable only from your operators' networks.
The number of messages and sessions smtp4dev retains is bounded, so the SQLite store stays small. Increase the retention limits in the settings dialog if you need a deeper history.
Support
SecureAnyCloud provides this image with 24/7 technical support by email and chat. Support covers deployment, HTTPS and reverse-proxy configuration, SMTP and IMAP integration, and storage and upgrade planning. Contact sales@secureanycloud.com.
All product and company names are trademarks or registered trademarks of their respective holders. Use of them does not imply any affiliation with or endorsement by them.
Deploy on AWS
Launch smtp4dev on AWS with 24/7 support from SecureAnyCloud.
View on Marketplace
Need Help?
Our support team is available 24/7.
sales@secureanycloud.com