• Stars
    star
    537
  • Rank 82,649 (Top 2 %)
  • Language
    Shell
  • License
    Apache License 2.0
  • Created about 9 years ago
  • Updated about 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Simplest and Smallest Email Forward Service based on Docker.

Simple Mail Forwarder (SMF) Docker

Gitter layers Docker Pulls Docker Stars Docker Repository on Quay.io

dockeri.co

Simplest and Smallest Email Forward Service for Docker.

  1. Config by one-line
  2. Run as docker start
  3. Image Size 10MB

View on GitHub | View on Docker

Voice from Users

@Brian Christner : After testing a ton of different mail projects I finally discovered Simple Mail Forwarder (SMF) by Huan. This image is based on Alpine which is already a positive. It is super tiny and as the name suggests, easy to use. link

@kachkaev : really happy to discover it! link

@kiani: have a working mail server, seriously, it was that easy. link

@counterbeing: great image. Wonderfully easy interface, with all that i need. 👍 link

@nelfer: Guess what? Your image already supports this! link

@Czocher: It's at least a timesaver if not a lifesaver. link

@StrangePeanut: I am so glad to have found SMF. Many thanks for this brilliant solution to email forwarding. link

What is Simple Mail Forwarder (SMF)?

If you have a domain name, only want to have one (or a few) email address(es) on this domain, and you want to forward all the emails to another email account - Simple Mail Forwarder (SMF) is exactly what you need. (with Docker)

Because of the above, this docker image was built for ultimate simplicity. I've owned many domains and needed email addresses for them (for fun and/or work). I hated configuring email servers. Some DNS providers provide free email forwarding services for their own domains, some do not. And almost all email forwarding services are NOT free. So I decided to make one myself (thanks docker).

Related Services

I was willing to pay $10/year, but the cheapest plan I could find was $9 per month. Having a $10 USD machine with unlimited e-mail & domains per month is an amazing idea! And of course you could also put other dockers on this machine. :-D

Quick-start (TL;DR)

Just set SMF_CONFIG and run:

export SMF_CONFIG='[email protected]:[email protected]:test'
docker run -e SMF_CONFIG -p 25:25 zixia/simple-mail-forwarder

Don't forget to modify the DNS MX record of your domain. (in this example, it's testo.com)

This will forward all emails received by [email protected] to [email protected].

If you want to forward all emails sent to domain testo.com to [email protected], set it like so:

export SMF_CONFIG='@testo.com:[email protected]'

See? There is nothing easier.

If you want to run it constanly in the background add -t -d --restart=always after run:

docker run -t -d --restart=always -e SMF_CONFIG -p 25:25 zixia/simple-mail-forwarder
  • -t: Allocate a pseudo-tty
  • -d: Detached Mode
  • --restart=always: Restart this container automatically

Otherwise, docker thinks that your applications stops and shutdown the container.

Quick Test

Tested by BATS(Bash Automated Testing System), a bash implementation of TAP(Test Anything Protol).

How to run:

$ docker run zixia/simple-mail-forwarder test
>> exec bats test
1..20
ok 1 confirm hostname pretend to work.
ok 2 confirm hwclock pretend to work.
ok 3 service postfix could start/stop right.
ok 4 SMF_CONFIG exist
ok 5 SMF_DOMAIN exist
ok 6 virtual maping source is set
ok 7 virtual maping data is set
ok 8 virtual maping db is set
ok 9 system hostname FQDN resolvable
ok 10 postfix myhostname FQDN & resolvable
ok 11 check other hostname setting
ok 12 confirm postfix is running
ok 13 confirm port 25 is open
ok 14 crond is running
ok 15 ESMTP STATTLS supported
ok 16 ESMTP AUTH supported
ok 17 ESMTP STARTTLS supported
ok 18 create user [email protected] by password test
ok 19 ESMTP AUTH by [email protected]/test
ok 20 ESMTP TLS AUTH by [email protected]/test

You are all set! :-]

Environment Variable and Default Values

SMF_CONFIG: MUST be defined. there's no default setting. (set me! I'm the only parameter you need to set~)

TZ : (Optional) set the timezone , IE EST5EDT or Europe/Rome

SMF_CONFIG Examples

Here's how to config the only required SMF_CONFIG environment parameter of SMF Docker:

1. Basic

Forward all emails received by [email protected] to [email protected]:

Forward all emails received by any email address in domain testo.com to [email protected]:

export SMF_CONFIG='@testo.com:[email protected]'

You could get the ESMTP AUTH password for you on your docker log. It's randomly generated if you do not provide one.

2. Advanced

Add ESMTP AUTH password:

export SMF_CONFIG='[email protected]:[email protected]:ThisIsPassword'

Password will be printed on the docker log.

3. Hardcore

Add as many email accounts as you want, with or without password. Seperated by semicolon or a new line:

export SMF_CONFIG='[email protected]:[email protected]:ThisIsPassword;[email protected]:[email protected]:AnotherPassword'

Tips: if you only provide the first password and leave the rest blank, then the passwords for all the rest accounts will be the same as the last password value you set. This is by design.

You can also forward all emails received by [email protected] to multiple destination addresses:

SMF_RELAYHOST Examples

Here's how to configure a relayhost/smarthost to use for forwarding mail.

Send all outgoing mail trough a smarthost on 192.168.1.2

export SMF_RELAYHOST='192.168.1.2'

SMF_RELAYAUTH Examples

If the SMF_RELAYHOST require authentication,

export SMF_RELAYAUTH='[email protected]:RelayHostPassword'

TLS (SSL) Certificates

SMF creates its own certificate and private key when it starts. This certificate is self signed, so some systems might give you a warning about the server not being trusted. If you have valid certificates for the domain name of the host, then you can use them and avoid the warning about not being trusted.

  1. First you need to prepare the certificate files. Copy your full chain certificate to a file named smtp.cert (or smtp.ec.cert if it contains a EC certificate). Then copy the private key to a file named smtp.key (or smtp.ec.key if it contains a EC key)

  2. Copy these files to a folder. For example: /data/certs/. This folder will be mounted as a volume in SMF

  3. When creating the container, add the -v (volume) parameter to mount it to the folder /etc/postfix/cert/ like so:

    docker run  -e SMF_CONFIG -p 25:25 -v /data/certs/:/etc/postfix/cert/ zixia/simple-mail-forwarder
  4. Your emails should now be forwarded with trusted encryption. You can use this tool to test it: http://checktls.com/

If you do not have a certificate and don't have the budget to afford one, you can use https://letsencrypt.org if you have shell access to the server (Note, SMF does not provide this service, yet). Letsencrypt allows you to create valid trusted certificates for a server, if the server responds to the domain you specify. In order to do this, you need to run the program from within the server and have administrator rights.

  1. First install letsencrypt. This might vary by distribution, but in Ubuntu it is like this:

    sudo apt-get install letsencrypt
  2. Stop any web server that might be using port 80 (Apache, nginx, etc)

  3. Determine all of the domains and subdomains that you want the certificate to cover, for example mydomain.com, www.mydomain.com, smtp.mydomain.com, etc. Remember to include the domain that SMF will respond to (as per MX record in DNS configuration of the domain)

  4. Execute the following command (you can add as many domains as you wish with the -d option. But remember, their DNS resolution must resolve to the server where letsencrypt is being executed)

    letsencrypt certonly --standalone -d yourdomain.com -d www.yourdomain.com -d mail.yourdomain.com
  5. Follow the prompts and if everything is successful you will get your certificates in a folder like /etc/letsencrypt/live/mydomain.com

  6. You can now use those certificates to make SMF TLS trusted.

This was a quick way of how to use letsencrypt. For a full tutorial based on your OS see: https://certbot.eff.org/

DKIM

SMF will generate private/public keypairs for $SMF_DOMAIN and for all source domains contained in SMF_CONFIG. All keys will be stored in /var/db/dkim/<domain.tld>/.

This will enable DKIM for multiple domains and test for their validity on SMF startup.

Public key must be set as TXT record in DNS under default._domainkey name. default._domainkey can be found in /var/db/dkim/<domain.tld>/default.txt.

It is highly advised to mount /var/db/dkim/ folder to host, so generated keypair would not get lost/regenerated:

docker run -e SMF_CONFIG -p 25:25 -v $(pwd)/dkim:/var/db/dkim/ zixia/simple-mail-forwarder

SMF allows using environment variables to change the size of the DKIM key:

  • SMF_DKIM_KEYSIZE will set the keysize of the generated DKIM key (setting opendkim-genkey -b $SMF_DKIM_KEYSIZE). Defaults to 2048.

Stripping sender details

SMF will strip the sender's IP, client, and user agent headers when the SMF_SENDERPRIVACY environment variable is defined.

Custom postfix configuration

SMF allows using environment variables to add or change lines to postfix main.cf and master.cf configuration files.

  • SMF_POSTFIXMAIN_* variables will edit postfix main.cf entries.

    • Format: SMF_POSTFIXMAIN_option_name=value
    • Example: SMF_POSTFIXMAIN_soft_bounce=yes will call postconf -e soft_bounce=yes and add the option.
  • SMF_POSTFIXMASTER_* variables will edit postfix master.cf.

    • Format: SMF_POSTFIXMASTER_service__name__type__parameter_name=value Please note the double underscore __ to differentiate service and type (which require a / as separation symbol) and the single underscore _ used only by parameter names.
    • Example: SMF_POSTFIXMASTER_submission__inet__smtpd__recipient_restrictions=permit_mynetworks,permit_sasl_authenticated,reject will call postconf -P submission/inet/smtpd/recipient_restrictions=permit_mynetworks,permit_sasl_authenticated,reject and add the option.

Logging

The default log configuration of postfix is sending all log entries to /dev/stdout. Because file logs are important in some cases, SMF allows overriding the default log configuration of postfix.

  • SMF_POSTFIXLOG will edit postfix logging configuration
    • Format: SMF_POSTFIXLOG=value
    • Example: SMF_POSTFIXLOG=/var/log/postfix.log will call postconf maillog_file="/var/log/postfix.log"

Attention: The logfile path must start with "/var".

When you wish to rotate logs, look at the postfix logrotate command in the official documentation.

Enable SRS (Sender Rewriting Scheme)

SRS is required if the sender uses SPF for verification. If SRS is not enabled, SPF verification will fail. (Additional Informations to SRS)

You can enable SRS by setting the environment variable SMF_SRS=true. This will start PostSRSd inside the container. The secret is automatically created and the domain is set to SMF_DOMAIN. Now you just need to set the following environment variables for Postfix:

SMF_POSTFIXMAIN_sender_canonical_maps=tcp:localhost:10001
SMF_POSTFIXMAIN_sender_canonical_classes=envelope_sender
SMF_POSTFIXMAIN_recipient_canonical_maps=tcp:localhost:10002
SMF_POSTFIXMAIN_recipient_canonical_classes=envelope_recipient,header_recipient

Helper Scripts

  1. Build from source.

    ./script/build.sh latest
  2. Run a self-test for SMF docker.

    ./script/run.sh latest test
  3. Get a shell inside SMF docker.

    ./script/devshell.sh latest

Manual Test

$ telnet 127.0.0.1 25
> 220 testo.com ESMTP
ehlo test.com
> 250-testo.com
> 250-STARTTLS
> 250-AUTH PLAIN LOGIN
auth plain
> 334
dGVzdGlAdGVzdG8uY29tAHRlc3RpQHRlc3RvLmNvbQB0ZXN0
> 235 2.7.0 Authentication successful
quit
> 221 2.0.0 Bye
> Connection closed by foreign host

P.S. The magic string dGVzdGlAdGVzdG8uY29tAHRlc3RpQHRlc3RvLmNvbQB0ZXN0 stands for [email protected]\[email protected]\0test in base64 encoding, required by AUTH PLAIN.

Useful article about SMTP Authentication: http://www.fehcom.de/qmail/smtpauth.html

Bug

Github Issue - https://github.com/huan/docker-simple-mail-forwarder/issues

Changelog

master

v1.4 (Mar 9, 2021)

  1. Update DockerHub README.md @thexperiments #94
  2. Allow for setting any Postfix variables in the config file (both main.cf and master.cf) @dgraziotin #93
  3. Strips sender details (IP, client, user agent) when sending @dgraziotin #91
  4. Adds DKIM support for multiple domains @dgraziotin #89
  5. DKIM support for multiple domains @dgraziotin #88
  6. Add DKIM support @petslane #83
  7. Use script to install s6 with right platforms (arm/x86) @huan #76

v1.3 (17 Sep 2020)

  1. Upgrade alpine docker base image to 3.12
  2. Fix timeout args breaking changes
  3. Fix etc and libexec path change for postfix

v1.1 (09 Jun 2019)

  1. Timezone support by @me1299 #56 #57
  2. EC key support by @Czocher #51
  3. Upgrade CircleCI from v1 to v2 @huan
  4. Fix typo in README @universeroc #47
  5. Update Base to Alpine 3.8 @riptidewave93 #43
  6. Update alpine:latest as base image @martijnrondeel #37

v1.0.0 (25 Jul 2017)

  • Release v1.0

v0.4.3 (14 Jul 2017)

  1. Add a note about running it in the background to prevent docker auto shutdown. by @delmicio #27
  2. Added smarthost support by @Duumke #22
  3. Added support for mynetworks by @SamMousa #20
  4. Allow own certificates by @nelfer #15
  5. Updated documentation for forward all emails @nelfer #14
  6. ARM version of armhf by @dimitrovs #12
  7. use SMF_DOMAIN env for certificate's CN by @bcardiff #11
  8. allow multiple forwards separated by | by @kminek #7
  9. Update docker-compose.yml to fix tutum tag by @vegasbrianc #4

v0.4.2 (25 Sep 2016)

  1. close issue #1
  2. increace message size limit from 10MB to 40MB
  3. fix domain name in scripts
  4. fix unit test fail error: do not upgrade alpine
  5. restore deploy button in readme: it is docker cloud now.(former tutum)

v0.4.0

  1. switch FROM image from alpine to sillelien/base-alpine
  2. manage postfix service by S6
  3. solve PID 1 Zombie Problem
  4. enhanced busybox shell
  5. NOT to use OpenRC(very buggy run inside docker container) any more!
  6. better ESMTP TLS AUTH test script
  7. docker image size: 10MB

v0.3.0 <- Don't use me, I'm BUGGY

  1. CI(continuous integration) supported by use CircleCI
  2. CD(continuous delivery) supported by use Tutum Button
  3. write better tests
  4. tune OpenRC inside alpine linux
  5. full description README
  6. docker image size: 7MB

v0.2.0 <- Don't use me, I'm BUGGY

  1. supported specify user password
  2. supported ESMTP TLS
  3. docker image size: 7MB

v0.1.0

  1. dockerized
  2. basic forward function
  3. self-testing
  4. docker image size: 6MB

Cloud Requirement

  • A Cloud Service that could host docker is required.

  • A Docker management platform is recommanded.

    • Docker Cloud(Former Tutum) Deploy to Docker Cloud
  • Docker is required.

    • Docker.com

CONTRIBUTORS

contributor contributor contributor contributor contributor contributor contributor contributor

Author

Profile of Huan LI (李卓桓) on StackOverflow

MAINTAINERS

COPYRIGHT & LICENSE

  • Code & Docs © 2015 - now Huan LI [email protected]
  • Code released under the Apache-2.0 License
  • Docs released under Creative Commons

More Repositories

1

docker-wechat

DoChat is a Dockerized WeChat (盒装微信) PC Windows Client for Linux
Shell
2,245
star
2

node-facenet

Solve face verification, recognition and clustering problems: A TensorFlow backed FaceNet implementation for Node.js.
TypeScript
399
star
3

docker-wxwork

DoWork is a Dockerized WeChat Work (盒装企业微信) PC Windows Client for Linux
Shell
126
star
4

gast

Google Apps Script TAP Testing-framework
JavaScript
96
star
5

rx-queue

Easy to Use RxJS Queue for Throttle/Debounce/Delay/DelayExecute
JavaScript
73
star
6

file-box

Pack a File into Box for easy move/transfer between servers no matter of where it is.(local, remote url, or cloud storage)
TypeScript
56
star
7

mailbox

Mailbox is the predictable states & transitions container for actors.
TypeScript
48
star
8

sidecar

Easily hook/call binary functions using ES6 class with TypeScript annotation (Powered by Frida)
JavaScript
47
star
9

docker-windows

Run Windows GUI Applications in a Linux Docker Container
Shell
44
star
10

hot-import

Hot Module Replacement (HMR) for Node.js
TypeScript
23
star
11

sshpass.sh

a ssh loader wrote by bash shell script to let ssh accept command line password
Shell
23
star
12

docker-wine

Docker Base Image for Wine
Shell
21
star
13

flash-store

FlashStore is a high-performance Key-Value Persistent Local Database using ES6 Map's API (Async & Sync), Powered by LevelDB/RocksDB/SQLite and TypeScript.
TypeScript
21
star
14

gasl

Google Apps Script Logging-framework
JavaScript
20
star
15

tensorflow-handbook-javascript

TensorFlow Handbook for JavaScript/TypeScript
TypeScript
19
star
16

tensorflow-handbook-tpu

TensorFlow 2 Handbook for TPU on Google Cloud
Jupyter Notebook
17
star
17

wechaty-blinder

Face Blinder Bot Powered by Wechaty
TypeScript
15
star
18

swagger-edit

Swagger-Editor for local files like VIM.
JavaScript
14
star
19

gas-freshdesk

OO Freshdesk API(v2) Class for Google Apps Script
JavaScript
12
star
20

brolog

Logger for AngularJS in Browser like Npmlog
JavaScript
11
star
21

chinese-whispers

An Efficient Graph Clustering Algorithm for Node.js
TypeScript
9
star
22

swift-MNIST

Swift Module for MNIST Dataset
Swift
9
star
23

watchdog

An Timer used to Detect and Recover from Malfunctions
TypeScript
9
star
24

tstest

Helps you write better TypeScript programs
JavaScript
8
star
25

paper-morpho-vector-presentation

A Mini Review of Word Embedding in Morpho
TeX
7
star
26

ffi-adapter

Foreign Function Interface Adapter Powered by Decorator & TypeScript
TypeScript
6
star
27

tensorflow-handbook-swift

TensorFlow Handbook for Swift
Jupyter Notebook
6
star
28

emoji-net

EmojiNet is an image to emoji recognizer based on MobileNet / Google Emoji Scavenger Hunt
TypeScript
6
star
29

ng-plus-wechaty

Conversational AI TensorFlow.js NLP examples with Wechaty SDK and Angular
TypeScript
5
star
30

memory-card

Memory Card is an Easy to Use Key/Value Store Implements ES6 Map with Async API in Distribution Scenarios.
TypeScript
5
star
31

liao.ga

尬聊助手
4
star
32

awesome-lucid-dream

A lucid dream is a dream during which the dreamer is aware that they are dreaming.
4
star
33

clone-class

Clone an ES6 Class as Another Class Name for Isolating Class Static Properties.
JavaScript
4
star
34

state-switch

State Switch is a Monitor/Guard for Managing Your Async Operations.
TypeScript
4
star
35

dofi

DoFi is a Docker Wifi Manager for converting your PC/Raspberry Pi to a Wireless Router
Shell
3
star
36

docker-swift-tensorflow

Dockerized Swift for TensorFlow with Jupyter and GPU Support.
3
star
37

face-blinder

API for Whom is Suffering form Face Blindess
TypeScript
3
star
38

microsoft-ai-bootcamp

Global AI Bootscamp Beijing
2
star
39

Browser-based-Models-with-TensorFlow.js

Course: Browser-based Models with TensorFlow.js
JavaScript
2
star
40

ai-art-design-workshop

AI Art & Design Workshop
2
star
41

docker-chown

`chown -r` & `COPY --chown` not work in my Dockerfile (?!)
Shell
2
star
42

sockie

Easy to Use Reactive Extensioned WebSocket Client/Server Framework for Node.js
TypeScript
2
star
43

wechaty-io

DEPRECATED(use @chatie/io instead) Wechaty IO Server
TypeScript
1
star
44

sse-3d-seg

Secondary Structure Elements 3D Segmentation for Protein
1
star
45

mike-bo

Mike Bo is an assitant bot for Huan@PreAngel
TypeScript
1
star
46

awkward-chat-assistant

尬聊助手
1
star
47

bbsnet

zixia bbsnet
TypeScript
1
star
48

watchdog.icu

Watchdog ICU for your Cloud Service
TypeScript
1
star
49

pkg-jq

Find the nearest package.json then deal with jq syntax on it. (in-line edit supported!)
TypeScript
1
star
50

python-concise-chitchat

Concise Chit Chat in Python
Jupyter Notebook
1
star