The original project FakeSMTP uses a java swing GUI which is fine if you want something basic and don't wish to use docker.
This project provides web support for FakeSMTP running in docker with the following features
- rest api supporting common crud operations
- server sent events for 'real time' email detection
- web ui written in elm
The rest api produces email data modelled from a MimeMessage including attachments and other nice to know things you would typically like to see during development. See API.
- Within this repository, copy and paste the
docker-compose.yml
file into an empty directory on your local machine. - cd into the directory containing this
docker-compose.yml
file docker-compose up -d
.
Open a browser and navigate to http://localhost:60500
which will display the ui (it may take a minute to start up).
To start with, its likely no emails will show up in the UI. The docker-compose.yml
contains a volumes
section. By default, any emails added to
~/fake-smtp-emails
on your local machine will be visible on the UI. Feel free to change this to whatever you like!
volumes:
- ~/fake-smtp-emails:/var/mail
-
See API for rest endpoints.
-
See API URL and port settings to change the IP and port.
If you don't wish to use docker compose, you'll need to start each container individually.
1 - FakeSMTP docker needs to be run first
docker run --name fake-smtp -d -p 25:25 -v ~/fake-smtp-emails:/var/mail munkyboy/fakesmtp
2 - Start the fakesmtp-web container (Note: the host port must be 60500
, see Configuration)
docker run --name fake-smtp-web -d -p 60500:8080 -v ~/fake-smtp-emails:/var/mail mjstewart/fakesmtp-web:1.3
If you need to change any configuration settings outlined in Configuration, the docker syntax for passing in environment variables is
docker run --name fake-smtp-web -d -p 60500:8080 \
-v ~/fake-smtp-emails:/var/mail \
-e EMAIL_INPUT_DIR_POLL_RATE_SECONDS=10 \
mjstewart/fakesmtp-web:1.3
docker-compose.yml
is used as the walk through example.
The volumes
mapping for both containers is
~/fake-smtp-emails:/var/mail
You can read this as - Within the docker container, /var/mail
is used to store emails which is mounted to the host
directory ~/fake-smtp-emails
. IMPORTANT - Please ensure the host directory ~/fake-smtp-emails
has the correct
permissions such as non root owner and its writable. Both can be changed using chown
and chmod
respectively.
This results in
- docker-fakesmtp writing emails into
~/fake-smtp-emails
- fakesmtp-web reading emails from
~/fake-smtp-emails
If you want a different host directory, be sure to change both volumes for each service eg:
/some-other-dir:/var/mail
~/fake-smtp-emails
is polled every 10 seconds to check for new emails.
This can be changed by setting EMAIL_INPUT_DIR_POLL_RATE_SECONDS
.
I would recommend this over 1 second to avoid potential issues in emails not getting parsed correctly.
http://localhost:60500
is used by default to prevent port clashes on the host machine. The docker port mappings must NOT
be changed as the ui is a SPA (Single page application). This means webpack injects the API endpoints when the bundle is built.
If you wish to deploy on a different IP and port, you'll have to manually build the project. See Build custom docker image
By default, http://localhost:60500
is the server IP and port the application is accessible on.
This behaviour can be changed by manually building a new docker image through the following steps.
You will need yarn
and maven
installed on your system. Once installed, go to the project directory and
execute the build.sh
script.
Note: Since you're building a custom image yourself, feel free to remove my image name in any of the docker steps
Instead of this
docker build -t mjstewart/fakesmtp-web:1.3 .
you might like to change it to your name (this will also avoid any name collisions with an existing image off dockerhub)
docker build -t alice/fakesmtp-web:1.0 .
-
Optional - set server IP and port in
build.sh
using environment variableFAKE_SMTP_WEB_API
. I don't really know of a usecase but I suppose if you were running this on a remote machine it could be useful? -
If
FAKE_SMTP_WEB_API
is updated, thefake-smtp-web
service indocker-compose.yml
must have its port mappings updated to be the same. -
To avoid the docker image name clashing with the existing image on docker hub, change the image name in
build.sh
to something unique.docker build -t custom/fakesmtp-web .
-
Run
./build.sh
See FAQ for non docker build instructions.
Note I apologise for this ceremony of having to build a new image just for a port change, if there is a better way please let me know.
Subscribe to receive new emails. The id should be a unique identifier the server uses to track your session. Eg - something like this is fine.
http://localhost:60500/api/stream/emails/client123Blah
The frequency of receiving new emails depends on the environment variable
EMAIL_INPUT_DIR_POLL_RATE_SECONDS
. This is configurable in docker-compose.yml
.
Returns collection of all the emails.
Its possible to sort the emails by any field and order. For example, to get all emails ordered from newest to oldest.
/api/emails?sort=sentDate,desc
- All string fields should be considered optional and may return null depending on the email parsing.
- Arrays are always empty if there's no data rather than null.
{
"_embedded": {
"emails": [
{
"id": "95f665cc-bbf3-4da5-a2cb-621c69d59b50",
"subject": "Testing registration service",
"replyTo": [
"[email protected]"
],
"body": {
"content": "some html string here",
"contentType": {
"mediaType": "text/html"
}
},
"receivedDate": null,
"sentDate": "2017-12-25T06:55:34",
"description": "a test email",
"toRecipients": [
"[email protected]"
],
"ccRecipients": ["[email protected]", "[email protected]"],
"bccRecipients": ["[email protected]", "[email protected]"],
"attachments": [
{
"id": "d81dcf50-cb89-4cd2-b348-d41215020513",
"fileName": "styles.css",
"contentType": {
"mediaType": "text/css"
}
},
{
"id": "f4bc2c82-7dad-40f4-9ae1-f102525cb525",
"fileName": "notes.txt",
"contentType": {
"mediaType": "text/plain",
}
},
{
"id": "62edda6b-7d67-4c43-8093-4af029c19e0f",
"fileName": "menu",
"contentType": {
"mediaType": "text/plain"
}
},
{
"id": "86495017-7988-496c-8e3b-b8d597e91853",
"fileName": "styles",
"contentType": {
"mediaType": "text/css"
}
}
],
"read": false,
"from": [
"[email protected]"
],
"_links": {
"self": {
"href": "http://localhost:60500/api/emails/95f665cc-bbf3-4da5-a2cb-621c69d59b50"
},
"email": {
"href": "http://localhost:60500/api/emails/95f665cc-bbf3-4da5-a2cb-621c69d59b50"
}
}
}
]
},
"_links": {
"self": {
"href": "http://localhost:60500/api/emails"
},
"profile": {
"href": "http://localhost:60500/api/profile/emails"
}
}
}
Get a single email by id
Delete a single email by id. Returns 204 No Content on successful deletion.
Delete all emails. Returns 204 No Content on successful deletion.
Include a json body with either action type to mark all emails read / unread.
{
"action": "READ_ALL" | "UNREAD_ALL"
}
The response is a list containing the read status of each updated email.
[
{
"id": "95f665cc-bbf3-4da5-a2cb-621c69d59b50",
"read": true
},
{
"id": "35f665cc-ccc3-4da5-a2cb-621c69d59b50",
"read": true
},
]
Update any field in a single email. Returns 200 OK on successful update.
For example, to change an emails subject, read, replyTo
fields.
{
"subject": "a new subject...",
"read": true,
"replyTo": ["[email protected]"]
}
-
Confirm the volume directory on the host has the correct permissions. Such as read/write/execute and non root user.
-
If you're running this on a remote server or docker in a VM such as on a mac or windows, its likely the default image cannot be used since the client javascript bundle has already been injected with the
localhost:60500
API endpoint. You will need to rebuild your own image using the docker ip on your machine - See Build custom docker image
Technically no, but using docker-compose
really simplifies the setup.
To use without docker assuming you have some form of FakeSMTP (standalone jar or in docker) writing emails to an output directory then...
-
clone this repo
-
set environment variables on your host machine. (Be careful - its common to need to reboot your computer for these variables to be updated or to
source ~/.bashrc
depending on your method.)-
EMAIL_INPUT_DIR=/output-directory
(The directory FakeSMTP is writing emails into) -
EMAIL_INPUT_DIR_POLL_RATE_SECONDS=10
-
FAKE_SMTP_WEB_API
(IP address and port the API will be deployed on, eghttp://localhost:60500
).
-
-
build
You will need yarn and maven installed on your system. Once installed, go to the project directory and execute the following commands in order.
cd src/main/ui yarn yarn run build cd ../../../ mvn clean package -DskipTests
-
Run
Run the jar maven created in the target folder of the project root directory. Specify the port you chose in FAKE_SMTP_WEB_API, eg 60500 using
-Dserver.port
option unless you use the default 8080.java -Dserver.port=60500 -jar target/fakesmtp-web-1.2.jar
-
When you want to set context path, you can do it for spring boot using
server.servlet.context-path
property. In addition, you need to update theFAKE_SMTP_WEB_API
variable.For example if you add context path as
server.servlet.context-path=/mail
append the context to
FAKE_SMTP_WEB_API
as belowhttp://localhost:8080 -> http://localhost:8080/mail
Same applies to the port number as well. Note : For the standalone (no docker) implementation, we can keep same port number.
-
Change
publicPath
in file below to update the context path.src\main\ui\webpack.config.js
Example: if context path is
/mail
make change asconst publicPath = (env === 'prod') ? '/ui/' : '/'; const publicPath = (env === 'prod') ? '/mail/ui/' : '/';
-
Recompile the application.
- Spring Boot
- Spring Integration
- Elm
Spring integration is used to poll the EMAIL_INPUT_DIR
representing the directory FakeSMTP outputs emails into. This
directory corresponds to the mounted host directory used in docker ~/fake-smtp-emails
.
The poll rate is configurable using EMAIL_INPUT_DIR_POLL_RATE_SECONDS
.
Spring integration reads every new email in this directory and parses it into valid domain objects before sending it into a pub/sub channel where 2 subscribers are waiting.
-
subscriber 1 saves the email into a h2 in memory database which enables the rest api.
-
subscriber 2 emits the email through a server sent event stream for real time email updates.
Since the UI is a SPA, it doesn't work so nicely with docker host:container port mappings since the javascript bundle has the API endpoints injected during the webpack build.
webpack builds the elm bundle and assets into resources/static
which is where spring boot serves static content by default.
webpack also generates the ui entry point index.html
in resources/templates
which spring boot serves up by default.
cd /src/main/ui
yarn run build
Development can be done using webpack dev server yarn run start
.