smtp4dev on Ubuntu 24.04 on Azure User Guide
Overview
smtp4dev is a fake, developer focused SMTP server with a modern web interface. It runs a fake SMTP server that catches every message your application sends, stores each one, and shows it in a web UI where 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 completely 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 cloudimg image installs the pinned smtp4dev 3.15.0 release on the ASP.NET Core 10 runtime, runs it as a dedicated smtp4dev system user under systemd, and fronts its web UI on port 80 with an nginx reverse proxy configured for the WebSocket the live message list uses. The SMTP listener is exposed on port 25 for your applications and the IMAP server on port 143, the SQLite message store lives on a dedicated Azure data disk, and a unique web UI password is generated on the first boot of every VM. Backed by 24/7 cloudimg support.
What is included:
- smtp4dev 3.15.0 running as the
smtp4devsystemd 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 smtp4dev.service+nginx.serviceas systemd units, enabled and active- An unauthenticated
/healthzendpoint for Azure Load Balancer health probes - 24/7 cloudimg support
Prerequisites
An active Azure subscription, an SSH key pair, and a VNet + subnet in the target region. Standard_B2s (2 vCPU / 4 GiB RAM) is a comfortable starting point; smtp4dev is light on resources. NSG inbound: allow 22/tcp from your management network, 80/tcp for the web UI, 25/tcp from the networks that run the applications under test so they can deliver mail to smtp4dev, and 143/tcp if you want to browse captured mail from an IMAP client. smtp4dev serves plain HTTP on port 80; for production adjacent use, 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 cloudimg, 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 Review + create -> Create.
Step 2 - Deploy from the Azure CLI
az vm create \
--resource-group <your-rg> \
--name smtp4dev \
--image <marketplace-image-urn> \
--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 1030
Step 3 - Connect to your VM
ssh azureuser@<vm-public-ip>
Step 4 - Confirm the services are running
systemctl is-active smtp4dev.service nginx.service
Both report active. smtp4dev serves its web UI and REST API on the loopback connector 127.0.0.1:5000, 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 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 and a unique password is generated on the first boot of your VM and written to a root-only file:
sudo cat /root/smtp4dev-credentials.txt
This file contains SMTP4DEV_USERNAME, SMTP4DEV_PASSWORD, the SMTP4DEV_URL to open in a browser and the SMTP4DEV_SMTP / SMTP4DEV_IMAP host:port values 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/healthz
It returns ok. This endpoint never requires authentication, so it is safe 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 following reads the per-VM password from the credentials file and proves the round-trip - unauthenticated 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/)"
It prints unauth: 401 then 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 - the message list of everything your applications have sent, each row showing the received time, sender and recipient.

Step 9 - Read a captured message
Click any message to open it. smtp4dev renders the email exactly as a mail client would, with the From, To and Subject headers at the top and tabs to 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 Headers / Parts) to see the exact MIME your application produced - 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 cloudimg 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, no password and no TLS are 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 it is safe to 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, so you can point a standard mail client (Thunderbird, Outlook, mutt) at the box 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 handy 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, so your captured messages survive OS changes and the disk can be resized independently:
findmnt /var/lib/smtp4dev
The 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
cloudimg provides 24/7 expert support for this image. Contact support@cloudimg.co.uk.