Skip to content
HoldMail is a Java Application for proxying SMTP mail, providing a browsable viewer for captured emails.
Java JavaScript Vue Shell Other
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Type Name Latest commit message Commit time
Failed to load latest commit information.


HoldMail - A fake SMTP relay server

Build Status   Download

Release 2.0 Available!

The latest release of holdmail brings several improvements:

  • Support for attachments
  • Multilingual support
  • A new UI (We're now using Vue.js as the UI framework)
  • Direct linking to emails in the UI
  • Many miscellaneous bugfixes

For the list of issues included in this release, see the CHANGELOG.

What is Holdmail?

Instead of spamming real users (or worse - customers) while you test your applications, HoldMail offers the following:

  • An SMTP service that stores mails instead of relaying them for delivery.
  • A web interface for searching and viewing of those emails.
  • A REST API to query and fetch email content, very useful for testing.
  • The ability to manually release(forward) individually selected mails to the real world.


Mail List

Mail List

Mail Preview

Mail List


If you just want to try it out, grab and install the RPM from the 'rpm' folder here: Download

After installation, start the holdmail service:

#> sudo /etc/init.d/holdmail start
#> sudo service holdmail start

It's now ready to use! Without any configuration, HoldMail does the following:

  • It accepts SMTP messages on localhost port 25000. Configure your application to use this as the outgoing SMTP server.
  • It makes the webapp available at http://localhost:8080/.
  • Similarly, the REST API will be available at http://localhost:8080/rest/messages
  • A H2 embedded database will be created in holdmail's home directory (/opt/holdmail).


Running a new distibution of holdmail will automatically apply any needed changes to the attached database.

❗️ It's still always a good idea to make a backup first! If you just ran holdmail without configuring anything, that's going to be the H2 database file at $HOME/


Endpoint Description Method URI Request/Response
Find messages GET /rest/messages
Query Params:
'recipient' (str) - search by email address
'size' (int) - limit response hit size
'page' (int) - pagination support
Response: 200, application/json: a 'messages: [..]' array.
Get message by ID GET /rest/messages/{id} Response: 200, application/json: JSON object with summary attributes.
Get original raw message GET /rest/messages/{id}/raw Response: 200, text/plain: the original MIME message.
Get message text body GET /rest/messages/{id}/text Response: 200, text/plain: the text body if one was present, 404 otherwise.
Get message HTML body GET /rest/messages/{id}/html Response: 200, text/html: the HTML body if one was present, HTTP 404 otherwise. Any embedded content in the HTML will be replaced with a URI to the 'embedded content' endpoint (next)
Get embedded content GET /rest/messages/{id}/content/{cid} Response: 200, The embedded content with identifier 'cid' will be served with its related content type
Get attachment (new in 2.0) GET /rest/messages/{id}/att/{att_id} Response: 200 with the headers and content associated with the referenced attachment ID (the attachment ID is found in the attachments[] array in the /rest/messages/{id} response.
Forward message POST /rest/messages/{id}/forward Request: application/json: The recipient email, in the format: {"recipient":""}.

Response: 202 on acceptance.


If using the RPM deployment, HoldMail will look for an optional file called /etc/ which it will use to override its default configuration.

Note: Since this is the initial release of holdmail, configuration is somewhat limited and is likely to receive some necessary cleanup/namespacing in the future. While any Spring Boot configuration is currently supported in this file, it may not be guaranteed to work in future releases.

Port Numbers

# HTTP/REST (default is 8080)

# SMTP (default is 25000)


HoldMail is designed to be open. There are no accounts or mailboxes to configure. Mail for any recipient will be stored and will be queryable. This is to facilitate the ease of email testing without requiring test authors/performers to perform mailbox setup in advance.

If you're going to have to expose the HTTP service to a larger group than desired, you can use spring basic configuration to lock it down:


Using a different Datasource

By default, the application will create a H2 database file called in the running user's home directory (this is /opt/holdmail/ if you used the RPM intaller).

This should be good enough for most users, but if you want to use a different RDBMS such as MySQL, you can configure your own datasource. Add your configuaration to /etc/ using the relevant Spring Boot DataSource properties. The following example shows how to configure to connect to a MySQL DB:

  • The app manages its own database, so this user will need to have sufficient provileges to create and modify tables.

  • HoldMail doesn't distribute drivers for external databases (for reasons of distributable size, but mostly to avoid farcical licensing complications 🙈).

    • If using the HoldMail RPM distribution, place your driver JAR file in /opt/holdmail/lib and the app will find it automatically.
    • To use the MySQL configuration above, you'll need to download the MySQL connector driver JAR yourself.

Mail Forwarding

To release forwarded mails from HoldMail to the real world, you'll need to configure an external SMTP relay server. By default, HoldMail is configured with itself as the outgoing SMTP relay, so forwarded messages will just end up back in HoldMail!

⚡ This feature is in its infancy, and can be temperamental. Most real-world relays are (and should be) pretty strict and may reject, or worse, silently discard a forwarded email. A familiar "From" email may be specified, as many relays won't trust arbitrary sender addresses. Your system/network administrator may be needed to help you trace outbound delivery issues.

# the outgoing relay hostname (default: localhost)

# the outgoing relay port (default: holdmail's SMTP port)

# the "From" header to be set on a forwarded mail (default: holdmail@localhost.localdomain)

Run It From Source

HoldMail's backend is a Spring Boot application, exposing a REST API and SMTP server. The UI is built with Vue.js.

You'll Need:

To build from the command line, use:

gradle build (this builds the UI as well)

You'll find the JARs under build/libs, with the RPM under build/rpm.

Most modern Java-aware IDEs should be able to import build.gradle and launch the app by running the HoldMailApplication class, but from the command line, the server can be launched in dev mode by using:

gradle bootRun

The UI can also be run in dev mode by navigating to the client/ directory and using:

npm start

Run it from Docker

Images of HoldMail are pushed to our private docker registry hosted on Bintray. The image pushed is our MySQL based image, and should be used within a docker compose or similar setup pointing to an external MySQL database. You can find an example at docker-compose.yml.

If you want to pull the container yourself, you can use docker pull

Building the Docker container

To build the application, including docker image and pushing to bintray, use the following gradle command:

./gradlew build docker dockerPush

If you want to push to another registry, you can use -DdockerName=your.repo/namespace/image-name on the command line.



HoldMail is licensed under the Apache 2.0 license.

Sparta Systems

© Copyright 2016 - 2018 Sparta Systems Inc.

Sparta Systems helps customers bring products to market safely and efficiently by delivering quality management software solutions that provide control and transparency throughout the enterprise and their critical supplier network.

HoldMail is a product of Sparta's R&D department, built to help us test notification systems in our applications. Efficient and comprehensive automated testing is an integral feature of how we build software. Come work with us!.

You can’t perform that action at this time.