Final Migration Step (#6)

* first migration steps
  * altered issue templates
  * altered README
  * removed .travis.yml
* adjusting registry & repository, Dockerfile and compose.env
* Close stale issues automatically
* Integrated CI with Github Actions (#3)
* feat: integrated ci with github actions
* fix: use secrets for docker org and update image
* docs: clarify why we use -t if no tty exists
* fix: correct remaining references to old repo
chore: prettier automatically updated markdown as well
* fix: hardcode docker org
* change testing image to just testing
* ci: add armv7 as a supported platform
* finished migration steps
* corrected linting in build-push action
* corrected linting in build-push action (2)
* minor preps for PR
* correcting push on pull request and minor details
* adjusted workflows to adhere closer to @wernerfred's diagram
* minor patches
* adjusting Dockerfile's installation of base packages
* adjusting schedule for stale issue action
* reverting license text
* improving CONTRIBUTING.md PR text
* Update CONTRIBUTING.md
* a bigger patch at the end
  * moved all scripts into one directory under target/scripts/
  * moved the quota-warning.sh script into target/scripts/ and removed empty directory /target/dovecot/scripts
  * minor fixes here and there
  * adjusted workflows for use a fully qualified name (i.e. docker.io/...)
  * improved on the Dockerfile layer count
  * corrected local tests - now they (actually) work (fine)!
  * corrected start-mailserver.sh to make use of defaults consistently
  * removed very old, deprecated variables (actually only one)
* various smaller improvements in the end
* last commit before merging #6
* rearranging variables to use alphabetic order

Co-authored-by: casperklein <casperklein@users.noreply.github.com>
Co-authored-by: Nick Pappas <radicand@users.noreply.github.com>
Co-authored-by: William Desportes <williamdes@wdes.fr>
This commit is contained in:
Georg Lauterbach 2021-01-16 10:16:05 +01:00 committed by GitHub
parent 66422cbcb0
commit 189e5376cc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
57 changed files with 1644 additions and 1671 deletions

View File

@ -1,4 +1,6 @@
.github .github
.git .git
.idea
.vscode
test/ test/

View File

@ -1,37 +0,0 @@
## Pull requests
We gladly accept pull requests to add documentation, fix bugs and, in some circumstances,
add new features to Spree.
Here's a quick guide:
1. Fork the repo
2. Clone the fork to your local machine
3. Create new branch then make changes and add tests for your changes. Only
refactoring and documentation changes require no new tests. If you are adding
functionality or fixing a bug, we need tests!
4. Run the tests. `make build-no-cache generate-accounts run fixtures tests clean`
5. Push to your fork and submit a pull request. If the changes will apply cleanly
to the master branch, you will only need to submit one pull request.
Don't do pull requests against `-stable` branches. Always target the master branch. Any bugfixes we'll backport to those branches.
At this point, you're waiting on us. We like to at least comment on, if not
accept, pull requests within several days.
We may suggest some changes or improvements or alternatives.
Some things that will increase the chance that your pull request is accepted.
Syntax:
* Two spaces, no tabs.
* No trailing whitespace. Blank lines should not have any space.
* Follow the conventions you see used in the source already.
* Alphabetize the class methods to keep them organized
And in case we didn't emphasize it enough: we love tests!

View File

@ -1,20 +1,16 @@
--- ---
name: "\U0001F41E Bug report" name: "\U0001F41E Bug report"
about: Create a report about a reproducible bug about: Create a report about a reproducible bug
title: '' title: "[BUG]"
labels: bug, needs triage labels: area/bug, meta/needs triage, priority/medium
assignees: '' assignees: ""
--- ---
<!--- Provide a general summary of the issue in the Title above -->
<!-- Thanks for the bug report! -->
<!--- <!---
## Possible answers to you issue Possible answers to your issue
* ClamAV keeps restarting: * ClamAV keeps restarting:
https://github.com/tomav/docker-mailserver#requirements https://github.com/docker-mailserver/docker-mailserver#requirements
* Email seen as spam: * Email seen as spam:
https://github.com/tomav/docker-mailserver/wiki/Configure-SPF https://github.com/tomav/docker-mailserver/wiki/Configure-SPF
@ -34,53 +30,52 @@ assignees: ''
https://github.com/tomav/docker-mailserver/wiki https://github.com/tomav/docker-mailserver/wiki
* Open issues * Open issues
https://github.com/tomav/docker-mailserver/issues https://github.com/docker-mailserver/docker-mailserver/issues
--> -->
# Bug Report
## Context ## Context
<!--- Provide a more detailed introduction to the issue itself -->
<!--- How has this issue affected you? What were you trying to accomplish? -->
### *What* is affected by this bug? <!--- Provide a general summary of the bug -->
### What is affected by this bug?
### When does this occur?
### *When* does this occur? ### How do we replicate the issue?
## *How* do we replicate the issue?
<!--- Provide a link to a live example, or an unambiguous set of steps to -->
<!--- reproduce this issue include code to reproduce, if relevant -->
1. 1.
2. 2.
3. 3.
4. 4.
## Actual Behavior ## Behavior
<!--- Tell us what happens instead -->
## Expected behavior (i.e. solution) ### Actual Behavior
<!--- Tell us what should happen -->
### Expected Behavior
## Your Environment ## Your Environment
<!--- Include as many relevant details about the environment you experienced the issue in --> <!--- Include as many relevant details about the environment you experienced the issue in -->
* Amount of RAM available:
* Mailserver version used:
* Docker version used:
* Environment settings relevant to the config:
* Any relevant stack traces ("Full trace" preferred):
<!--- - version: `v`
Please remember to format code using triple backticks (`) so that it is neatly formatted when the issue is posted. - available RAM: `GB`
- Docker version: `v`
Spoilers are recommended for readability: ### Environment Variables
<details>
<summary>Click me to expand </summary>
```sh
echo "hello world"
```
</details>
--> ```CFG
```
### Relevant Stack Traces
<!-- Remember to format code using triple backticks (`) so that it is neatly formatted when the issue is posted. -->
```BASH
# BEGIN
# END
```

View File

@ -1,42 +1,48 @@
--- ---
name: "\U0001F389 Feature request" name: "\U0001F389 Feature request"
about: Suggest an idea for this project about: Suggest an idea for this project
title: '' title: '[FR]'
labels: feature request, needs triage labels: area/enhancement, kind/feature request, meta/needs triage, priority/low
assignees: '' assignees: ''
--- ---
## Is your feature request related to a problem? # Feature Request
<!-- A clear and concise description of what the problem is. -->
## Context
## Describe the solution you'd like ### Is your Feature Request related to a Problem?
<!-- A clear and concise description of what you want to happen. -->
## Alternatives you've considered ### Describe the Solution you'd like
<!-- A clear and concise description of any alternative solutions or features you've considered. -->
## Who will that feature be useful to? ### Are you going to implement it?
<!-- Is it solving a common problem, or is it an improvement that all current users will benefit from? -->
<!-- Select one, remove the other and do not shorten the sentence -->
Yes, because I know the probability of someone else doing it is low and I can learn from it.
## What have you done already? No, and I understand that it is highly likely no one will implement it. Furthermore, I understand that this issue will likely become stale and will be closed.
<!-- If you already built a prototype or a complete implementation of that feature, where is it possible to see it? -->
### What are you going to contribute??
## What are you going to contribute?
<!-- Besides testing volunteering work made by other people, what are you going to contribute in order to help have that feature implemented, tested and documented? -->
## Additional context ## Additional context
<!-- Add any other context about the feature request here. -->
### Alternatives you've considered
### Who will that Feature be useful to?
### What have you done already?

View File

@ -1,21 +1,27 @@
--- ---
name: "❓ Question" name: "❓ Question / Other"
about: Ask a question about docker-mailserver about: Ask a question about docker-mailserver
title: '' title: ''
labels: question, needs triage labels: kind/question, priority/low, meta/help wanted, meta/needs triage
assignees: '' assignees: ''
--- ---
## Subject # Subject
<!-- Select one, remove the others: -->
* [ ] I would like to contribute to the project (code, documentation, advocacy, integration, ...) <!-- Select one, remove the others -->
* [ ] I would like some help for integrating this container with another service (rainloop, PostFWD, ...)
* [ ] I would like to configure a not documented mail server use case I would like to contribute to the project
* [ ] I would like some feedback concerning a use case I would like to configure a not documented mail server use case
* [ ] I have questions about TLS/SSL/STARTTLS/OpenSSL I would like some feedback concerning a use case
* [ ] Other I have questions about TLS/SSL/STARTTLS/OpenSSL
Other
## Description ## Description
<!-- When copy/pasting code, format the code with tripe backticks (`) ! -->
``` BASH
# CODE GOES HERE
```

View File

@ -0,0 +1,22 @@
name: "Close Stale Issues"
on:
schedule:
- cron: "0 1 * * *"
jobs:
stale:
runs-on: ubuntu-latest
steps:
- uses: actions/stale@v3
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
days-before-stale: 1 # TODO just for testing purposes, otherwise (20)
days-before-close: 1 # TODO just for testing purposes, otherwise (10)
stale-issue-label: "meta/stale"
close-issue-label: "meta/frozen due to age or inactivity"
stale-issue-message: >
This issue has become stale because it has been open for 20 days without
activity. Remove the label and comment or this issue will be closed in 10 days.
close-issue-message: >
This issue was closed due to inactivity.

116
.github/workflows/default_on_push.yml vendored Normal file
View File

@ -0,0 +1,116 @@
name: "Build, Test & Deploy"
on:
push:
branches: [ "master", "stable" ]
jobs:
build:
runs-on: ubuntu-latest
outputs:
imagetag: ${{ steps.prep.outputs.imagetag }}
steps:
- name: Checkout
uses: actions/checkout@v2
with:
submodules: recursive
- name: Prepare
id: prep
run: |
DOCKER_IMAGE=docker.io/mailserver/testing
TAGS="${DOCKER_IMAGE}:${GITHUB_SHA::8},${DOCKER_IMAGE}:latest"
echo ::set-output name=tags::${TAGS}
- name: Set up QEMU
uses: docker/setup-qemu-action@v1
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
id: buildx
- name: Cache Docker layers
uses: actions/cache@v2
with:
path: /tmp/.buildx-cache
key: ${{ runner.os }}-buildx-${{ github.sha }}
restore-keys: |
${{ runner.os }}-buildx-
- name: Login to DockerHub
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Build image locally
uses: docker/build-push-action@v2
with:
builder: ${{ steps.buildx.outputs.name }}
context: .
file: ./Dockerfile
build-args: |
VCS_REF=${{ github.sha }}
VCS_VER=${{ github.ref }}
platforms: linux/amd64,linux/arm/v7,linux/arm64
pull: true
push: true
tags: ${{ steps.prep.outputs.tags }}
cache-to: type=local,dest=/tmp/.buildx-cache
test:
needs: build
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
with:
submodules: recursive
- name: run test suite
run: |
NAME=docker.io/mailserver/testing:${GITHUB_SHA::8} bash -c 'make generate-accounts tests'
env:
CI: true
publish:
needs: test
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
with:
submodules: recursive
- name: Prepare
id: prep
run: |
DOCKER_IMAGE=docker.io/mailserver/docker-mailserver
VERSION=latest
[[ $GITHUB_REF == refs/tags/* ]] && VERSION=${GITHUB_REF#refs/tags/v}
TAGS="${DOCKER_IMAGE}:${VERSION}"
[[ $VERSION =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]] && TAGS="$TAGS,${DOCKER_IMAGE}:latest"
echo ::set-output name=tags::${TAGS}
- name: Set up QEMU
uses: docker/setup-qemu-action@v1
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
id: buildx
- name: Cache Docker layers
uses: actions/cache@v2
with:
path: /tmp/.buildx-cache
key: ${{ runner.os }}-buildx-${{ github.sha }}
restore-keys: |
${{ runner.os }}-buildx-
- name: Login to DockerHub
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Build image locally
uses: docker/build-push-action@v2
with:
builder: ${{ steps.buildx.outputs.name }}
context: .
file: ./Dockerfile
build-args: |
VCS_REF=${{ github.sha }}
VCS_VER=${{ github.ref }}
platforms: linux/amd64,linux/arm/v7,linux/arm64
pull: true
push: true
tags: ${{ steps.prep.outputs.tags }}
cache-from: type=local,src=/tmp/.buildx-cache

40
.github/workflows/linting.yml vendored Normal file
View File

@ -0,0 +1,40 @@
name: "Lint"
on:
pull_request:
branches: [ "*" ]
push:
branches: [ "master", "stable" ]
jobs:
lint:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
with:
submodules: recursive
- name: Hadolint
run: |
sudo curl -S -L https://github.com/hadolint/hadolint/releases/download/v${HADOLINT_VERSION}/hadolint-$(uname -s)-$(uname -m) -o /usr/local/bin/hadolint
sudo chmod +rx /usr/local/bin/hadolint
make hadolint
env:
HADOLINT_VERSION: 1.19.0
- name: ShellCheck
run: |
sudo curl -S -L "https://github.com/koalaman/shellcheck/releases/download/v${SHELLCHECK_VERSION}/shellcheck-v${SHELLCHECK_VERSION}.linux.x86_64.tar.xz" | tar -xJ
sudo mv "shellcheck-v${SHELLCHECK_VERSION}/shellcheck" /usr/bin/
sudo rm -rf "shellcheck-v${SHELLCHECK_VERSION}"
make shellcheck
env:
SHELLCHECK_VERSION: 0.7.1
- name: ECLint
run: |
sudo curl -S -L "https://github.com/editorconfig-checker/editorconfig-checker/releases/download/${ECLINT_VERSION}/ec-linux-amd64.tar.gz" | tar -xaz
sudo mv bin/ec-linux-amd64 /usr/bin/eclint
sudo rm -rf bin
sudo chmod +x /usr/bin/eclint
make eclint
env:
ECLINT_VERSION: 2.3.1

43
.github/workflows/scheduled_builds.yml vendored Normal file
View File

@ -0,0 +1,43 @@
name: "Build Stable on Schedule"
on:
schedule:
- cron: "0 0 * * 5"
jobs:
publish:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
with:
ref: stable
submodules: recursive
- name: Prepare
id: prep
run: |
TAGS="docker.io/mailserver/docker-mailserver:stable"
echo ::set-output name=tags::${TAGS}
- name: Set up QEMU
uses: docker/setup-qemu-action@v1
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
id: buildx
- name: Login to DockerHub
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Build image locally
uses: docker/build-push-action@v2
with:
builder: ${{ steps.buildx.outputs.name }}
context: .
file: ./Dockerfile
build-args: |
VCS_REF=${{ github.sha }}
VCS_VER=${{ github.ref }}
platforms: linux/amd64,linux/arm/v7,linux/arm64
pull: true
push: true
tags: ${{ steps.prep.outputs.tags }}

View File

@ -0,0 +1,59 @@
name: "Test Merge Requests"
on:
pull_request:
branches: [ "*" ]
jobs:
build:
runs-on: ubuntu-latest
outputs:
imagetag: ${{ steps.prep.outputs.imagetag }}
steps:
- name: Checkout
uses: actions/checkout@v2
with:
submodules: recursive
- name: Prepare
id: prep
run: |
DOCKER_IMAGE=docker.io/mailserver/testing
TAGS="${DOCKER_IMAGE}:${GITHUB_SHA::8},${DOCKER_IMAGE}:latest"
echo ::set-output name=tags::${TAGS}
- name: Set up QEMU
uses: docker/setup-qemu-action@v1
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
id: buildx
- name: Login to DockerHub
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Build image locally
uses: docker/build-push-action@v2
with:
builder: ${{ steps.buildx.outputs.name }}
context: .
file: ./Dockerfile
build-args: |
VCS_REF=${{ github.sha }}
VCS_VER=${{ github.ref }}
platforms: linux/amd64
pull: true
push: true
tags: ${{ steps.prep.outputs.tags }}
test:
needs: build
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
with:
submodules: recursive
- name: run test suite
run: |
NAME=docker.io/mailserver/testing:${GITHUB_SHA::8} bash -c 'make generate-accounts tests'
env:
CI: true

View File

@ -1,55 +0,0 @@
branches:
except:
- donttestme
language: bash
sudo: required
env:
global:
- HADOLINT_VERSION=1.18.0
- SHELLCHECK_VERSION=0.7.1
- ECLINT_VERSION=2.1.0
addons:
apt:
packages:
- xz-utils
services:
- docker
before_install:
# HADOLINT
- sudo curl -L https://github.com/hadolint/hadolint/releases/download/v${HADOLINT_VERSION}/hadolint-$(uname -s)-$(uname -m) -o /usr/local/bin/hadolint
- sudo chmod +rx /usr/local/bin/hadolint
# SHELLCHECK
- sudo wget -qO- "https://github.com/koalaman/shellcheck/releases/download/v${SHELLCHECK_VERSION}/shellcheck-v${SHELLCHECK_VERSION}.linux.x86_64.tar.xz" | tar -xJ
- sudo mv "shellcheck-v${SHELLCHECK_VERSION}/shellcheck" /usr/bin/
# ECLINT
- sudo wget -qO- "https://github.com/editorconfig-checker/editorconfig-checker/releases/download/${ECLINT_VERSION}/ec-linux-amd64.tar.gz" | tar -xaz
- sudo mv bin/ec-linux-amd64 /usr/bin/eclint
- sudo chmod +x /usr/bin/eclint
install:
- travis_retry travis_wait make build
script:
- make eclint
- make hadolint
- make shellcheck
- make generate-accounts tests
after_script:
- make clean
notifications:
slack:
secure: TTo1z9nbZCWcIdfPwypubNa3y+pwvfgDGlzEVAGEuK7uuIpmEoAcAUNSSPTnbewDGHnDl8t/ml93MtvP+a+IVuAKytMqF39PHyoZO7aUl9J62V+G75OmnyGjXGJm40pQosCS6LzqoRRYXotl9+fwH568Kf4ifXCrMZX1d+ir7Ww=
webhooks:
on_success: always
on_failure: always
on_start: never
urls:
- https://webhooks.gitter.im/e/7ec65291bfb4bf1f8518

View File

@ -1,169 +1,60 @@
# Changelog # Changelog
## Next Major Release
- migrated the whole repository to `docker-mailserver/docker-mailserver`
- switched from TravisCI to GitHub Actions for CI/CD
- integrated stale issues action to automatically close stale issues
- adjusted issue templates
- adjusted `README.md` and split off `ENVIRONMENT.md`
- completely refactored `Dockerfile`
- adjusted `Makefile`
## v7.2.0
- Refactored `target/bin/`
- Enhanced and refactored all tests
- Added Code of Conduct
- Redesigned environment variable use
- Added missing Dovecot descriptions
## v7.1.0
- The use of default variables has changed slightly. Consult the [environment variables](./ENVIRONMENT.md) page
- New contributing guidelines were added
- Added coherent coding style and linting
- Added option to use non-default network interface
- SELinux is now supported
## 6.2.0+ ## 6.2.0+
* see <https://github.com/tomav/docker-mailserver/releases> - see <https://github.com/docker-mailserver/docker-mailserver/releases>
## 6.1.0 ## 6.1.0
* Deliver root mail (#952) - Deliver root mail (#952)
* don't update permissions on non-existent file (#956) - don't update permissions on non-existent file (#956)
* Update docker-configomat (#959) - Update docker-configomat (#959)
* Support for detecting running container mount (#884) - Support for detecting running container mount (#884)
* Report sender (#965) - Report sender (#965)
added REPORT_SENDER env variable to the container. added REPORT_SENDER env variable to the container.
* Add saslauthd option for ldap_start_tls & ldap_tls_check_peer - (#979, #980) - Add saslauthd option for ldap_start_tls & ldap_tls_check_peer - (#979, #980)
* fix SASL domain (#892, #970) - fix SASL domain (#892, #970)
* DOMAINNAME can fail to be set in postsrsd-wrapper.sh (#989) - DOMAINNAME can fail to be set in postsrsd-wrapper.sh (#989)
## 6.0.0 ## 6.0.0
* Implementation of multi-domain relay hosts (#922, #926) - Implementation of multi-domain relay hosts (#922, #926)
AWS_SES_HOST and AWS_SES_PORT are deprecated now. AWS_SES_HOST and AWS_SES_PORT are deprecated now.
RELAY_HOST and RELAY_PORT are introduced to replace them. RELAY_HOST and RELAY_PORT are introduced to replace them.
* Password creation fix (#908, #914) - Password creation fix (#908, #914)
* Fixes 'duplicate log entry for /var/log/mail/mail.log' (#925, #927) - Fixes 'duplicate log entry for /var/log/mail/mail.log' (#925, #927)
* fixed cleanup (mail_with_relays didn't get cleaned up) (#930) - fixed cleanup (mail_with_relays didn't get cleaned up) (#930)
* fix line breaks in postfix-summary mail error case (#936) - fix line breaks in postfix-summary mail error case (#936)
* Set default virus delete time (#932, #935) - Set default virus delete time (#932, #935)
This defaults to 7 days This defaults to 7 days
* Ensure that the account contains a @ (#923, #924) - Ensure that the account contains a @ (#923, #924)
* Introducing global filters. (#934) - Introducing global filters. (#934)
* add missing env vars to docker-compose.yml (#937) - add missing env vars to docker-compose.yml (#937)
* set postmaster address to a sensible default (#938, #939, #940) - set postmaster address to a sensible default (#938, #939, #940)
* Testfixes & more (#942) - Testfixes & more (#942)
## 5.8.1
* add headers to postfix summary mail (#919)
* quotes needed to run multi-word command inside
container (#921)
* Fix uncommented lines in .env file (#920)
* Tls level fix (#916)
* test/config backup & restore (#907)
* Restore userdb for tests (#913)
## 5.8.0
* Adding daily mail review from Issue 839 (#881)
You can enable REPORT_RECIPIENT for REPORT_INTERVAL
reports. Default is disabled.
* introducing ENABLE_SRS env variable (#906, #852)
In v3.2.0 was SRS introduced and enabled by default
Now it is disabled by default and can be enabled with
the new env variable.
* fixed delalias, added additional tests (#909)
Fixes to setup where made for deletion and addition.
## 5.7.0
* Delmailuser (#878)
You can now delete users and the mailbox
* Backup config folder while testing (#901)
* added error messages to letsencrypt on startup (#898)
## 5.6.1
* Update docker-configomat (#680)
## 5.6.0
* Generate SRS secret on first run and store it (#891)
The secret will be constant afther this.
## 5.5.0
* Add /var/lib/dovecot to mailstate persistence (#887)
## 5.4.0
* Allow configuring SRS secrets using the environment (#885)
You can set your own secret with the env SRS_SECRET
By default it uses the docker generated secret
* Removed unneeded check for Let's encrypt cert.pem (#843)
## 5.3.0
* Added reject_authenticated_sender_login_mismatch (#872)
You can enable it with the env SPOOF_PROTECTION
It is not enabled by default
## 5.2.0
* Setting quiet mode on invoke-rc.d (#792)
* Implement undef option for SA_SPAM_SUBJECT (#767)
## 5.1.0
* Dkim key size can be changed (#868)
It defaults to 2048 bits
## 5.0.1
* update postmaster_address in dovecot config according to
POSTMASTER_ADDRESS env var (#866)
## 5.0.0
* Use Nist tls recommendations (#831)
This might break access with older email clients that use
an older version of openssl. You can TLS_LEVEL to lower
the ciphers.
## 4.2.0
* Add environment variable to allow for customizing postsrsd's SRS_EXCLUDE_DOMAINS setting (#849, #842)
## 4.1.0
* fixed greedy postgrey sed command (#845)
* postscreen implementation altered (#846)
You can now apply sender and receives restrictions
## 4.0.0
* moved fail2ban function from setup.sh to own file (#837)
This might break automatic scripting and you need to use
fail2ban now
## 3.4.0
* Generate new DH param weekly instead of daily (#834, #836)
## 3.3.1
* added config-path option to setup.sh script (#698)
## 3.3.0
* Restrict access (#452, #816)
## 3.2.3
* Introduce .env for docker-compose examples (#815)
## 3.2.2
* Changed Junk folder to be created and subscribed by default (#806)
## 3.2.1 (2018-02-06)
* Added reject_sender_login_mismatch (#811)
## 3.2.0 (2018-02-06)
* Add SRS to fix SPF issues on redirect (#611, #814)
## 3.1.0 (2018-02-04)
* Introduced Postscreen
Breaks email submission on port 25. Sending emails should be done on port 465 or 587
## 3.0.0 (2018-02-04)
* Image rebased on Debian stable
## 2.0.0 (2016-05-09)
* New version
* Major redesign of configuration

View File

@ -1,4 +1,3 @@
# Contributor Covenant Code of Conduct # Contributor Covenant Code of Conduct
## Our Pledge ## Our Pledge

View File

@ -1,6 +1,6 @@
# Contributing # Contributing
`docker-mailserver` is OpenSource. That means that you can contribute on enhancements, bug fixing or improving the documentation in the Wiki. This project is Open Source. That means that you can contribute on enhancements, bug fixing or improving the documentation in the [Wiki](https://github.com/docker-mailserver/docker-mailserver/wiki).
1. [Issues & PRs](#issues--prs) 1. [Issues & PRs](#issues--prs)
1. [Opening an Issue](#opening-an-issue) 1. [Opening an Issue](#opening-an-issue)
@ -23,20 +23,18 @@ You want to add a feature? Feel free to start creating an issue explaining what
The development workflow is the following: The development workflow is the following:
- Fork the project and clone your fork 1. Fork the project and clone your fork
- Create a branch using `git checkout -b branch_name` (you can use `issue-xxx` if fixing an existing issue) 1. Create a new branch to work on
- Run `git submodule init` and `git submodule update` to get the BATS submodules 2. Run `git submodule update --init --recursive`
- Code :-) 2. Write the code that is needed :D
- Add integration tests in `test/tests.bats` 3. Add integration tests if necessary
- Use `make clean all` to build image locally and run tests 4. Get the linters with `make install_linters`
Note that tests work on Linux only; they hang on Mac and Windows. 5. Use `make clean all` to build image locally and run tests (note that tests work on Linux **only**)
- Document your improvements in `README.md` or Wiki depending on content 6. Document your improvements if necessary (e.g. if you introduced new environment variables, write the description in [`ENVIRONMENT.md`](./ENVIRONMENT.md))
- [Commit][commit], if possible with [signing your commit with a GPG key][gpg], push and make a pull-request 7. [Commit][commit] and [sign your commit][gpg], push and create a pull-request to merge into `master`
- Pull-request is automatically tested on Travis 1. Pull requests are automatically tested against the CI and will be reviewed when tests pass
- When tests are green, a review may be done 2. When your changes are validated, your branch is merged
- When changed are validated, your branch is merged into `master` 3. CI builds the new `:latest` image
- `master` is automatically tested on Travis
- Docker builds a new `latest` image
## Coding Style ## Coding Style

View File

@ -1,104 +1,136 @@
FROM debian:buster-slim FROM docker.io/debian:buster-slim
ARG VCS_VER
ARG VCS_REF ARG VCS_REF
ARG VCS_VERSION
LABEL maintainer="Thomas VIAL" \
org.label-schema.name="docker-mailserver" \
org.label-schema.description="A fullstack but simple mailserver (smtp, imap, antispam, antivirus, ssl...)" \
org.label-schema.url="https://github.com/tomav/docker-mailserver" \
org.label-schema.vcs-ref=$VCS_REF \
org.label-schema.vcs-url="https://github.com/tomav/docker-mailserver" \
org.label-schema.version=$VCS_VERSION \
org.label-schema.schema-version="1.0"
ARG DEBIAN_FRONTEND=noninteractive ARG DEBIAN_FRONTEND=noninteractive
ENV VIRUSMAILS_DELETE_DELAY=7
ENV ONE_DIR=0 LABEL org.opencontainers.image.version=${VCS_VER}
LABEL org.opencontainers.image.revision=${VCS_REF}
LABEL org.opencontainers.image.title="docker-mailserver"
LABEL org.opencontainers.image.vendor="The Docker Mailserver Organization"
LABEL org.opencontainers.image.authors="The Docker Mailserver Organization on GitHub"
LABEL org.opencontainers.image.licenses="MIT"
LABEL org.opencontainers.image.description="A fullstack but simple mail server (SMTP, IMAP, LDAP, Antispam, Antivirus, etc.). Only configuration files, no SQL database."
LABEL org.opencontainers.image.url="https://github.com/docker-mailserver"
LABEL org.opencontainers.image.documentation="https://github.com/docker-mailserver/docker-mailserver/blob/master/README.md"
LABEL org.opencontainers.image.source="https://github.com/docker-mailserver/docker-mailserver"
ENV ENABLE_POSTGREY=0 ENV ENABLE_POSTGREY=0
ENV FETCHMAIL_POLL=300 ENV FETCHMAIL_POLL=300
ENV ONE_DIR=0
ENV POSTGREY_AUTO_WHITELIST_CLIENTS=5
ENV POSTGREY_DELAY=300 ENV POSTGREY_DELAY=300
ENV POSTGREY_MAX_AGE=35 ENV POSTGREY_MAX_AGE=35
ENV POSTGREY_AUTO_WHITELIST_CLIENTS=5 ENV POSTGREY_TEXT="Delayed by Postgrey"
ENV POSTGREY_TEXT="Delayed by postgrey"
ENV SASLAUTHD_MECHANISMS=pam ENV SASLAUTHD_MECHANISMS=pam
ENV SASLAUTHD_MECH_OPTIONS="" ENV SASLAUTHD_MECH_OPTIONS=""
ENV VIRUSMAILS_DELETE_DELAY=7
SHELL ["/bin/bash", "-o", "pipefail", "-c"] SHELL ["/bin/bash", "-o", "pipefail", "-c"]
# Packages #
# hadolint ignore=DL3015,DL3005 # Install Basic Software
#
RUN \ RUN \
apt-get update -q --fix-missing && \ apt-get -qq --fix-missing update && \
apt-get -y upgrade && \ apt-get -y dist-upgrade >/dev/null && \
apt-get -y install postfix && \ apt-get -y install apt-utils &>/dev/null && \
apt-get -y install --no-install-recommends \ apt-get -y install postfix >/dev/null && \
altermime \ apt-get -y --no-install-recommends install \
amavisd-new \ # A - E
apt-transport-https \ altermime amavisd-new apt-transport-https arj binutils bzip2 \
arj \ dovecot-core dovecot-imapd dovecot-ldap dovecot-lmtpd \
binutils \ dovecot-managesieved dovecot-pop3d dovecot-sieve dovecot-solr \
bzip2 \ ca-certificates cabextract clamav clamav-daemon cpio curl ed \
ca-certificates \ # F - O
cabextract \ fail2ban fetchmail file gamin gnupg gzip iproute2 iptables \
clamav \ locales logwatch lhasa libdate-manip-perl liblz4-tool \
clamav-daemon \ libmail-spf-perl libnet-dns-perl libsasl2-modules lrzip lzop \
cpio \ netcat-openbsd nomarch opendkim opendkim-tools opendmarc \
curl \ # P - Z
ed \ pax pflogsumm postgrey p7zip-full postfix-ldap postfix-pcre \
fail2ban \ postfix-policyd-spf-python postsrsd pyzor \
fetchmail \ razor rpm2cpio rsyslog sasl2-bin spamassassin supervisor \
file \ unrar-free unzip whois xz-utils >/dev/null && \
gamin \ # cleanup
gzip \ apt-get -qq autoclean && \
gnupg \ apt-get -qq clean && \
iproute2 \
iptables \
locales \
logwatch \
lhasa \
libdate-manip-perl \
liblz4-tool \
libmail-spf-perl \
libnet-dns-perl \
libsasl2-modules \
lrzip \
lzop \
netcat-openbsd \
nomarch \
opendkim \
opendkim-tools \
opendmarc \
pax \
pflogsumm \
p7zip-full \
postfix-ldap \
postfix-pcre \
postfix-policyd-spf-python \
postsrsd \
pyzor \
razor \
rpm2cpio \
rsyslog \
sasl2-bin \
spamassassin \
supervisor \
postgrey \
unrar-free \
unzip \
whois \
xz-utils \
dovecot-core \
dovecot-imapd \
dovecot-ldap \
dovecot-lmtpd \
dovecot-managesieved \
dovecot-pop3d \
dovecot-sieve \
dovecot-solr \
&& \
apt-get autoclean && \
rm -rf /var/lib/apt/lists/* && \ rm -rf /var/lib/apt/lists/* && \
c_rehash 2>/dev/null
#
# ClamAV & FeshClam
#
RUN \
echo '0 */6 * * * clamav /usr/bin/freshclam --quiet' > /etc/cron.d/clamav-freshclam && \
chmod 644 /etc/clamav/freshclam.conf && \
freshclam && \
sed -i 's/Foreground false/Foreground true/g' /etc/clamav/clamd.conf && \
mkdir /var/run/clamav && \
chown -R clamav:root /var/run/clamav && \
rm -rf /var/log/clamav/
#
# Dovecot
#
COPY target/dovecot/auth-passwdfile.inc target/dovecot/??-*.conf /etc/dovecot/conf.d/
COPY target/dovecot/sieve/ /etc/dovecot/sieve/
COPY target/dovecot/dovecot-purge.cron /etc/cron.d/dovecot-purge.disabled
RUN chmod 0 /etc/cron.d/dovecot-purge.disabled
WORKDIR /usr/share/dovecot
# hadolint ignore=SC2016,SC2086,SC2069
RUN \
sed -i -e 's/include_try \/usr\/share\/dovecot\/protocols\.d/include_try \/etc\/dovecot\/protocols\.d/g' /etc/dovecot/dovecot.conf && \
sed -i -e 's/#mail_plugins = \$mail_plugins/mail_plugins = \$mail_plugins sieve/g' /etc/dovecot/conf.d/15-lda.conf && \
sed -i -e 's/^.*lda_mailbox_autocreate.*/lda_mailbox_autocreate = yes/g' /etc/dovecot/conf.d/15-lda.conf && \
sed -i -e 's/^.*lda_mailbox_autosubscribe.*/lda_mailbox_autosubscribe = yes/g' /etc/dovecot/conf.d/15-lda.conf && \
sed -i -e 's/^.*postmaster_address.*/postmaster_address = '${POSTMASTER_ADDRESS:="postmaster@domain.com"}'/g' /etc/dovecot/conf.d/15-lda.conf && \
sed -i 's/#imap_idle_notify_interval = 2 mins/imap_idle_notify_interval = 29 mins/' /etc/dovecot/conf.d/20-imap.conf && \
# adapt mkcert for Dovecot community repo
sed -i 's/CERTDIR=.*/CERTDIR=\/etc\/dovecot\/ssl/g' /usr/share/dovecot/mkcert.sh && \
sed -i 's/KEYDIR=.*/KEYDIR=\/etc\/dovecot\/ssl/g' /usr/share/dovecot/mkcert.sh && \
sed -i 's/KEYFILE=.*/KEYFILE=\$KEYDIR\/dovecot.key/g' /usr/share/dovecot/mkcert.sh && \
sed -i 's/RANDFILE.*//g' /usr/share/dovecot/dovecot-openssl.cnf && \
# create directory for certificates required by mkcert
mkdir /etc/dovecot/ssl && \
chmod 755 /etc/dovecot/ssl && \
./mkcert.sh 2>&1 >/dev/null && \
mkdir -p /usr/lib/dovecot/sieve-pipe /usr/lib/dovecot/sieve-filter /usr/lib/dovecot/sieve-global && \
chmod 755 -R /usr/lib/dovecot/sieve-pipe /usr/lib/dovecot/sieve-filter /usr/lib/dovecot/sieve-global
#
# LDAP & Spamassassin's Cron
#
COPY target/dovecot/dovecot-ldap.conf.ext /etc/dovecot
COPY \
target/postfix/ldap-users.cf \
target/postfix/ldap-groups.cf \
target/postfix/ldap-aliases.cf \
target/postfix/ldap-domains.cf \
/etc/postfix/
# hadolint ignore=SC2016
RUN \
sed -i -r 's/^(CRON)=0/\1=1/g' /etc/default/spamassassin && \
sed -i -r 's/^\$INIT restart/supervisorctl restart amavis/g' /etc/spamassassin/sa-update-hooks.d/amavisd-new
#
# Scripts & Miscellaneous
#
COPY \
./target/bin/* \
./target/scripts/*.sh \
./target/docker-configomat/configomat.sh \
/usr/local/bin/
RUN \
chmod +x /usr/local/bin/* && \
rm -rf /usr/share/locale/* && \ rm -rf /usr/share/locale/* && \
rm -rf /usr/share/man/* && \ rm -rf /usr/share/man/* && \
rm -rf /usr/share/doc/* && \ rm -rf /usr/share/doc/* && \
@ -107,102 +139,76 @@ RUN \
rm /etc/postsrsd.secret && \ rm /etc/postsrsd.secret && \
rm /etc/cron.daily/00logwatch rm /etc/cron.daily/00logwatch
RUN echo "0 */6 * * * clamav /usr/bin/freshclam --quiet" > /etc/cron.d/clamav-freshclam && \ #
chmod 644 /etc/clamav/freshclam.conf && \ # PostSRSD, Postgrey & Amavis
freshclam && \ #
sed -i 's/Foreground false/Foreground true/g' /etc/clamav/clamd.conf && \
mkdir /var/run/clamav && \
chown -R clamav:root /var/run/clamav && \
rm -rf /var/log/clamav/
# Configures Dovecot COPY target/postsrsd/postsrsd /etc/default/postsrsd
COPY target/dovecot/auth-passwdfile.inc target/dovecot/??-*.conf /etc/dovecot/conf.d/
COPY target/dovecot/scripts/quota-warning.sh /usr/local/bin/quota-warning.sh
COPY target/dovecot/sieve/ /etc/dovecot/sieve/
COPY target/dovecot/dovecot-purge.cron /etc/cron.d/dovecot-purge.disabled
RUN chmod 0 /etc/cron.d/dovecot-purge.disabled
WORKDIR /usr/share/dovecot
# hadolint ignore=SC2016,SC2086
RUN sed -i -e 's/include_try \/usr\/share\/dovecot\/protocols\.d/include_try \/etc\/dovecot\/protocols\.d/g' /etc/dovecot/dovecot.conf && \
sed -i -e 's/#mail_plugins = \$mail_plugins/mail_plugins = \$mail_plugins sieve/g' /etc/dovecot/conf.d/15-lda.conf && \
sed -i -e 's/^.*lda_mailbox_autocreate.*/lda_mailbox_autocreate = yes/g' /etc/dovecot/conf.d/15-lda.conf && \
sed -i -e 's/^.*lda_mailbox_autosubscribe.*/lda_mailbox_autosubscribe = yes/g' /etc/dovecot/conf.d/15-lda.conf && \
sed -i -e 's/^.*postmaster_address.*/postmaster_address = '${POSTMASTER_ADDRESS:="postmaster@domain.com"}'/g' /etc/dovecot/conf.d/15-lda.conf && \
sed -i 's/#imap_idle_notify_interval = 2 mins/imap_idle_notify_interval = 29 mins/' /etc/dovecot/conf.d/20-imap.conf && \
# Adapt mkcert for Dovecot community repo
sed -i 's/CERTDIR=.*/CERTDIR=\/etc\/dovecot\/ssl/g' /usr/share/dovecot/mkcert.sh && \
sed -i 's/KEYDIR=.*/KEYDIR=\/etc\/dovecot\/ssl/g' /usr/share/dovecot/mkcert.sh && \
sed -i 's/KEYFILE=.*/KEYFILE=\$KEYDIR\/dovecot.key/g' /usr/share/dovecot/mkcert.sh && \
# create directory for certificates created by mkcert
mkdir /etc/dovecot/ssl && \
chmod 755 /etc/dovecot/ssl && \
./mkcert.sh && \
mkdir -p /usr/lib/dovecot/sieve-pipe /usr/lib/dovecot/sieve-filter /usr/lib/dovecot/sieve-global && \
chmod 755 -R /usr/lib/dovecot/sieve-pipe /usr/lib/dovecot/sieve-filter /usr/lib/dovecot/sieve-global
# Configures LDAP
COPY target/dovecot/dovecot-ldap.conf.ext /etc/dovecot
COPY target/postfix/ldap-users.cf target/postfix/ldap-groups.cf target/postfix/ldap-aliases.cf target/postfix/ldap-domains.cf /etc/postfix/
# Enables Spamassassin CRON updates and update hook for supervisor
# hadolint ignore=SC2016
RUN sed -i -r 's/^(CRON)=0/\1=1/g' /etc/default/spamassassin && \
sed -i -r 's/^\$INIT restart/supervisorctl restart amavis/g' /etc/spamassassin/sa-update-hooks.d/amavisd-new
# Enables Postgrey
COPY target/postgrey/postgrey /etc/default/postgrey COPY target/postgrey/postgrey /etc/default/postgrey
COPY target/postgrey/postgrey.init /etc/init.d/postgrey COPY target/postgrey/postgrey.init /etc/init.d/postgrey
RUN chmod 755 /etc/init.d/postgrey && \ RUN \
chmod 755 /etc/init.d/postgrey && \
mkdir /var/run/postgrey && \ mkdir /var/run/postgrey && \
chown postgrey:postgrey /var/run/postgrey chown postgrey:postgrey /var/run/postgrey
# Copy PostSRSd Config
COPY target/postsrsd/postsrsd /etc/default/postsrsd
# Copy shared ffdhe params
COPY target/shared/ffdhe4096.pem /etc/postfix/shared/ffdhe4096.pem
# Enables Amavis
COPY target/amavis/conf.d/* /etc/amavis/conf.d/ COPY target/amavis/conf.d/* /etc/amavis/conf.d/
RUN sed -i -r 's/#(@| \\%)bypass/\1bypass/g' /etc/amavis/conf.d/15-content_filter_mode && \ RUN \
adduser clamav amavis && \ sed -i -r 's/#(@| \\%)bypass/\1bypass/g' /etc/amavis/conf.d/15-content_filter_mode && \
adduser amavis clamav && \ adduser clamav amavis >/dev/null && \
adduser amavis clamav >/dev/null && \
# no syslog user in debian compared to ubuntu # no syslog user in debian compared to ubuntu
adduser --system syslog && \ adduser --system syslog >/dev/null && \
useradd -u 5000 -d /home/docker -s /bin/bash -p "$(echo docker | openssl passwd -1 -stdin)" docker && \ useradd -u 5000 -d /home/docker -s /bin/bash -p "$(echo docker | openssl passwd -1 -stdin)" docker >/dev/null && \
echo "0 4 * * * /usr/local/bin/virus-wiper" | crontab - && \ echo "0 4 * * * /usr/local/bin/virus-wiper" | crontab - && \
chmod 644 /etc/amavis/conf.d/* chmod 644 /etc/amavis/conf.d/*
# Configure Fail2ban RUN su - amavis -c "razor-admin -create && razor-admin -register"
#
# Fail2Ban, DKIM & DMARC
#
COPY target/fail2ban/jail.conf /etc/fail2ban/jail.conf COPY target/fail2ban/jail.conf /etc/fail2ban/jail.conf
COPY target/fail2ban/filter.d/postfix-sasl.conf /etc/fail2ban/filter.d/postfix-sasl.conf COPY target/fail2ban/filter.d/postfix-sasl.conf /etc/fail2ban/filter.d/postfix-sasl.conf
RUN mkdir /var/run/fail2ban RUN mkdir /var/run/fail2ban
# Enables Pyzor and Razor
RUN su - amavis -c "razor-admin -create && razor-admin -register"
# Configure DKIM (opendkim)
# DKIM config files
COPY target/opendkim/opendkim.conf /etc/opendkim.conf COPY target/opendkim/opendkim.conf /etc/opendkim.conf
COPY target/opendkim/default-opendkim /etc/default/opendkim COPY target/opendkim/default-opendkim /etc/default/opendkim
# Configure DMARC (opendmarc)
COPY target/opendmarc/opendmarc.conf /etc/opendmarc.conf COPY target/opendmarc/opendmarc.conf /etc/opendmarc.conf
COPY target/opendmarc/default-opendmarc /etc/default/opendmarc COPY target/opendmarc/default-opendmarc /etc/default/opendmarc
COPY target/opendmarc/ignore.hosts /etc/opendmarc/ignore.hosts COPY target/opendmarc/ignore.hosts /etc/opendmarc/ignore.hosts
# Configure fetchmail RUN \
# switch iptables and ip6tables to legacy for fail2ban
update-alternatives --set iptables /usr/sbin/iptables-legacy && \
update-alternatives --set ip6tables /usr/sbin/ip6tables-legacy
#
# Fetchmail, Postfix & Let'sEncrypt
#
COPY target/fetchmail/fetchmailrc /etc/fetchmailrc_general COPY target/fetchmail/fetchmailrc /etc/fetchmailrc_general
RUN sed -i 's/START_DAEMON=no/START_DAEMON=yes/g' /etc/default/fetchmail
RUN mkdir /var/run/fetchmail && chown fetchmail /var/run/fetchmail
# Configures Postfix
COPY target/postfix/main.cf target/postfix/master.cf /etc/postfix/ COPY target/postfix/main.cf target/postfix/master.cf /etc/postfix/
COPY target/postfix/header_checks.pcre target/postfix/sender_header_filter.pcre target/postfix/sender_login_maps.pcre /etc/postfix/maps/ COPY target/shared/ffdhe4096.pem /etc/postfix/shared/ffdhe4096.pem
RUN echo "" > /etc/aliases COPY \
target/postfix/header_checks.pcre \
target/postfix/sender_header_filter.pcre \
target/postfix/sender_login_maps.pcre \
/etc/postfix/maps/
# Configuring Logs RUN \
RUN sed -i -r "/^#?compress/c\compress\ncopytruncate" /etc/logrotate.conf && \ : >/etc/aliases && \
sed -i 's/START_DAEMON=no/START_DAEMON=yes/g' /etc/default/fetchmail && \
mkdir /var/run/fetchmail && chown fetchmail /var/run/fetchmail && \
curl -s https://letsencrypt.org/certs/lets-encrypt-x3-cross-signed.pem >/etc/ssl/certs/lets-encrypt-x3-cross-signed.pem
#
# Logs
#
RUN \
sed -i -r "/^#?compress/c\compress\ncopytruncate" /etc/logrotate.conf && \
mkdir -p /var/log/mail && \ mkdir -p /var/log/mail && \
chown syslog:root /var/log/mail && \ chown syslog:root /var/log/mail && \
touch /var/log/mail/clamav.log && \ touch /var/log/mail/clamav.log && \
@ -222,31 +228,20 @@ RUN sed -i -r "/^#?compress/c\compress\ncopytruncate" /etc/logrotate.conf && \
# prevent syslog logrotate warnings \ # prevent syslog logrotate warnings \
sed -i -e 's/\(printerror "could not determine current runlevel"\)/#\1/' /usr/sbin/invoke-rc.d && \ sed -i -e 's/\(printerror "could not determine current runlevel"\)/#\1/' /usr/sbin/invoke-rc.d && \
sed -i -e 's/^\(POLICYHELPER=\).*/\1/' /usr/sbin/invoke-rc.d && \ sed -i -e 's/^\(POLICYHELPER=\).*/\1/' /usr/sbin/invoke-rc.d && \
# Prevent syslog warning about imklog permissions. # prevent syslog warning about imklog permissions
# We won't want to look at that inside a container anyway.
sed -i -e 's/^module(load=\"imklog\")/#module(load=\"imklog\")/' /etc/rsyslog.conf && \ sed -i -e 's/^module(load=\"imklog\")/#module(load=\"imklog\")/' /etc/rsyslog.conf && \
# prevent email when /sbin/init or init system is not existing \ # prevent email when /sbin/init or init system is not existing \
sed -i -e 's|invoke-rc.d rsyslog rotate > /dev/null|/usr/bin/supervisorctl signal hup rsyslog >/dev/null|g' /usr/lib/rsyslog/rsyslog-rotate sed -i -e 's|invoke-rc.d rsyslog rotate > /dev/null|/usr/bin/supervisorctl signal hup rsyslog >/dev/null|g' /usr/lib/rsyslog/rsyslog-rotate
# Get LetsEncrypt signed certificate #
RUN curl -s https://letsencrypt.org/certs/lets-encrypt-x3-cross-signed.pem > /etc/ssl/certs/lets-encrypt-x3-cross-signed.pem # Supervisord & Start
#
COPY ./target/bin /usr/local/bin
# Start-mailserver script
COPY ./target/bin-helper.sh ./target/helper-functions.sh ./target/check-for-changes.sh ./target/start-mailserver.sh ./target/fail2ban-wrapper.sh ./target/postfix-wrapper.sh ./target/postsrsd-wrapper.sh ./target/docker-configomat/configomat.sh /usr/local/bin/
RUN chmod +x /usr/local/bin/*
# Configure supervisor
COPY target/supervisor/supervisord.conf /etc/supervisor/supervisord.conf COPY target/supervisor/supervisord.conf /etc/supervisor/supervisord.conf
COPY target/supervisor/conf.d/* /etc/supervisor/conf.d/ COPY target/supervisor/conf.d/* /etc/supervisor/conf.d/
WORKDIR / WORKDIR /
# Switch iptables and ip6tables to legacy for fail2ban
RUN update-alternatives --set iptables /usr/sbin/iptables-legacy \
&& update-alternatives --set ip6tables /usr/sbin/ip6tables-legacy
EXPOSE 25 587 143 465 993 110 995 4190 EXPOSE 25 587 143 465 993 110 995 4190
CMD ["supervisord", "-c", "/etc/supervisor/supervisord.conf"] CMD ["supervisord", "-c", "/etc/supervisor/supervisord.conf"]

656
ENVIRONMENT.md Normal file
View File

@ -0,0 +1,656 @@
# Environment
## Variables
1. If an option doesn't work as documented here, check if you are running the latest image!
2. Values in **bold** are the default values.
3. Since `docker-mailserver v7.1.0`, comparisons for environment variables are executed differently. If you previously used `VARIABLE=''` as the `empty` value, **update** to now use `VARIABLE=`.
### Assignments
#### General
##### DMS_DEBUG
- **0** => Debug disabled
- 1 => Enables debug on startup
##### ENABLE_CLAMAV
- **0** => Clamav is disabled
- 1 => Clamav is enabled
##### ONE_DIR
- **0** => state in default directories
- 1 => consolidate all states into a single directory (`/var/mail-state`) to allow persistence using docker volumes
##### ENABLE_POP3
- **empty** => POP3 service disabled
- 1 => Enables POP3 service
##### ENABLE_FAIL2BAN
- **0** => fail2ban service disabled
- 1 => Enables fail2ban service
If you enable Fail2Ban, don't forget to add the following lines to your `docker-compose.yml`:
``` BASH
cap_add:
- NET_ADMIN
```
Otherwise, `iptables` won't be able to ban IPs.
##### SMTP_ONLY
- **empty** => all daemons start
- 1 => only launch postfix smtp
##### SSL_TYPE
- **empty** => SSL disabled
- letsencrypt => Enables Let's Encrypt certificates
- custom => Enables custom certificates
- manual => Let you manually specify locations of your SSL certificates for non-standard cases
- self-signed => Enables self-signed certificates
- _any other value_ => SSL required, settings by default
Please read [the SSL page in the wiki](https://github.com/tomav/docker-mailserver/wiki/Configure-SSL) for more information.
##### TLS_LEVEL
- **empty** => modern
- modern => Enables TLSv1.2 and modern ciphers only. (default)
- intermediate => Enables TLSv1, TLSv1.1 and TLSv1.2 and broad compatibility ciphers.
- old => NOT implemented. If you really need it, then customize the TLS ciphers overriding postfix and dovecot settings [wiki](https://github.com/tomav/docker-mailserver/wiki/)
##### SPOOF_PROTECTION
Configures the handling of creating mails with forged sender addresses.
- **empty** => Mail address spoofing allowed. Any logged in user may create email messages with a forged sender address. See also [Wikipedia](https://en.wikipedia.org/wiki/Email_spoofing)(not recommended, but default for backwards compatibility reasons)
- 1 => (recommended) Mail spoofing denied. Each user may only send with his own or his alias addresses. Addresses with [extension delimiters](http://www.postfix.org/postconf.5.html#recipient_delimiter) are not able to send messages.
##### ENABLE_SRS
Enables the Sender Rewriting Scheme. SRS is needed if your mail server acts as forwarder. See [postsrsd](https://github.com/roehling/postsrsd/blob/master/README.md#sender-rewriting-scheme-crash-course) for further explanation.
- **0** => Disabled
- 1 => Enabled
##### PERMIT_DOCKER
Set different options for mynetworks option (can be overwrite in postfix-main.cf) **WARNING**: Adding the docker network's gateway to the list of trusted hosts, e.g. using the `network` or `connected-networks` option, can create an [**open relay**](https://en.wikipedia.org/wiki/Open_mail_relay), for instance if IPv6 is enabled on the host machine but not in Docker.
- **empty** => localhost only
- host => Add docker host (ipv4 only)
- network => Add the docker default bridge network (172.16.0.0/12); **WARNING**: `docker-compose` might use others (e.g. 192.168.0.0/16) use `PERMIT_DOCKER=connected-networks` in this case
- connected-networks => Add all connected docker networks (ipv4 only)
Note: you probably want to [set `POSTFIX_INET_PROTOCOLS=ipv4`](#postfix_inet_protocols) to make it work fine with Docker.
##### NETWORK_INTERFACE
In case your network interface differs from `eth0`, e.g. when you are using HostNetworking in Kubernetes, you can set this to whatever interface you want. This interface will then be used.
- **empty** => `eth0`
##### VIRUSMAILS_DELETE_DELAY
Set how many days a virusmail will stay on the server before being deleted
- **empty** => 7 days
##### ENABLE_POSTFIX_VIRTUAL_TRANSPORT
This Option is activating the Usage of POSTFIX_DAGENT to specify a ltmp client different from default dovecot socket.
- **empty** => disabled
- 1 => enabled
##### POSTFIX_DAGENT
Enabled by ENABLE_POSTFIX_VIRTUAL_TRANSPORT. Specify the final delivery of postfix
- **empty**: fail
- `lmtp:unix:private/dovecot-lmtp` (use socket)
- `lmtps:inet:<host>:<port>` (secure lmtp with starttls, take a look at <https://sys4.de/en/blog/2014/11/17/sicheres-lmtp-mit-starttls-in-dovecot/>)
- `lmtp:<kopano-host>:2003` (use kopano as mailstore)
- etc.
##### POSTFIX\_MAILBOX\_SIZE\_LIMIT
Set the mailbox size limit for all users. If set to zero, the size will be unlimited (default).
- **empty** => 0 (no limit)
##### ENABLE_QUOTAS
- **1** => Dovecot quota is enabled
- 0 => Dovecot quota is disabled
See [mailbox quota](https://github.com/tomav/docker-mailserver/wiki/Configure-Accounts#mailbox-quota).
##### POSTFIX\_MESSAGE\_SIZE\_LIMIT
Set the message size limit for all users. If set to zero, the size will be unlimited (not recommended!)
- **empty** => 10240000 (~10 MB)
##### ENABLE_MANAGESIEVE
- **empty** => Managesieve service disabled
- 1 => Enables Managesieve on port 4190
##### OVERRIDE_HOSTNAME
- **empty** => uses the `hostname` command to get the mail server's canonical hostname
- => Specify a fully-qualified domainname to serve mail for. This is used for many of the config features so if you can't set your hostname (e.g. you're in a container platform that doesn't let you) specify it in this environment variable.
##### POSTMASTER_ADDRESS
- **empty** => postmaster@domain.com
- => Specify the postmaster address
##### POSTSCREEN_ACTION
- **enforce** => Allow other tests to complete. Reject attempts to deliver mail with a 550 SMTP reply, and log the helo/sender/recipient information. Repeat this test the next time the client connects.
- drop => Drop the connection immediately with a 521 SMTP reply. Repeat this test the next time the client connects.
- ignore => Ignore the failure of this test. Allow other tests to complete. Repeat this test the next time the client connects. This option is useful for testing and collecting statistics without blocking mail.
##### DOVECOT_MAILBOX_FORMAT
- **maildir** => uses very common Maildir format, one file contains one message
- sdbox => (experimental) uses Dovecot high-performance mailbox format, one file contains one message
- mdbox ==> (experimental) uses Dovecot high-performance mailbox format, multiple messages per file and multiple files per box
This option has been added in November 2019. Using other format than Maildir is considered as experimental in docker-mailserver and should only be used for testing purpose. For more details, please refer to [Dovecot Documentation](https://wiki2.dovecot.org/MailboxFormat).
##### POSTFIX_INET_PROTOCOLS
- **all** => All possible protocols.
- ipv4 => Use only IPv4 traffic. Most likely you want this behind Docker.
- ipv6 => Use only IPv6 traffic.
Note: More details in <http://www.postfix.org/postconf.5.html#inet_protocols>
#### Reports
##### PFLOGSUMM_TRIGGER
Enables regular pflogsumm mail reports.
- **not set** => No report
- daily_cron => Daily report for the previous day
- logrotate => Full report based on the mail log when it is rotated
This is a new option. The old REPORT options are still supported for backwards compatibility.
If this is not set and reports are enabled with the old options, logrotate will be used.
##### PFLOGSUMM_RECIPIENT
Recipient address for pflogsumm reports.
- **not set** => Use REPORT_RECIPIENT or POSTMASTER_ADDRESS
- => Specify the recipient address(es)
##### PFLOGSUMM_SENDER
From address for pflogsumm reports.
- **not set** => Use REPORT_SENDER or POSTMASTER_ADDRESS
- => Specify the sender address
##### LOGWATCH_INTERVAL
Interval for logwatch report.
- **none** => No report is generated
- daily => Send a daily report
- weekly => Send a report every week
##### LOGWATCH_RECIPIENT
Recipient address for logwatch reports if they are enabled.
- **not set** => Use REPORT_RECIPIENT or POSTMASTER_ADDRESS
- => Specify the recipient address(es)
##### REPORT_RECIPIENT (deprecated)
Enables a report being sent (created by pflogsumm) on a regular basis.
- **0** => Report emails are disabled unless enabled by other options
- 1 => Using POSTMASTER_ADDRESS as the recipient
- => Specify the recipient address
##### REPORT_SENDER (deprecated)
Change the sending address for mail report
- **empty** => mailserver-report@hostname
- => Specify the report sender (From) address
##### REPORT_INTERVAL (deprecated)
Changes the interval in which logs are rotated and a report is being sent (deprecated).
- **daily** => Send a daily report
- weekly => Send a report every week
- monthly => Send a report every month
Note: This variable used to control logrotate inside the container and sent the pflogsumm report when the logs were rotated.
It is still supported for backwards compatibility, but the new option LOGROTATE_INTERVAL has been added that only rotates
the logs.
##### LOGROTATE_INTERVAL
Defines the interval in which the mail log is being rotated.
- **daily** => Rotate daily.
- weekly => Rotate weekly.
- monthly => Rotate monthly.
Note that only the log inside the container is affected.
The full log output is still available via `docker logs mail` (or your respective container name).
If you want to control logrotation for the docker generated logfile see: [Docker Logging Drivers](https://docs.docker.com/config/containers/logging/configure/).
Also note that by default the logs are lost when the container is recycled. To keep the logs, mount a volume.
Finally the logrotate interval **may** affect the period for generated reports. That is the case when the reports are triggered by log rotation.
#### Spamassassin
##### ENABLE_SPAMASSASSIN
- **0** => Spamassassin is disabled
- 1 => Spamassassin is enabled
**/!\\ Spam delivery:** when Spamassassin is enabled, messages marked as spam WILL NOT BE DELIVERED.
Use `SPAMASSASSIN_SPAM_TO_INBOX=1` for receiving spam messages.
##### SPAMASSASSIN_SPAM_TO_INBOX
- **0** => Spam messages will be bounced (_rejected_) without any notification (_dangerous_).
- 1 => Spam messages will be delivered to the inbox and tagged as spam using `SA_SPAM_SUBJECT`.
##### MOVE_SPAM_TO_JUNK
- **1** => Spam messages will be delivered in the `Junk` folder.
- 0 => Spam messages will be delivered in the mailbox.
Note: this setting needs `SPAMASSASSIN_SPAM_TO_INBOX=1`
##### SA_TAG
- **2.0** => add spam info headers if at, or above that level
Note: this spamassassin setting needs `ENABLE_SPAMASSASSIN=1`
##### SA_TAG2
- **6.31** => add 'spam detected' headers at that level
Note: this spamassassin setting needs `ENABLE_SPAMASSASSIN=1`
##### SA_KILL
- **6.31** => triggers spam evasive actions
Note: this spamassassin setting needs `ENABLE_SPAMASSASSIN=1`. By default, the mailserver is configured to quarantine spam emails. If emails are quarantined, they are compressed and stored in a location dependent on the ONE_DIR setting above. If `ONE_DIR=1` the location is /var/mail-state/lib-amavis/virusmails/. If `ONE_DIR=0` it is /var/lib/amavis/virusmails/. These paths are inside the docker container. To inhibit this behaviour and deliver spam emails, set this to a very high value e.g. 100.0.
##### SA_SPAM_SUBJECT
- **\*\*\*SPAM\*\*\*** => add tag to subject if spam detected
Note: this spamassassin setting needs `ENABLE_SPAMASSASSIN=1`. Add the spamassassin score to the subject line by inserting the keyword _SCORE_: **\*\*\*SPAM(_SCORE_)\*\*\***.
##### SA_SHORTCIRCUIT_BAYES_SPAM
- **1** => will activate spamassassin short circuiting for bayes spam detection.
This will uncomment the respective line in ```/etc/spamassasin/local.cf```
Note: activate this only if you are confident in your bayes database for identifying spam.
##### SA_SHORTCIRCUIT_BAYES_HAM
- **1** => will activate spamassassin short circuiting for bayes ham detection
This will uncomment the respective line in ```/etc/spamassasin/local.cf```
Note: activate this only if you are confident in your bayes database for identifying ham.
#### Fetchmail
##### ENABLE_FETCHMAIL
- **0** => `fetchmail` disabled
- 1 => `fetchmail` enabled
##### FETCHMAIL_POLL
- **300** => `fetchmail` The number of seconds for the interval
#### LDAP
##### ENABLE_LDAP
- **empty** => LDAP authentification is disabled
- 1 => LDAP authentification is enabled
- NOTE:
- A second container for the ldap service is necessary (e.g. [docker-openldap](https://github.com/osixia/docker-openldap))
- For preparing the ldap server to use in combination with this container [this](http://acidx.net/wordpress/2014/06/installing-a-mailserver-with-postfix-dovecot-sasl-ldap-roundcube/) article may be helpful
##### LDAP_START_TLS
- **empty** => no
- yes => LDAP over TLS enabled for Postfix
##### LDAP_SERVER_HOST
- **empty** => mail.domain.com
- => Specify the dns-name/ip-address where the ldap-server
- NOTE: If you going to use the mailserver in combination with docker-compose you can set the service name here
##### LDAP_SEARCH_BASE
- **empty** => ou=people,dc=domain,dc=com
- => e.g. LDAP_SEARCH_BASE=dc=mydomain,dc=local
##### LDAP_BIND_DN
- **empty** => cn=admin,dc=domain,dc=com
- => take a look at examples of SASL_LDAP_BIND_DN
##### LDAP_BIND_PW
- **empty** => admin
- => Specify the password to bind against ldap
##### LDAP_QUERY_FILTER_USER
- e.g. `(&(mail=%s)(mailEnabled=TRUE))`
- => Specify how ldap should be asked for users
##### LDAP_QUERY_FILTER_GROUP
- e.g. `(&(mailGroupMember=%s)(mailEnabled=TRUE))`
- => Specify how ldap should be asked for groups
##### LDAP_QUERY_FILTER_ALIAS
- e.g. `(&(mailAlias=%s)(mailEnabled=TRUE))`
- => Specify how ldap should be asked for aliases
##### LDAP_QUERY_FILTER_DOMAIN
- e.g. `(&(|(mail=*@%s)(mailalias=*@%s)(mailGroupMember=*@%s))(mailEnabled=TRUE))`
- => Specify how ldap should be asked for domains
##### DOVECOT_TLS
- **empty** => no
- yes => LDAP over TLS enabled for Dovecot
#### Dovecot
The following variables overwrite the default values for ```/etc/dovecot/dovecot-ldap.conf.ext```.
##### DOVECOT_BASE
- **empty** => same as `LDAP_SEARCH_BASE`
- => Tell Dovecot to search only below this base entry. (e.g. `ou=people,dc=domain,dc=com`)
##### DOVECOT_DEFAULT_PASS_SCHEME
- **empty** => `SSHA`
- => Select one crypt scheme for password hashing from this list of [password schemes](https://doc.dovecot.org/configuration_manual/authentication/password_schemes/).
##### DOVECOT_DN
- **empty** => same as `LDAP_BIND_DN`
- => Bind dn for LDAP connection. (e.g. `cn=admin,dc=domain,dc=com`)
##### DOVECOT_DNPASS
- **empty** => same as `LDAP_BIND_PW`
- => Password for LDAP dn sepecifified in `DOVECOT_DN`.
##### DOVECOT_HOSTS
- **empty** => same as `LDAP_SERVER_HOST`
- => Specify a space separated list of LDAP hosts.
##### DOVECOT_LDAP_VERSION
- **empty** => 3
- 2 => LDAP version 2 is used
- 3 => LDAP version 3 is used
##### DOVECOT_AUTH_BIND
- **empty** => no
- yes => Enable [LDAP authentication binds](https://wiki.dovecot.org/AuthDatabase/LDAP/AuthBinds)
##### DOVECOT_USER_FILTER
- e.g. `(&(objectClass=PostfixBookMailAccount)(uniqueIdentifier=%n))`
##### DOVECOT_USER_ATTRS
- e.g. `homeDirectory=home,qmailUID=uid,qmailGID=gid,mailMessageStore=mail`
- => Specify the directory to dovecot attribute mapping that fits your directory structure.
- Note: This is necessary for directories that do not use the [Postfix Book Schema](test/docker-openldap/bootstrap/schema/mmc/postfix-book.schema).
- Note: The left-hand value is the directory attribute, the right hand value is the dovecot variable.
- More details on the [Dovecot Wiki](https://wiki.dovecot.org/AuthDatabase/LDAP/Userdb)
##### DOVECOT_PASS_FILTER
- e.g. `(&(objectClass=PostfixBookMailAccount)(uniqueIdentifier=%n))`
##### DOVECOT_PASS_ATTRS
- e.g. `uid=user,userPassword=password`
- => Specify the directory to dovecot variable mapping that fits your directory structure.
- Note: This is necessary for directories that do not use the [Postfix Book Schema](test/docker-openldap/bootstrap/schema/mmc/postfix-book.schema).
- Note: The left-hand value is the directory attribute, the right hand value is the dovecot variable.
- More details on the [Dovecot Wiki](https://wiki.dovecot.org/AuthDatabase/LDAP/PasswordLookups)
#### Postgrey
##### ENABLE_POSTGREY
- **0** => `postgrey` is disabled
- 1 => `postgrey` is enabled
##### POSTGREY_DELAY
- **300** => greylist for N seconds
Note: This postgrey setting needs `ENABLE_POSTGREY=1`
##### POSTGREY_MAX_AGE
- **35** => delete entries older than N days since the last time that they have been seen
Note: This postgrey setting needs `ENABLE_POSTGREY=1`
##### POSTGREY_AUTO_WHITELIST_CLIENTS
- **5** => whitelist host after N successful deliveries (N=0 to disable whitelisting)
Note: This postgrey setting needs `ENABLE_POSTGREY=1`
##### POSTGREY_TEXT
- **Delayed by Postgrey** => response when a mail is greylisted
Note: This postgrey setting needs `ENABLE_POSTGREY=1`
#### SASL Auth
##### ENABLE_SASLAUTHD
- **0** => `saslauthd` is disabled
- 1 => `saslauthd` is enabled
##### SASLAUTHD_MECHANISMS
- empty => pam
- `ldap` => authenticate against ldap server
- `shadow` => authenticate against local user db
- `mysql` => authenticate against mysql db
- `rimap` => authenticate against imap server
- NOTE: can be a list of mechanisms like pam ldap shadow
##### SASLAUTHD_MECH_OPTIONS
- empty => None
- e.g. with SASLAUTHD_MECHANISMS rimap you need to specify the ip-address/servername of the imap server ==> xxx.xxx.xxx.xxx
##### SASLAUTHD_LDAP_SERVER
- empty => localhost
##### SASLAUTHD_LDAP_SSL
- empty or 0 => `ldap://` will be used
- 1 => `ldaps://` will be used
##### SASLAUTHD_LDAP_START_TLS
- **empty** => `no`
- `yes` => Enable `ldap_start_tls` option
##### SASLAUTHD_LDAP_TLS_CHECK_PEER
- **empty** => `no`
- `yes` => Enable `ldap_tls_check_peer` option
##### SASLAUTHD_LDAP_TLS_CACERT_DIR
Path to directory with CA (Certificate Authority) certificates.
- **empty** => Nothing is added to the configuration
- Any value => Fills the `ldap_tls_cacert_dir` option
##### SASLAUTHD_LDAP_TLS_CACERT_FILE
File containing CA (Certificate Authority) certificate(s).
- **empty** => Nothing is added to the configuration
- Any value => Fills the `ldap_tls_cacert_file` option
##### SASLAUTHD_LDAP_BIND_DN
- empty => anonymous bind
- specify an object with privileges to search the directory tree
- e.g. active directory: SASLAUTHD_LDAP_BIND_DN=cn=Administrator,cn=Users,dc=mydomain,dc=net
- e.g. openldap: SASLAUTHD_LDAP_BIND_DN=cn=admin,dc=mydomain,dc=net
##### SASLAUTHD_LDAP_PASSWORD
- empty => anonymous bind
##### SASLAUTHD_LDAP_SEARCH_BASE
- empty => Reverting to SASLAUTHD_MECHANISMS pam
- specify the search base
##### SASLAUTHD_LDAP_FILTER
- empty => default filter `(&(uniqueIdentifier=%u)(mailEnabled=TRUE))`
- e.g. for active directory: `(&(sAMAccountName=%U)(objectClass=person))`
- e.g. for openldap: `(&(uid=%U)(objectClass=person))`
##### SASLAUTHD_LDAP_PASSWORD_ATTR
Specify what password attribute to use for password verification.
- **empty** => Nothing is added to the configuration but the documentation says it is `userPassword` by default.
- Any value => Fills the `ldap_password_attr` option
##### SASL_PASSWD
- **empty** => No sasl_passwd will be created
- string => `/etc/postfix/sasl_passwd` will be created with the string as password
##### SASLAUTHD_LDAP_AUTH_METHOD
- **empty** => `bind` will be used as a default value
- `fastbind` => The fastbind method is used
- `custom` => The custom method uses userPassword attribute to verify the password
##### SASLAUTHD_LDAP_MECH
Specify the authentication mechanism for SASL bind.
- **empty** => Nothing is added to the configuration
- Any value => Fills the `ldap_mech` option
#### SRS (Sender Rewriting Scheme)
##### SRS_SENDER_CLASSES
An email has an "envelope" sender (indicating the sending server) and a
"header" sender (indicating who sent it). More strict SPF policies may require
you to replace both instead of just the envelope sender.
[More info](https://www.mybluelinux.com/what-is-email-envelope-and-email-header/).
- **envelope_sender** => Rewrite only envelope sender address
- header_sender => Rewrite only header sender (not recommended)
- envelope_sender,header_sender => Rewrite both senders
##### SRS_EXCLUDE_DOMAINS
- **empty** => Envelope sender will be rewritten for all domains
- provide comma separated list of domains to exclude from rewriting
##### SRS_SECRET
- **empty** => generated when the container is started for the first time
- provide a secret to use in base64
- you may specify multiple keys, comma separated. the first one is used for signing and the remaining will be used for verification. this is how you rotate and expire keys
- if you have a cluster/swarm make sure the same keys are on all nodes
- example command to generate a key: `dd if=/dev/urandom bs=24 count=1 2>/dev/null | base64`
##### SRS_DOMAINNAME
- **empty** => Derived from OVERRIDE_HOSTNAME, DOMAINNAME, or the container's hostname
- Set this if auto-detection fails, isn't what you want, or you wish to have a separate container handle DSNs
#### Default Relay Host
##### DEFAULT_RELAY_HOST
- **empty** => don't set default relayhost setting in main.cf
- default host and port to relay all mail through.
Format: `[example.com]:587` (don't forget the brackets if you need this to
be compatible with `$RELAY_USER` and `$RELAY_PASSWORD`, explained below).
#### Multi-domain Relay Hosts
##### RELAY_HOST
- **empty** => don't configure relay host
- default host to relay mail through
##### RELAY_PORT
- **empty** => 25
- default port to relay mail through
##### RELAY_USER
- **empty** => no default
- default relay username (if no specific entry exists in postfix-sasl-password.cf)
##### RELAY_PASSWORD
- **empty** => no default
- password for default relay user

View File

@ -1,6 +1,8 @@
The MIT License (MIT) The MIT License (MIT)
Copyright (c) 2016 Thomas VIAL Copyright © 2016 & 2017 Thomas Vial & Contributors
Copyright © 2016 - 2020 The GitHub Community & Contributors
Copyright © 2021 - PRESENT The Docker Mailserver Organization & Contributors
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal

View File

@ -1,23 +1,38 @@
SHELL = /bin/bash SHELL = /bin/bash
NAME = tvial/docker-mailserver:testing NAME ?= docker.io/mailserver/testing:local
VCS_REF := $(shell git rev-parse --short HEAD) VCS_REF := $(shell git rev-parse --short HEAD)
VCS_VERSION := $(shell git describe --tags --contains --always) VCS_VER := $(shell git describe --tags --contains --always)
all: build backup generate-accounts tests clean HADOLINT_VERSION := 1.19.0
no-build: backup generate-accounts tests clean SHELLCHECK_VERSION := 0.7.1
complete_test: lint build generate-accounts tests ECLINT_VERSION := 2.3.1
#
# Generic Build Targets
#
all: lint build backup generate-accounts tests clean
build: build:
docker build -t $(NAME) . \ docker build -t $(NAME) . --build-arg VCS_VER=$(VCS_VER) --build-arg VCS_REF=$(VCS_REF)
--build-arg VCS_REF=$(VCS_REF) \
--build-arg VCS_VERSION=$(VCS_VERSION) \
backup: backup:
# if backup directories exist, clean hasn't been called, therefore # if backup directories exist, clean hasn't been called, therefore
# we shouldn't overwrite it. It still contains the original content. # we shouldn't overwrite it. It still contains the original content.
@ [[ ! -d config.bak ]] && cp -rp config config.bak -@ [[ ! -d config.bak ]] && cp -rp config config.bak || :
@ [[ ! -d testconfig.bak ]] && cp -rp test/config testconfig.bak -@ [[ ! -d testconfig.bak ]] && cp -rp test/config testconfig.bak || :
clean:
# remove running and stopped test containers
-@ [[ -d config.bak ]] && { rm -rf config ; mv config.bak config ; } || :
-@ [[ -d testconfig.bak ]] && { sudo rm -rf test/config ; mv testconfig.bak test/config ; } || :
-@ docker ps -a | grep -E "testing:local|ldap_for_mail|mail_override_hostname" | cut -f 1-1 -d ' ' | xargs --no-run-if-empty docker rm -f
-@ sudo rm -rf test/onedir test/alias test/quota test/relay test/config/dovecot-lmtp/userdb test/config/key* test/config/opendkim/keys/domain.tld/ test/config/opendkim/keys/example.com/ test/config/opendkim/keys/localdomain2.com/ test/config/postfix-aliases.cf test/config/postfix-receive-access.cf test/config/postfix-receive-access.cfe test/config/dovecot-quotas.cf test/config/postfix-send-access.cf test/config/postfix-send-access.cfe test/config/relay-hosts/chksum test/config/relay-hosts/postfix-aliases.cf test/config/dhparams.pem test/config/dovecot-lmtp/dh.pem test/config/relay-hosts/dovecot-quotas.cf test/config/user-patches.sh test/alias/config/postfix-virtual.cf test/quota/config/dovecot-quotas.cf test/quota/config/postfix-accounts.cf test/relay/config/postfix-relaymap.cf test/relay/config/postfix-sasl-password.cf test/duplicate_configs/
#
# Tests
#
generate-accounts: generate-accounts:
@ docker run --rm -e MAIL_USER=user1@localhost.localdomain -e MAIL_PASS=mypassword -t $(NAME) /bin/sh -c 'echo "$$MAIL_USER|$$(doveadm pw -s SHA512-CRYPT -u $$MAIL_USER -p $$MAIL_PASS)"' > test/config/postfix-accounts.cf @ docker run --rm -e MAIL_USER=user1@localhost.localdomain -e MAIL_PASS=mypassword -t $(NAME) /bin/sh -c 'echo "$$MAIL_USER|$$(doveadm pw -s SHA512-CRYPT -u $$MAIL_USER -p $$MAIL_PASS)"' > test/config/postfix-accounts.cf
@ -26,18 +41,11 @@ generate-accounts:
@ echo " # this is also a test comment, :O" >> test/config/postfix-accounts.cf @ echo " # this is also a test comment, :O" >> test/config/postfix-accounts.cf
tests: tests:
./test/bats/bin/bats test/*.bats @ NAME=$(NAME) ./test/bats/bin/bats test/*.bats
.PHONY: ALWAYS_RUN .PHONY: ALWAYS_RUN
test/%.bats: ALWAYS_RUN test/%.bats: ALWAYS_RUN
./test/bats/bin/bats $@ @ ./test/bats/bin/bats $@
clean:
# remove running and stopped test containers
-@ docker ps -a | grep -E "docker-mailserver:testing|ldap_for_mail" | cut -f 1-1 -d ' ' | xargs --no-run-if-empty docker rm -f
-@ [[ -d config.bak ]] && { rm -rf config ; mv config.bak config ; } || :
-@ [[ -d testconfig.bak ]] && { sudo rm -rf test/config ; mv testconfig.bak test/config ; } || :
-@ sudo rm -rf test/onedir test/alias test/quota test/relay test/config/dovecot-lmtp/userdb test/config/key* test/config/opendkim/keys/domain.tld/ test/config/opendkim/keys/example.com/ test/config/opendkim/keys/localdomain2.com/ test/config/postfix-aliases.cf test/config/postfix-receive-access.cf test/config/postfix-receive-access.cfe test/config/dovecot-quotas.cf test/config/postfix-send-access.cf test/config/postfix-send-access.cfe test/config/relay-hosts/chksum test/config/relay-hosts/postfix-aliases.cf test/config/dhparams.pem test/config/dovecot-lmtp/dh.pem test/config/relay-hosts/dovecot-quotas.cf test/config/user-patches.sh test/alias/config/postfix-virtual.cf test/quota/config/dovecot-quotas.cf test/quota/config/postfix-accounts.cf test/relay/config/postfix-relaymap.cf test/relay/config/postfix-sasl-password.cf test/duplicate_configs/
lint: eclint hadolint shellcheck lint: eclint hadolint shellcheck
@ -49,3 +57,16 @@ shellcheck:
eclint: eclint:
@ ./test/linting/lint.sh eclint @ ./test/linting/lint.sh eclint
install_linters:
@ sudo curl -S -L \
"https://github.com/hadolint/hadolint/releases/download/v$(HADOLINT_VERSION)/hadolint-$(shell uname -s)-$(shell uname -m)" -o /usr/local/bin/hadolint
@ sudo curl -S -L \
"https://github.com/koalaman/shellcheck/releases/download/v$(SHELLCHECK_VERSION)/shellcheck-v$(SHELLCHECK_VERSION).linux.x86_64.tar.xz" | tar -xJ
@ sudo curl -S -L \
"https://github.com/editorconfig-checker/editorconfig-checker/releases/download/$(ECLINT_VERSION)/ec-linux-amd64.tar.gz" | tar -xaz
@ sudo chmod +rx /usr/local/bin/hadolint
@ sudo mv "shellcheck-v$(SHELLCHECK_VERSION)/shellcheck" /usr/bin/
@ sudo mv bin/ec-linux-amd64 /usr/bin/eclint
@ sudo chmod +x /usr/bin/eclint
@ sudo rm -rf "shellcheck-v$(SHELLCHECK_VERSION)" bin

794
README.md
View File

@ -1,53 +1,28 @@
# docker-mailserver # Docker Mailserver
![build_status] [![docker_pulls]][docker::hub] [![ci::status]][ci::github] [![docker::pulls]][docker::hub]
[![gh_stars]][repo] [![contributors]][repo] [![forks]][repo] [ci::status]: https://img.shields.io/github/workflow/status/docker-mailserver/docker-mailserver/Build%2C%20Test%20%26%20Deploy?color=blue&label=CI&logo=github&logoColor=white&style=for-the-badge
[ci::github]: https://github.com/docker-mailserver/docker-mailserver/actions
[docker::pulls]: https://img.shields.io/docker/pulls/mailserver/docker-mailserver.svg?style=for-the-badge&logo=docker&logoColor=white
[docker::hub]: https://hub.docker.com/r/mailserver/docker-mailserver/
[build_status]: https://img.shields.io/travis/tomav/docker-mailserver/master?style=for-the-badge A fullstack but simple mail server (SMTP, IMAP, LDAP, Antispam, Antivirus, etc.). Only configuration files, no SQL database. Keep it simple and versioned. Easy to deploy and upgrade.
[docker_pulls]: https://img.shields.io/docker/pulls/tvial/docker-mailserver.svg?style=for-the-badge
[docker::hub]: https://hub.docker.com/r/tvial/docker-mailserver/
[gh_stars]: https://img.shields.io/github/stars/tomav/docker-mailserver.svg?label=github%20%E2%98%85&style=for-the-badge
[contributors]: https://img.shields.io/github/contributors/tomav/docker-mailserver.svg?style=for-the-badge
[forks]: https://img.shields.io/github/forks/tomav/docker-mailserver.svg?label=github%20forks&style=for-the-badge
[repo]: https://github.com/tomav/docker-mailserver/
A fullstack but simple mail server (SMTP, IMAP, Antispam, Antivirus...). Only configuration files, no SQL database. Keep it simple and versioned. Easy to deploy and upgrade.
[Why this image was created.](http://tvi.al/simple-mail-server-with-docker/) [Why this image was created.](http://tvi.al/simple-mail-server-with-docker/)
1. [Release Notes](#release-notes) 1. [Included Services](#included-services)
2. [Includes](#includes) 2. [Opening Issues and Contributing](#opening-issues-and-contributing)
3. [Issues & Contributing](#issues--contributing) 3. [Requirements](#requirements)
4. [Requirements](#requirements) 4. [Usage](#usage)
5. [Usage](#usage) 5. [Examples](#examples)
6. [Examples](#examples) 6. [Environment Variables](./ENVIRONMENT.md)
7. [Environment Variables](#environment-variables) 7. [Release Notes](./CHANGELOG.md)
## Release Notes ## Included Services
### `v7.2.0`
1. Refactored `target/bin/`
2. Enhanced and refactored all tests
3. Added Code of Conduct
4. Redesigned environment variable use
5. Added missing Dovecot descriptions
### `v7.1.0`
1. The use of default variables has changed slightly. Consult the [environment variables](#environment-variables) section
2. New contributing guidelines were added
3. Added coherent coding style and linting
4. Added option to use non-default network interface
5. SELinux is now supported
## Includes
- [Postfix](http://www.postfix.org) with SMTP or LDAP auth - [Postfix](http://www.postfix.org) with SMTP or LDAP auth
- [Dovecot](https://www.dovecot.org) for SASL, IMAP (and optional POP3) with SSL support, with LDAP auth, Sieve and [quotas](https://github.com/tomav/docker-mailserver/wiki/Configure-Accounts#mailbox-quota) - [Dovecot](https://www.dovecot.org) for SASL, IMAP (or POP3), with LDAP Auth, Sieve and [quotas](https://github.com/tomav/docker-mailserver/wiki/Configure-Accounts#mailbox-quota)
- [Amavis](https://www.amavis.org/) - [Amavis](https://www.amavis.org/)
- [Spamassasin](http://spamassassin.apache.org/) supporting custom rules - [Spamassasin](http://spamassassin.apache.org/) supporting custom rules
- [ClamAV](https://www.clamav.net/) with automatic updates - [ClamAV](https://www.clamav.net/) with automatic updates
@ -59,29 +34,25 @@ A fullstack but simple mail server (SMTP, IMAP, Antispam, Antivirus...). Only co
- [Postgrey](https://postgrey.schweikert.ch/) - [Postgrey](https://postgrey.schweikert.ch/)
- [LetsEncrypt](https://letsencrypt.org/) and self-signed certificates - [LetsEncrypt](https://letsencrypt.org/) and self-signed certificates
- [Setup script](https://github.com/tomav/docker-mailserver/wiki/Setup-docker-mailserver-using-the-script-setup.sh) to easily configure and maintain your mailserver - [Setup script](https://github.com/tomav/docker-mailserver/wiki/Setup-docker-mailserver-using-the-script-setup.sh) to easily configure and maintain your mailserver
- basic [Sieve support](https://github.com/tomav/docker-mailserver/wiki/Configure-Sieve-filters) using dovecot - Basic [Sieve support](https://github.com/tomav/docker-mailserver/wiki/Configure-Sieve-filters) using dovecot
- SASLauthd with LDAP auth - SASLauthd with LDAP auth
- persistent data and state (but think about backups!) - Persistent data and state
- [Integration tests](https://travis-ci.org/tomav/docker-mailserver) - [CI/CD](https://github.com/docker-mailserver/docker-mailserver/actions)
- [Automated builds on docker hub](https://hub.docker.com/r/tvial/docker-mailserver/) - [Extension Delimiters](http://www.postfix.org/postconf.5.html#recipient_delimiter) (`you+extension@example.com` go to `you@example.com`)
- Plus addressing (a.k.a. [extension delimiters](http://www.postfix.org/postconf.5.html#recipient_delimiter))
works out of the box: email for `you+extension@example.com` go to `you@example.com`
## Issues & Contributing ## Opening Issues and Contributing
Before opening an issue, please have a look this `README`, the [Wiki](https://github.com/tomav/docker-mailserver/wiki/) and the Postfix/Dovecot documentation. **Before opening an issue**, read this `README` carefully, use the [Wiki](https://github.com/tomav/docker-mailserver/wiki/), the Postfix/Dovecot documentation and your search engine you trust. The issue tracker is not meant to be used for unrelated questions! If you'd like to contribute, read [`CONTRIBUTING.md`](./CONTRIBUTING.md) thoroughly.
If you'd like to contribute, read [`CONTRIBUTING.md`](./CONTRIBUTING.md) thoroughly.
## Requirements ## Requirements
Recommended: **Recommended**:
- 1 Core - 1 Core
- 1-2GB RAM - 1-2GB RAM
- Swap enabled for the container - Swap enabled for the container
Minimum: **Minimum**:
- 1 vCore - 1 vCore
- 512MB RAM - 512MB RAM
@ -95,10 +66,10 @@ Minimum:
Download the `docker-compose.yml`, `compose.env`, `mailserver.env` and the `setup.sh` files: Download the `docker-compose.yml`, `compose.env`, `mailserver.env` and the `setup.sh` files:
``` BASH ``` BASH
wget https://raw.githubusercontent.com/tomav/docker-mailserver/master/setup.sh wget https://raw.githubusercontent.com/docker-mailserver/docker-mailserver/stable/setup.sh
wget https://raw.githubusercontent.com/tomav/docker-mailserver/master/docker-compose.yml wget https://raw.githubusercontent.com/docker-mailserver/docker-mailserver/stable/docker-compose.yml
wget https://raw.githubusercontent.com/tomav/docker-mailserver/master/mailserver.env wget https://raw.githubusercontent.com/docker-mailserver/docker-mailserver/stable/mailserver.env
wget -O .env https://raw.githubusercontent.com/tomav/docker-mailserver/master/compose.env wget -O .env https://raw.githubusercontent.com/docker-mailserver/docker-mailserver/stable/compose.env
chmod a+x ./setup.sh chmod a+x ./setup.sh
``` ```
@ -107,31 +78,27 @@ chmod a+x ./setup.sh
- [Install the latest docker-compose](https://docs.docker.com/compose/install/) - [Install the latest docker-compose](https://docs.docker.com/compose/install/)
- Edit the files `.env` and `mailserver.env` to your liking: - Edit the files `.env` and `mailserver.env` to your liking:
- `.env` contains the configuration for docker-compose - `.env` contains the configuration for Docker Compose
- `mailserver.env` contains the configuration for the mailserver container - `mailserver.env` contains the configuration for the mailserver container
- These files supports only simple `VAR=VAL` lines (see [Documentation](https://docs.docker.com/compose/env-file/)). - these files supports [only simple `VAR=VAL`](https://docs.docker.com/compose/env-file/)
- Don't quote your values. - don't quote your values
- Variable substitution is *not* supported (e.g. `OVERRIDE_HOSTNAME=$HOSTNAME.$DOMAINNAME`). - variable substitution is *not* supported (e.g. `OVERRIDE_HOSTNAME=$HOSTNAME.$DOMAINNAME`).
- Variables in `.env` are expanded in the `docker-compose.yml` file **only** and **not** in the container. The file `mailserver.env` serves this case where environment variables are used in the container.
**Note:** Variables in `.env` are expanded in the `docker-compose.yml` file **only** and **not** in the container. The file `mailserver.env` serves this case where environment variables are used in the container. - If you want to use a bare domain (host name = domain name), see [FAQ](https://github.com/tomav/docker-mailserver/wiki/FAQ-and-Tips#can-i-use-nakedbare-domains-no-host-name)
**Note:** If you want to use a bare domain (host name equals domain name) see [FAQ](https://github.com/tomav/docker-mailserver/wiki/FAQ-and-Tips#can-i-use-nakedbare-domains-no-host-name).
### Get up and running ### Get up and running
If you'd like to use SELinux, add `-Z` to the variable `SELINUX_LABEL` in `.env`. If you want the volume bind mount to be shared among other containers switch `-Z` to `-z` If you'd like to use SELinux, add `-Z` to the variable `SELINUX_LABEL` in `.env`. If you want the volume bind mount to be shared among other containers switch `-Z` to `-z`
``` BASH ``` BASH
# without SELinux
docker-compose up -d mail docker-compose up -d mail
# without SELinux
./setup.sh email add <user@domain> [<password>] ./setup.sh email add <user@domain> [<password>]
./setup.sh alias add postmaster@<domain> <user@domain> ./setup.sh alias add postmaster@<domain> <user@domain>
./setup.sh config dkim ./setup.sh config dkim
# with SELinux # with SELinux
docker-compose up -d mail
./setup.sh -Z email add <user@domain> [<password>] ./setup.sh -Z email add <user@domain> [<password>]
./setup.sh -Z alias add postmaster@<domain> <user@domain> ./setup.sh -Z alias add postmaster@<domain> <user@domain>
./setup.sh -Z config dkim ./setup.sh -Z config dkim
@ -141,37 +108,26 @@ docker-compose up -d mail
#### DNS - DKIM #### DNS - DKIM
Now that the keys are generated, you can configure your DNS server by just pasting the content of `config/opendkim/keys/domain.tld/mail.txt` in your `domain.tld.hosts` zone. When keys are generated, you can configure your DNS server by just pasting the content of `config/opendkim/keys/domain.tld/mail.txt` to [set up DKIM](https://mxtoolbox.com/dmarc/dkim/setup/how-to-setup-dkim).
#### Custom user changes & patches #### Custom user changes & patches
If you'd like to change, patch or alter files or behavior of `docker-mailserver`, you can use a script. Just place it the `config/` folder that is created on startup and call it `user-patches.sh`. The setup is done like this: If you'd like to change, patch or alter files or behavior of `docker-mailserver`, you can use a script. Just place it the `config/` folder that is created on startup and call it `user-patches.sh`. The setup is done like this:
``` BASH ``` BASH
$ pwd
/where/docker-mailserver/resides/
$ ls -lhA
-rw-r--r-- USER GROUP SIZE DATE .env
-rw-r--r-- USER GROUP SIZE DATE docker-compose.yml
-rw-r--r-- USER GROUP SIZE DATE mailserver.env
# 1. Either create the config/ directory yourself # 1. Either create the config/ directory yourself
# or let docker-mailserver create it on initial # or let docker-mailserver create it on initial
# startup # startup
$ mkdir config /where/docker-mailserver/resides/ $ mkdir config && cd config
$ cd config
# 2. Create the user-patches.sh script and make it # 2. Create the user-patches.sh script and make it
# executable # executable
$ touch user-patches.sh /where/docker-mailserver/resides/config/ $ touch user-patches.sh
$ chmod +x user-patches.sh /where/docker-mailserver/resides/config/ $ chmod +x user-patches.sh
$ ls -lh
-rwxr-xr-x USER GROUP SIZE DATE user-patches.sh
# 3. Edit it # 3. Edit it
$ vi user-patches.sh /where/docker-mailserver/resides/config/ $ vi user-patches.sh
$ cat user-patches.sh /where/docker-mailserver/resides/config/ $ cat user-patches.sh
#! /bin/bash #! /bin/bash
# ! THIS IS AN EXAMPLE ! # ! THIS IS AN EXAMPLE !
@ -187,13 +143,10 @@ then
echo -e '192.168.0.1 some.domain.com' >> /etc/hosts echo -e '192.168.0.1 some.domain.com' >> /etc/hosts
fi fi
sed -i "s/smtpd_sender_restrictions = /smtpd_sender_restrictions = reject_unknown_reverse_client_hostname, /" /etc/postfix/main.cf
sed -i "s/smtpd_sender_restrictions = /smtpd_sender_restrictions = reject_unknown_client_hostname, /" /etc/postfix/main.cf
echo 'user-patches.sh finished successfully' echo 'user-patches.sh finished successfully'
``` ```
And you're done. the user patches script runs right before starting daemons. That means, all the other configuration is in place, so the script can make final adjustments. And you're done. The user patches script runs right before starting daemons. That means, all the other configuration is in place, so the script can make final adjustments.
#### Supported Operating Systems #### Supported Operating Systems
@ -213,7 +166,7 @@ We are currently providing support for Linux. Windows is _not_ supported and is
``` BASH ``` BASH
docker-compose down docker-compose down
docker pull tvial/docker-mailserver:<VERSION TAG> docker pull docker.io/mailserver/docker-mailserver:<VERSION TAG>
docker-compose up -d mail docker-compose up -d mail
``` ```
@ -242,14 +195,14 @@ See the [wiki](https://github.com/tomav/docker-mailserver/wiki) for further deta
### With Relevant Environmental Variables ### With Relevant Environmental Variables
This example provides you only with a basic example of what a minimal setup could look like. We **strongly recommend** that you go through the configuration file yourself and adjust everything to your needs. This example provides you only with a basic example of what a minimal setup could look like. We **strongly recommend** that you go through the configuration file yourself and adjust everything to your needs. The default [docker-compose.yml](./docker-compose.yml) can be used for the purpose out-of-the-box, see the [usage section](#usage).
``` YAML ``` YAML
version: '3.8' version: '3.8'
services: services:
mail: mail:
image: docker.io/tvial/docker-mailserver:latest image: docker.io/mailserver/docker-mailserver:latest
hostname: mail # ${HOSTNAME} hostname: mail # ${HOSTNAME}
domainname: domain.com # ${DOMAINNAME} domainname: domain.com # ${DOMAINNAME}
container_name: mail # ${CONTAINER_NAME} container_name: mail # ${CONTAINER_NAME}
@ -290,7 +243,7 @@ version: '3.8'
services: services:
mail: mail:
image: docker.io/tvial/docker-mailserver:latest image: docker.io/mailserver/docker-mailserver:latest
hostname: mail # ${HOSTNAME} hostname: mail # ${HOSTNAME}
domainname: domain.com # ${DOMAINNAME} domainname: domain.com # ${DOMAINNAME}
container_name: mail # ${CONTAINER_NAME} container_name: mail # ${CONTAINER_NAME}
@ -342,658 +295,3 @@ volumes:
mailstate: mailstate:
maillogs: maillogs:
``` ```
## Environment Variables
If an option doesn't work as documented here, check if you are running the latest image! Values in **bold** are the default values.
**Note**: Since `docker-mailserver v7.1.0`, comparisons for environment variables are executed differently. If you previously used `VARIABLE=''` as the `empty` value, please **update** to now use `VARIABLE=`.
### Assignments
#### General
##### DMS_DEBUG
- **0** => Debug disabled
- 1 => Enables debug on startup
##### ENABLE_CLAMAV
- **0** => Clamav is disabled
- 1 => Clamav is enabled
##### ONE_DIR
- **0** => state in default directories
- 1 => consolidate all states into a single directory (`/var/mail-state`) to allow persistence using docker volumes
##### ENABLE_POP3
- **empty** => POP3 service disabled
- 1 => Enables POP3 service
##### ENABLE_FAIL2BAN
- **0** => fail2ban service disabled
- 1 => Enables fail2ban service
If you enable Fail2Ban, don't forget to add the following lines to your `docker-compose.yml`:
``` BASH
cap_add:
- NET_ADMIN
```
Otherwise, `iptables` won't be able to ban IPs.
##### SMTP_ONLY
- **empty** => all daemons start
- 1 => only launch postfix smtp
##### SSL_TYPE
- **empty** => SSL disabled
- letsencrypt => Enables Let's Encrypt certificates
- custom => Enables custom certificates
- manual => Let you manually specify locations of your SSL certificates for non-standard cases
- self-signed => Enables self-signed certificates
- _any other value_ => SSL required, settings by default
Please read [the SSL page in the wiki](https://github.com/tomav/docker-mailserver/wiki/Configure-SSL) for more information.
##### TLS_LEVEL
- **empty** => modern
- modern => Enables TLSv1.2 and modern ciphers only. (default)
- intermediate => Enables TLSv1, TLSv1.1 and TLSv1.2 and broad compatibility ciphers.
- old => NOT implemented. If you really need it, then customize the TLS ciphers overriding postfix and dovecot settings [wiki](https://github.com/tomav/docker-mailserver/wiki/)
##### SPOOF_PROTECTION
Configures the handling of creating mails with forged sender addresses.
- **empty** => Mail address spoofing allowed. Any logged in user may create email messages with a forged sender address. See also [Wikipedia](https://en.wikipedia.org/wiki/Email_spoofing)(not recommended, but default for backwards compatibility reasons)
- 1 => (recommended) Mail spoofing denied. Each user may only send with his own or his alias addresses. Addresses with [extension delimiters](http://www.postfix.org/postconf.5.html#recipient_delimiter) are not able to send messages.
##### ENABLE_SRS
Enables the Sender Rewriting Scheme. SRS is needed if your mail server acts as forwarder. See [postsrsd](https://github.com/roehling/postsrsd/blob/master/README.md#sender-rewriting-scheme-crash-course) for further explanation.
- **0** => Disabled
- 1 => Enabled
##### PERMIT_DOCKER
Set different options for mynetworks option (can be overwrite in postfix-main.cf) **WARNING**: Adding the docker network's gateway to the list of trusted hosts, e.g. using the `network` or `connected-networks` option, can create an [**open relay**](https://en.wikipedia.org/wiki/Open_mail_relay), [for instance](https://github.com/tomav/docker-mailserver/issues/1405#issuecomment-590106498) if IPv6 is enabled on the host machine but not in Docker.
- **empty** => localhost only
- host => Add docker host (ipv4 only)
- network => Add the docker default bridge network (172.16.0.0/12); **WARNING**: `docker-compose` might use others (e.g. 192.168.0.0/16) use `PERMIT_DOCKER=connected-networks` in this case
- connected-networks => Add all connected docker networks (ipv4 only)
Note: you probably want to [set `POSTFIX_INET_PROTOCOLS=ipv4`](#postfix_inet_protocols) to make it work fine with Docker.
##### NETWORK_INTERFACE
In case your network interface differs from `eth0`, e.g. when you are using HostNetworking in Kubernetes, you can set this to whatever interface you want. This interface will then be used.
- **empty** => `eth0`
##### VIRUSMAILS_DELETE_DELAY
Set how many days a virusmail will stay on the server before being deleted
- **empty** => 7 days
##### ENABLE_POSTFIX_VIRTUAL_TRANSPORT
This Option is activating the Usage of POSTFIX_DAGENT to specify a ltmp client different from default dovecot socket.
- **empty** => disabled
- 1 => enabled
##### POSTFIX_DAGENT
Enabled by ENABLE_POSTFIX_VIRTUAL_TRANSPORT. Specify the final delivery of postfix
- **empty**: fail
- `lmtp:unix:private/dovecot-lmtp` (use socket)
- `lmtps:inet:<host>:<port>` (secure lmtp with starttls, take a look at <https://sys4.de/en/blog/2014/11/17/sicheres-lmtp-mit-starttls-in-dovecot/>)
- `lmtp:<kopano-host>:2003` (use kopano as mailstore)
- etc.
##### POSTFIX\_MAILBOX\_SIZE\_LIMIT
Set the mailbox size limit for all users. If set to zero, the size will be unlimited (default).
- **empty** => 0 (no limit)
##### ENABLE_QUOTAS
- **1** => Dovecot quota is enabled
- 0 => Dovecot quota is disabled
See [mailbox quota](https://github.com/tomav/docker-mailserver/wiki/Configure-Accounts#mailbox-quota).
##### POSTFIX\_MESSAGE\_SIZE\_LIMIT
Set the message size limit for all users. If set to zero, the size will be unlimited (not recommended!)
- **empty** => 10240000 (~10 MB)
##### ENABLE_MANAGESIEVE
- **empty** => Managesieve service disabled
- 1 => Enables Managesieve on port 4190
##### OVERRIDE_HOSTNAME
- **empty** => uses the `hostname` command to get the mail server's canonical hostname
- => Specify a fully-qualified domainname to serve mail for. This is used for many of the config features so if you can't set your hostname (e.g. you're in a container platform that doesn't let you) specify it in this environment variable.
##### POSTMASTER_ADDRESS
- **empty** => postmaster@domain.com
- => Specify the postmaster address
##### POSTSCREEN_ACTION
- **enforce** => Allow other tests to complete. Reject attempts to deliver mail with a 550 SMTP reply, and log the helo/sender/recipient information. Repeat this test the next time the client connects.
- drop => Drop the connection immediately with a 521 SMTP reply. Repeat this test the next time the client connects.
- ignore => Ignore the failure of this test. Allow other tests to complete. Repeat this test the next time the client connects. This option is useful for testing and collecting statistics without blocking mail.
##### DOVECOT_MAILBOX_FORMAT
- **maildir** => uses very common Maildir format, one file contains one message
- sdbox => (experimental) uses Dovecot high-performance mailbox format, one file contains one message
- mdbox ==> (experimental) uses Dovecot high-performance mailbox format, multiple messages per file and multiple files per box
This option has been added in November 2019. Using other format than Maildir is considered as experimental in docker-mailserver and should only be used for testing purpose. For more details, please refer to [Dovecot Documentation](https://wiki2.dovecot.org/MailboxFormat).
##### POSTFIX_INET_PROTOCOLS
- **all** => All possible protocols.
- ipv4 => Use only IPv4 traffic. Most likely you want this behind Docker.
- ipv6 => Use only IPv6 traffic.
Note: More details in <http://www.postfix.org/postconf.5.html#inet_protocols>
#### Reports
##### PFLOGSUMM_TRIGGER
Enables regular pflogsumm mail reports.
- **not set** => No report
- daily_cron => Daily report for the previous day
- logrotate => Full report based on the mail log when it is rotated
This is a new option. The old REPORT options are still supported for backwards compatibility.
If this is not set and reports are enabled with the old options, logrotate will be used.
##### PFLOGSUMM_RECIPIENT
Recipient address for pflogsumm reports.
- **not set** => Use REPORT_RECIPIENT or POSTMASTER_ADDRESS
- => Specify the recipient address(es)
##### PFLOGSUMM_SENDER
From address for pflogsumm reports.
- **not set** => Use REPORT_SENDER or POSTMASTER_ADDRESS
- => Specify the sender address
##### LOGWATCH_INTERVAL
Interval for logwatch report.
- **none** => No report is generated
- daily => Send a daily report
- weekly => Send a report every week
##### LOGWATCH_RECIPIENT
Recipient address for logwatch reports if they are enabled.
- **not set** => Use REPORT_RECIPIENT or POSTMASTER_ADDRESS
- => Specify the recipient address(es)
##### REPORT_RECIPIENT (deprecated)
Enables a report being sent (created by pflogsumm) on a regular basis.
- **0** => Report emails are disabled unless enabled by other options
- 1 => Using POSTMASTER_ADDRESS as the recipient
- => Specify the recipient address
##### REPORT_SENDER (deprecated)
Change the sending address for mail report
- **empty** => mailserver-report@hostname
- => Specify the report sender (From) address
##### REPORT_INTERVAL (deprecated)
Changes the interval in which logs are rotated and a report is being sent (deprecated).
- **daily** => Send a daily report
- weekly => Send a report every week
- monthly => Send a report every month
Note: This variable used to control logrotate inside the container and sent the pflogsumm report when the logs were rotated.
It is still supported for backwards compatibility, but the new option LOGROTATE_INTERVAL has been added that only rotates
the logs.
##### LOGROTATE_INTERVAL
Defines the interval in which the mail log is being rotated.
- **daily** => Rotate daily.
- weekly => Rotate weekly.
- monthly => Rotate monthly.
Note that only the log inside the container is affected.
The full log output is still available via `docker logs mail` (or your respective container name).
If you want to control logrotation for the docker generated logfile see: [Docker Logging Drivers](https://docs.docker.com/config/containers/logging/configure/).
Also note that by default the logs are lost when the container is recycled. To keep the logs, mount a volume.
Finally the logrotate interval **may** affect the period for generated reports. That is the case when the reports are triggered by log rotation.
#### Spamassassin
##### ENABLE_SPAMASSASSIN
- **0** => Spamassassin is disabled
- 1 => Spamassassin is enabled
**/!\\ Spam delivery:** when Spamassassin is enabled, messages marked as spam WILL NOT BE DELIVERED.
Use `SPAMASSASSIN_SPAM_TO_INBOX=1` for receiving spam messages.
##### SPAMASSASSIN_SPAM_TO_INBOX
- **0** => Spam messages will be bounced (_rejected_) without any notification (_dangerous_).
- 1 => Spam messages will be delivered to the inbox and tagged as spam using `SA_SPAM_SUBJECT`.
##### MOVE_SPAM_TO_JUNK
- **1** => Spam messages will be delivered in the `Junk` folder.
- 0 => Spam messages will be delivered in the mailbox.
Note: this setting needs `SPAMASSASSIN_SPAM_TO_INBOX=1`
##### SA_TAG
- **2.0** => add spam info headers if at, or above that level
Note: this spamassassin setting needs `ENABLE_SPAMASSASSIN=1`
##### SA_TAG2
- **6.31** => add 'spam detected' headers at that level
Note: this spamassassin setting needs `ENABLE_SPAMASSASSIN=1`
##### SA_KILL
- **6.31** => triggers spam evasive actions
Note: this spamassassin setting needs `ENABLE_SPAMASSASSIN=1`. By default, the mailserver is configured to quarantine spam emails. If emails are quarantined, they are compressed and stored in a location dependent on the ONE_DIR setting above. If `ONE_DIR=1` the location is /var/mail-state/lib-amavis/virusmails/. If `ONE_DIR=0` it is /var/lib/amavis/virusmails/. These paths are inside the docker container. To inhibit this behaviour and deliver spam emails, set this to a very high value e.g. 100.0.
##### SA_SPAM_SUBJECT
- **\*\*\*SPAM\*\*\*** => add tag to subject if spam detected
Note: this spamassassin setting needs `ENABLE_SPAMASSASSIN=1`. Add the spamassassin score to the subject line by inserting the keyword _SCORE_: **\*\*\*SPAM(_SCORE_)\*\*\***.
##### SA_SHORTCIRCUIT_BAYES_SPAM
- **1** => will activate spamassassin short circuiting for bayes spam detection.
This will uncomment the respective line in ```/etc/spamassasin/local.cf```
Note: activate this only if you are confident in your bayes database for identifying spam.
##### SA_SHORTCIRCUIT_BAYES_HAM
- **1** => will activate spamassassin short circuiting for bayes ham detection
This will uncomment the respective line in ```/etc/spamassasin/local.cf```
Note: activate this only if you are confident in your bayes database for identifying ham.
#### Fetchmail
##### ENABLE_FETCHMAIL
- **0** => `fetchmail` disabled
- 1 => `fetchmail` enabled
##### FETCHMAIL_POLL
- **300** => `fetchmail` The number of seconds for the interval
#### LDAP
##### ENABLE_LDAP
- **empty** => LDAP authentification is disabled
- 1 => LDAP authentification is enabled
- NOTE:
- A second container for the ldap service is necessary (e.g. [docker-openldap](https://github.com/osixia/docker-openldap))
- For preparing the ldap server to use in combination with this container [this](http://acidx.net/wordpress/2014/06/installing-a-mailserver-with-postfix-dovecot-sasl-ldap-roundcube/) article may be helpful
##### LDAP_START_TLS
- **empty** => no
- yes => LDAP over TLS enabled for Postfix
##### LDAP_SERVER_HOST
- **empty** => mail.domain.com
- => Specify the dns-name/ip-address where the ldap-server
- NOTE: If you going to use the mailserver in combination with docker-compose you can set the service name here
##### LDAP_SEARCH_BASE
- **empty** => ou=people,dc=domain,dc=com
- => e.g. LDAP_SEARCH_BASE=dc=mydomain,dc=local
##### LDAP_BIND_DN
- **empty** => cn=admin,dc=domain,dc=com
- => take a look at examples of SASL_LDAP_BIND_DN
##### LDAP_BIND_PW
- **empty** => admin
- => Specify the password to bind against ldap
##### LDAP_QUERY_FILTER_USER
- e.g. `(&(mail=%s)(mailEnabled=TRUE))`
- => Specify how ldap should be asked for users
##### LDAP_QUERY_FILTER_GROUP
- e.g. `(&(mailGroupMember=%s)(mailEnabled=TRUE))`
- => Specify how ldap should be asked for groups
##### LDAP_QUERY_FILTER_ALIAS
- e.g. `(&(mailAlias=%s)(mailEnabled=TRUE))`
- => Specify how ldap should be asked for aliases
##### LDAP_QUERY_FILTER_DOMAIN
- e.g. `(&(|(mail=*@%s)(mailalias=*@%s)(mailGroupMember=*@%s))(mailEnabled=TRUE))`
- => Specify how ldap should be asked for domains
##### DOVECOT_TLS
- **empty** => no
- yes => LDAP over TLS enabled for Dovecot
#### Dovecot
The following variables overwrite the default values for ```/etc/dovecot/dovecot-ldap.conf.ext```.
##### DOVECOT_BASE
- **empty** => same as `LDAP_SEARCH_BASE`
- => Tell Dovecot to search only below this base entry. (e.g. `ou=people,dc=domain,dc=com`)
##### DOVECOT_DEFAULT_PASS_SCHEME
- **empty** => `SSHA`
- => Select one crypt scheme for password hashing from this list of [password schemes](https://doc.dovecot.org/configuration_manual/authentication/password_schemes/).
##### DOVECOT_DN
- **empty** => same as `LDAP_BIND_DN`
- => Bind dn for LDAP connection. (e.g. `cn=admin,dc=domain,dc=com`)
##### DOVECOT_DNPASS
- **empty** => same as `LDAP_BIND_PW`
- => Password for LDAP dn sepecifified in `DOVECOT_DN`.
##### DOVECOT_HOSTS
- **empty** => same as `LDAP_SERVER_HOST`
- => Specify a space separated list of LDAP hosts.
##### DOVECOT_LDAP_VERSION
- **empty** => 3
- 2 => LDAP version 2 is used
- 3 => LDAP version 3 is used
##### DOVECOT_AUTH_BIND
- **empty** => no
- yes => Enable [LDAP authentication binds](https://wiki.dovecot.org/AuthDatabase/LDAP/AuthBinds)
##### DOVECOT_USER_FILTER
- e.g. `(&(objectClass=PostfixBookMailAccount)(uniqueIdentifier=%n))`
##### DOVECOT_USER_ATTRS
- e.g. `homeDirectory=home,qmailUID=uid,qmailGID=gid,mailMessageStore=mail`
- => Specify the directory to dovecot attribute mapping that fits your directory structure.
- Note: This is necessary for directories that do not use the [Postfix Book Schema](test/docker-openldap/bootstrap/schema/mmc/postfix-book.schema).
- Note: The left-hand value is the directory attribute, the right hand value is the dovecot variable.
- More details on the [Dovecot Wiki](https://wiki.dovecot.org/AuthDatabase/LDAP/Userdb)
##### DOVECOT_PASS_FILTER
- e.g. `(&(objectClass=PostfixBookMailAccount)(uniqueIdentifier=%n))`
##### DOVECOT_PASS_ATTRS
- e.g. `uid=user,userPassword=password`
- => Specify the directory to dovecot variable mapping that fits your directory structure.
- Note: This is necessary for directories that do not use the [Postfix Book Schema](test/docker-openldap/bootstrap/schema/mmc/postfix-book.schema).
- Note: The left-hand value is the directory attribute, the right hand value is the dovecot variable.
- More details on the [Dovecot Wiki](https://wiki.dovecot.org/AuthDatabase/LDAP/PasswordLookups)
#### Postgrey
##### ENABLE_POSTGREY
- **0** => `postgrey` is disabled
- 1 => `postgrey` is enabled
##### POSTGREY_DELAY
- **300** => greylist for N seconds
Note: This postgrey setting needs `ENABLE_POSTGREY=1`
##### POSTGREY_MAX_AGE
- **35** => delete entries older than N days since the last time that they have been seen
Note: This postgrey setting needs `ENABLE_POSTGREY=1`
##### POSTGREY_AUTO_WHITELIST_CLIENTS
- **5** => whitelist host after N successful deliveries (N=0 to disable whitelisting)
Note: This postgrey setting needs `ENABLE_POSTGREY=1`
##### POSTGREY_TEXT
- **Delayed by postgrey** => response when a mail is greylisted
Note: This postgrey setting needs `ENABLE_POSTGREY=1`
#### SASL Auth
##### ENABLE_SASLAUTHD
- **0** => `saslauthd` is disabled
- 1 => `saslauthd` is enabled
##### SASLAUTHD_MECHANISMS
- empty => pam
- `ldap` => authenticate against ldap server
- `shadow` => authenticate against local user db
- `mysql` => authenticate against mysql db
- `rimap` => authenticate against imap server
- NOTE: can be a list of mechanisms like pam ldap shadow
##### SASLAUTHD_MECH_OPTIONS
- empty => None
- e.g. with SASLAUTHD_MECHANISMS rimap you need to specify the ip-address/servername of the imap server ==> xxx.xxx.xxx.xxx
##### SASLAUTHD_LDAP_SERVER
- empty => localhost
##### SASLAUTHD_LDAP_SSL
- empty or 0 => `ldap://` will be used
- 1 => `ldaps://` will be used
##### SASLAUTHD_LDAP_START_TLS
- **empty** => `no`
- `yes` => Enable `ldap_start_tls` option
##### SASLAUTHD_LDAP_TLS_CHECK_PEER
- **empty** => `no`
- `yes` => Enable `ldap_tls_check_peer` option
##### SASLAUTHD_LDAP_TLS_CACERT_DIR
Path to directory with CA (Certificate Authority) certificates.
- **empty** => Nothing is added to the configuration
- Any value => Fills the `ldap_tls_cacert_dir` option
##### SASLAUTHD_LDAP_TLS_CACERT_FILE
File containing CA (Certificate Authority) certificate(s).
- **empty** => Nothing is added to the configuration
- Any value => Fills the `ldap_tls_cacert_file` option
##### SASLAUTHD_LDAP_BIND_DN
- empty => anonymous bind
- specify an object with privileges to search the directory tree
- e.g. active directory: SASLAUTHD_LDAP_BIND_DN=cn=Administrator,cn=Users,dc=mydomain,dc=net
- e.g. openldap: SASLAUTHD_LDAP_BIND_DN=cn=admin,dc=mydomain,dc=net
##### SASLAUTHD_LDAP_PASSWORD
- empty => anonymous bind
##### SASLAUTHD_LDAP_SEARCH_BASE
- empty => Reverting to SASLAUTHD_MECHANISMS pam
- specify the search base
##### SASLAUTHD_LDAP_FILTER
- empty => default filter `(&(uniqueIdentifier=%u)(mailEnabled=TRUE))`
- e.g. for active directory: `(&(sAMAccountName=%U)(objectClass=person))`
- e.g. for openldap: `(&(uid=%U)(objectClass=person))`
##### SASLAUTHD_LDAP_PASSWORD_ATTR
Specify what password attribute to use for password verification.
- **empty** => Nothing is added to the configuration but the documentation says it is `userPassword` by default.
- Any value => Fills the `ldap_password_attr` option
##### SASL_PASSWD
- **empty** => No sasl_passwd will be created
- string => `/etc/postfix/sasl_passwd` will be created with the string as password
##### SASLAUTHD_LDAP_AUTH_METHOD
- **empty** => `bind` will be used as a default value
- `fastbind` => The fastbind method is used
- `custom` => The custom method uses userPassword attribute to verify the password
##### SASLAUTHD_LDAP_MECH
Specify the authentication mechanism for SASL bind.
- **empty** => Nothing is added to the configuration
- Any value => Fills the `ldap_mech` option
#### SRS (Sender Rewriting Scheme)
##### SRS_SENDER_CLASSES
An email has an "envelope" sender (indicating the sending server) and a
"header" sender (indicating who sent it). More strict SPF policies may require
you to replace both instead of just the envelope sender.
[More info](https://www.mybluelinux.com/what-is-email-envelope-and-email-header/).
- **envelope_sender** => Rewrite only envelope sender address
- header_sender => Rewrite only header sender (not recommended)
- envelope_sender,header_sender => Rewrite both senders
##### SRS_EXCLUDE_DOMAINS
- **empty** => Envelope sender will be rewritten for all domains
- provide comma separated list of domains to exclude from rewriting
##### SRS_SECRET
- **empty** => generated when the container is started for the first time
- provide a secret to use in base64
- you may specify multiple keys, comma separated. the first one is used for signing and the remaining will be used for verification. this is how you rotate and expire keys
- if you have a cluster/swarm make sure the same keys are on all nodes
- example command to generate a key: `dd if=/dev/urandom bs=24 count=1 2>/dev/null | base64`
##### SRS_DOMAINNAME
- **empty** => Derived from OVERRIDE_HOSTNAME, DOMAINNAME, or the container's hostname
- Set this if auto-detection fails, isn't what you want, or you wish to have a separate container handle DSNs
#### Default Relay Host
##### DEFAULT_RELAY_HOST
- **empty** => don't set default relayhost setting in main.cf
- default host and port to relay all mail through.
Format: `[example.com]:587` (don't forget the brackets if you need this to
be compatible with `$RELAY_USER` and `$RELAY_PASSWORD`, explained below).
#### Multi-domain Relay Hosts
##### RELAY_HOST
- **empty** => don't configure relay host
- default host to relay mail through
##### RELAY_PORT
- **empty** => 25
- default port to relay mail through
##### RELAY_USER
- **empty** => no default
- default relay username (if no specific entry exists in postfix-sasl-password.cf)
##### RELAY_PASSWORD
- **empty** => no default
- password for default relay user

View File

@ -2,13 +2,13 @@
# Docker Compose Settings Variables # Docker Compose Settings Variables
# #
HOSTNAME=mail HOSTNAME=<INSERT 'HOSTNAME' HERE>
DOMAINNAME=domain.com DOMAINNAME=<INSERT 'DOMAIN.TLD' HERE>
CONTAINER_NAME=mail CONTAINER_NAME=<INSERT 'CONTAINER NAME' HERE>
# #
# SELinux Compose File Settings Variables # SELinux Compose File Settings Variables
# options: -z or -Z # options: empty, '-z' or '-Z'
# #
SELINUX_LABEL= SELINUX_LABEL=

View File

@ -1,11 +1,12 @@
version: '3.8' version: '3.8'
services: services:
mail: mailserver:
image: tvial/docker-mailserver:latest image: docker.io/mailserver/docker-mailserver:latest
hostname: ${HOSTNAME} hostname: ${HOSTNAME}
domainname: ${DOMAINNAME} domainname: ${DOMAINNAME}
container_name: ${CONTAINER_NAME} container_name: ${CONTAINER_NAME}
env_file: mailserver.env
ports: ports:
- "25:25" - "25:25"
- "143:143" - "143:143"
@ -16,12 +17,8 @@ services:
- mailstate:/var/mail-state - mailstate:/var/mail-state
- maillogs:/var/log/mail - maillogs:/var/log/mail
- ./config/:/tmp/docker-mailserver/${SELINUX_LABEL} - ./config/:/tmp/docker-mailserver/${SELINUX_LABEL}
env_file:
- mailserver.env
cap_add:
- NET_ADMIN
- SYS_PTRACE
restart: always restart: always
cap_add: [ "NET_ADMIN", "SYS_PTRACE" ]
volumes: volumes:
maildata: maildata:

View File

@ -1,9 +0,0 @@
#! /bin/sh
VCS_REF="$(git rev-parse --short HEAD)"
VCS_VERSION="$(git describe --tags --contains --always)"
docker build \
--build-arg VCS_REF="${VCS_REF}" \
--build-arg VCS_VERSION="${VCS_VERSION}" \
-f "${DOCKERFILE_PATH}" -t "${IMAGE_NAME}" .

View File

@ -289,7 +289,7 @@ POSTGREY_DELAY=300
# delete entries older than N days since the last time that they have been seen # delete entries older than N days since the last time that they have been seen
POSTGREY_MAX_AGE=35 POSTGREY_MAX_AGE=35
# response when a mail is greylisted # response when a mail is greylisted
POSTGREY_TEXT=Delayed by postgrey POSTGREY_TEXT=Delayed by Postgrey
# whitelist host after N successful deliveries (N=0 to disable whitelisting) # whitelist host after N successful deliveries (N=0 to disable whitelisting)
POSTGREY_AUTO_WHITELIST_CLIENTS=5 POSTGREY_AUTO_WHITELIST_CLIENTS=5

View File

@ -1,7 +1,8 @@
#! /bin/bash #! /bin/bash
# Wrapper for various setup scripts # version v0.2.4 stable
# included in docker-mailserver # executed manually (via Make)
# task wrapper for various setup scripts
SCRIPT='setup.sh' SCRIPT='setup.sh'
@ -11,16 +12,11 @@ trap '_unset_vars || :' EXIT
function __log_err function __log_err
{ {
local FUNC_NAME LINE EXIT_CODE
FUNC_NAME="${1} / ${2}"
LINE="${3}"
EXIT_CODE="${4}"
printf "\n \e[1m\e[31mUNCHECKED ERROR\e[0m\n%s\n%s\n%s\n%s\n\n" \ printf "\n \e[1m\e[31mUNCHECKED ERROR\e[0m\n%s\n%s\n%s\n%s\n\n" \
" script = ${SCRIPT:-${0}}" \ " script = ${SCRIPT:-${0}}" \
" function = ${FUNC_NAME}" \ " function = ${1} / ${2}" \
" line = ${LINE}" \ " line = ${3}" \
" exit code = ${EXIT_CODE}" 1>&2 " exit code = ${4}" >&2
} }
function _unset_vars function _unset_vars
@ -62,7 +58,7 @@ function _check_root
if [[ ${EUID} -ne 0 ]] if [[ ${EUID} -ne 0 ]]
then then
echo "Curently docker-mailserver doesn't support podman's rootless mode, please run this script as root user." echo "Curently docker-mailserver doesn't support podman's rootless mode, please run this script as root user."
return 1 exit 1
fi fi
} }
@ -108,8 +104,8 @@ Usage: ${0} [-i IMAGE_NAME] [-c CONTAINER_NAME] <subcommand> <subcommand> [args]
OPTIONS: OPTIONS:
-i IMAGE_NAME The name of the docker-mailserver image, by default -i IMAGE_NAME The name of the docker-mailserver image, by default
'tvial/docker-mailserver:latest' for docker, and 'mailserver/docker-mailserver:latest' for docker, and
'docker.io/tvial/docker-mailserver:latest' for podman. 'docker.io/mailserver/docker-mailserver:latest' for podman.
-c CONTAINER_NAME The name of the running container. -c CONTAINER_NAME The name of the running container.
@ -170,12 +166,8 @@ SUBCOMMANDS:
function _docker_image_exists function _docker_image_exists
{ {
if ${CRI} history -q "${1}" >/dev/null 2>&1 ${CRI} history -q "${1}" &>/dev/null
then return ${?}
return 0
else
return 1
fi
} }
function _docker_image function _docker_image
@ -204,17 +196,17 @@ function _docker_container
then then
${CRI} exec "${USE_TTY}" "${CONTAINER_NAME}" "${@}" ${CRI} exec "${USE_TTY}" "${CONTAINER_NAME}" "${@}"
else else
echo "The docker-mailserver is not running!" echo "The mailserver is not running!"
exit 5 exit 1
fi fi
} }
function _main function _main
{ {
if [[ -n $(command -v docker) ]] if command -v docker &>/dev/null
then then
CRI=docker CRI=docker
elif [[ -n $(command -v podman) ]] elif command -v podman &>/dev/null
then then
CRI=podman CRI=podman
_check_root _check_root
@ -223,29 +215,25 @@ function _main
exit 10 exit 10
fi fi
INFO=$(${CRI} ps \ INFO=$(${CRI} ps --no-trunc --format "{{.Image}};{{.Names}}" --filter \
--no-trunc \ label=org.opencontainers.image.title="docker-mailserver" | tail -1)
--format "{{.Image}};{{.Names}}" \
--filter label=org.label-schema.name="docker-mailserver" | \
tail -1)
IMAGE_NAME=${INFO%;*} IMAGE_NAME=${INFO%;*}
CONTAINER_NAME=${INFO#*;} CONTAINER_NAME=${INFO#*;}
if [[ -z ${IMAGE_NAME} ]] if [[ -z ${IMAGE_NAME} ]]
then then
if [[ ${CRI} == "docker" ]] IMAGE_NAME=${NAME:-'docker.io/mailserver/docker-mailserver:latest'}
then
IMAGE_NAME=tvial/docker-mailserver:latest
elif [[ ${CRI} == "podman" ]]
then
IMAGE_NAME=docker.io/tvial/docker-mailserver:latest
fi
fi fi
if tty -s if test -t 0
then then
USE_TTY="-ti" USE_TTY="-ti"
else
# GitHub Actions will fail (or really anything else
# lacking an interactive tty) if we don't set a
# value here; "-t" alone works for these cases.
USE_TTY="-t"
fi fi
local OPTIND local OPTIND

View File

@ -1,15 +0,0 @@
#! /bin/bash
# executed from scripts in target/bin/
# task provides frequently used functions
function errex
{
echo "${@}" 1>&2
exit 1
}
function escape
{
echo "${1//./\\.}"
}

View File

@ -1,7 +1,7 @@
#! /bin/bash #! /bin/bash
# shellcheck source=../bin-helper.sh # shellcheck source=../scripts/helper-functions.sh
. /usr/local/bin/bin-helper.sh . /usr/local/bin/helper-functions.sh
DATABASE=${DATABASE:-/tmp/docker-mailserver/postfix-virtual.cf} DATABASE=${DATABASE:-/tmp/docker-mailserver/postfix-virtual.cf}

View File

@ -2,8 +2,8 @@
# shellcheck disable=SC2094 # shellcheck disable=SC2094
# shellcheck source=../bin-helper.sh # shellcheck source=../scripts/helper-functions.sh
. /usr/local/bin/bin-helper.sh . /usr/local/bin/helper-functions.sh
DATABASE=${DATABASE:-/tmp/docker-mailserver/postfix-accounts.cf} DATABASE=${DATABASE:-/tmp/docker-mailserver/postfix-accounts.cf}

View File

@ -1,7 +1,7 @@
#! /bin/bash #! /bin/bash
# shellcheck source=../bin-helper.sh # shellcheck source=../scripts/helper-functions.sh
. /usr/local/bin/bin-helper.sh . /usr/local/bin/helper-functions.sh
DATABASE=${DATABASE:-/tmp/docker-mailserver/postfix-relaymap.cf} DATABASE=${DATABASE:-/tmp/docker-mailserver/postfix-relaymap.cf}

View File

@ -1,7 +1,7 @@
#! /bin/bash #! /bin/bash
# shellcheck source=../bin-helper.sh # shellcheck source=../scripts/helper-functions.sh
. /usr/local/bin/bin-helper.sh . /usr/local/bin/helper-functions.sh
DATABASE=${DATABASE:-/tmp/docker-mailserver/postfix-sasl-password.cf} DATABASE=${DATABASE:-/tmp/docker-mailserver/postfix-sasl-password.cf}

View File

@ -1,7 +1,7 @@
#! /bin/bash #! /bin/bash
# shellcheck source=../bin-helper.sh # shellcheck source=../scripts/helper-functions.sh
. /usr/local/bin/bin-helper.sh . /usr/local/bin/helper-functions.sh
DATABASE=${DATABASE:-/tmp/docker-mailserver/postfix-virtual.cf} DATABASE=${DATABASE:-/tmp/docker-mailserver/postfix-virtual.cf}

View File

@ -5,8 +5,8 @@
# ? being used below. (This disables the message file-wide.) # ? being used below. (This disables the message file-wide.)
# shellcheck disable=SC2094 # shellcheck disable=SC2094
# shellcheck source=../bin-helper.sh # shellcheck source=../scripts/helper-functions.sh
. /usr/local/bin/bin-helper.sh . /usr/local/bin/helper-functions.sh
DATABASE=${DATABASE:-/tmp/docker-mailserver/postfix-accounts.cf} DATABASE=${DATABASE:-/tmp/docker-mailserver/postfix-accounts.cf}
ALIAS_DATABASE="/tmp/docker-mailserver/postfix-virtual.cf" ALIAS_DATABASE="/tmp/docker-mailserver/postfix-virtual.cf"

View File

@ -1,7 +1,7 @@
#! /bin/bash #! /bin/bash
# shellcheck source=../bin-helper.sh # shellcheck source=../scripts/helper-functions.sh
. /usr/local/bin/bin-helper.sh . /usr/local/bin/helper-functions.sh
DATABASE=${DATABASE:-/tmp/docker-mailserver/dovecot-quotas.cf} DATABASE=${DATABASE:-/tmp/docker-mailserver/dovecot-quotas.cf}
USER_DATABASE=${USER_DATABASE:-/tmp/docker-mailserver/postfix-accounts.cf} USER_DATABASE=${USER_DATABASE:-/tmp/docker-mailserver/postfix-accounts.cf}

View File

@ -1,7 +1,7 @@
#! /bin/bash #! /bin/bash
# shellcheck source=../bin-helper.sh # shellcheck source=../scripts/helper-functions.sh
. /usr/local/bin/bin-helper.sh . /usr/local/bin/helper-functions.sh
DATABASE=${DATABASE:-/tmp/docker-mailserver/postfix-relaymap.cf} DATABASE=${DATABASE:-/tmp/docker-mailserver/postfix-relaymap.cf}

View File

@ -1,7 +1,7 @@
#! /bin/bash #! /bin/bash
# shellcheck source=../bin-helper.sh # shellcheck source=../scripts/helper-functions.sh
. /usr/local/bin/bin-helper.sh . /usr/local/bin/helper-functions.sh
function usage { echo "Usage: ${0} [<unban> <ip-address>]" ; } function usage { echo "Usage: ${0} [<unban> <ip-address>]" ; }

View File

@ -1,7 +1,7 @@
#! /bin/bash #! /bin/bash
# shellcheck source=../bin-helper.sh # shellcheck source=../scripts/helper-functions.sh
. /usr/local/bin/bin-helper.sh . /usr/local/bin/helper-functions.sh
DATABASE=${DATABASE:-/tmp/docker-mailserver/postfix-virtual.cf} DATABASE=${DATABASE:-/tmp/docker-mailserver/postfix-virtual.cf}

View File

@ -5,8 +5,8 @@
# ? being used below. (This disables the message file-wide.) # ? being used below. (This disables the message file-wide.)
# shellcheck disable=SC2094 # shellcheck disable=SC2094
# shellcheck source=../bin-helper.sh # shellcheck source=../scripts/helper-functions.sh
. /usr/local/bin/bin-helper.sh . /usr/local/bin/helper-functions.sh
DATABASE=${DATABASE:-/tmp/docker-mailserver/postfix-accounts.cf} DATABASE=${DATABASE:-/tmp/docker-mailserver/postfix-accounts.cf}

View File

@ -1,7 +1,7 @@
#! /bin/bash #! /bin/bash
# shellcheck source=../bin-helper.sh # shellcheck source=../scripts/helper-functions.sh
. /usr/local/bin/bin-helper.sh . /usr/local/bin/helper-functions.sh
HOSTNAME=${1} HOSTNAME=${1}
RECIPIENT=${2} RECIPIENT=${2}

View File

@ -1,7 +1,7 @@
#! /bin/bash #! /bin/bash
# shellcheck source=../bin-helper.sh # shellcheck source=../scripts/helper-functions.sh
. /usr/local/bin/bin-helper.sh . /usr/local/bin/helper-functions.sh
set -o errexit set -o errexit
set -o pipefail set -o pipefail

View File

@ -1,7 +1,7 @@
#! /bin/bash #! /bin/bash
# shellcheck source=../bin-helper.sh # shellcheck source=../scripts/helper-functions.sh
. /usr/local/bin/bin-helper.sh . /usr/local/bin/helper-functions.sh
MODE="${1}" MODE="${1}"
USER="${3}" USER="${3}"

View File

@ -5,8 +5,8 @@
# ? being used below. (This disables the message file-wide.) # ? being used below. (This disables the message file-wide.)
# shellcheck disable=SC2094 # shellcheck disable=SC2094
# shellcheck source=../bin-helper.sh # shellcheck source=../scripts/helper-functions.sh
. /usr/local/bin/bin-helper.sh . /usr/local/bin/helper-functions.sh
DATABASE=${DATABASE:-/tmp/docker-mailserver/dovecot-quotas.cf} DATABASE=${DATABASE:-/tmp/docker-mailserver/dovecot-quotas.cf}
USER_DATABASE=${USER_DATABASE:-/tmp/docker-mailserver/postfix-accounts.cf} USER_DATABASE=${USER_DATABASE:-/tmp/docker-mailserver/postfix-accounts.cf}

View File

@ -5,8 +5,8 @@
# ? being used below. (This disables the message file-wide.) # ? being used below. (This disables the message file-wide.)
# shellcheck disable=SC2094 # shellcheck disable=SC2094
# shellcheck source=../bin-helper.sh # shellcheck source=../scripts/helper-functions.sh
. /usr/local/bin/bin-helper.sh . /usr/local/bin/helper-functions.sh
DATABASE=${DATABASE:-/tmp/docker-mailserver/postfix-accounts.cf} DATABASE=${DATABASE:-/tmp/docker-mailserver/postfix-accounts.cf}

View File

@ -251,7 +251,7 @@ mail_plugins = $mail_plugins quota
# (For systems setting struct dirent->d_type, this check is free and it's # (For systems setting struct dirent->d_type, this check is free and it's
# done always regardless of this setting) # done always regardless of this setting)
# ------- # -------
# tomav/docker-mailserver: # mailserver/docker-mailserver:
# Seen dovecot-sieve is always enabled, setting `maildir_stat_dirs = yes` permits # Seen dovecot-sieve is always enabled, setting `maildir_stat_dirs = yes` permits
# to avoid `/var/mail/domain.tld/user/.dovecot.sieve` (symlink) to be treated as a directory (default behavior). # to avoid `/var/mail/domain.tld/user/.dovecot.sieve` (symlink) to be treated as a directory (default behavior).
# According to https://github.com/Mailu/Mailu/issues/143#issuecomment-274596931, there is no noticeable impact when this is enabled. # According to https://github.com/Mailu/Mailu/issues/143#issuecomment-274596931, there is no noticeable impact when this is enabled.

View File

@ -1,15 +0,0 @@
#! /usr/bin/env sh
# Report a quota usage warning to an user
PERCENT="${1}"
USER="${2}"
DOMAIN="${3}"
# shellcheck disable=SC2250
cat << EOF | /usr/lib/dovecot/dovecot-lda -d "$USER" -o "plugin/quota=maildir:User quota:noenforcing"
From: postmaster@$DOMAIN
Subject: quota warning
Your mailbox is now $PERCENT% full.
EOF

View File

@ -6,34 +6,35 @@
LOG_DATE=$(date +"%Y-%m-%d %H:%M:%S ") LOG_DATE=$(date +"%Y-%m-%d %H:%M:%S ")
echo "${LOG_DATE} Start check-for-changes script." echo "${LOG_DATE} Start check-for-changes script."
# ? Checks ------------------------------------------------ # ? Checks
cd /tmp/docker-mailserver || exit 1 cd /tmp/docker-mailserver || exit 1
# Check postfix-accounts.cf exist else break # check postfix-accounts.cf exist else break
if [[ ! -f postfix-accounts.cf ]] if [[ ! -f postfix-accounts.cf ]]
then then
echo "${LOG_DATE} postfix-accounts.cf is missing! This should not run! Exit!" echo "${LOG_DATE} postfix-accounts.cf is missing! This should not run! Exit!"
exit exit 0
fi fi
# Verify checksum file exists; must be prepared by start-mailserver.sh # verify checksum file exists; must be prepared by start-mailserver.sh
if [[ ! -f ${CHKSUM_FILE} ]] if [[ ! -f ${CHKSUM_FILE} ]]
then then
echo "${LOG_DATE} ${CHKSUM_FILE} is missing! Start script failed? Exit!" echo "${LOG_DATE} ${CHKSUM_FILE} is missing! Start script failed? Exit!"
exit exit 0
fi fi
# ? Actual script begins ---------------------------------- # ? Actual script begins
# Determine postmaster address, duplicated from start-mailserver.sh # determine postmaster address, duplicated from start-mailserver.sh
# This script previously didn't work when POSTMASTER_ADDRESS was empty # this script previously didn't work when POSTMASTER_ADDRESS was empty
if [[ -n ${OVERRIDE_HOSTNAME} ]] if [[ -n ${OVERRIDE_HOSTNAME} ]]
then then
DOMAINNAME="${OVERRIDE_HOSTNAME#*.}" DOMAINNAME="${OVERRIDE_HOSTNAME#*.}"
else else
DOMAINNAME="$(hostname -d)" DOMAINNAME="$(hostname -d)"
fi fi
PM_ADDRESS="${POSTMASTER_ADDRESS:=postmaster@${DOMAINNAME}}" PM_ADDRESS="${POSTMASTER_ADDRESS:=postmaster@${DOMAINNAME}}"
echo "${LOG_DATE} Using postmaster address ${PM_ADDRESS}" echo "${LOG_DATE} Using postmaster address ${PM_ADDRESS}"
sleep 10 sleep 10

View File

@ -1,7 +1,21 @@
#! /bin/bash #! /bin/bash
# ? IP and CIDR ------------------------------------------- DMS_DEBUG="${DMS_DEBUG:=0}"
# ? BIN HELPER
function errex
{
echo "${@}" 1>&2
exit 1
}
function escape
{
echo "${1//./\\.}"
}
# ? IP & CIDR
function _mask_ip_digit function _mask_ip_digit
{ {
@ -43,9 +57,7 @@ function _sanitize_ipv4_to_subnet_cidr
} }
export -f _sanitize_ipv4_to_subnet_cidr export -f _sanitize_ipv4_to_subnet_cidr
# ? ACME
# ? ACME certs --------------------------------------------
function _extract_certs_from_acme function _extract_certs_from_acme
{ {
@ -94,60 +106,30 @@ for key, value in acme.items():
} }
export -f _extract_certs_from_acme export -f _extract_certs_from_acme
# ? Notifications
# ? Notification ------------------------------------------
declare -A DEFAULT_VARS
DEFAULT_VARS["DMS_DEBUG"]="${DMS_DEBUG:=0}"
function _notify function _notify
{ {
c_red="\e[0;31m" local FINAL_MSG=''
c_green="\e[0;32m" local MSG="${2:-}"
c_brown="\e[0;33m" local TYPE="${1:-}"
c_blue="\e[0;34m"
c_bold="\033[1m"
c_reset="\e[0m"
notification_type=${1} case "${TYPE}" in
notification_msg=${2} 'none' ) FINAL_MSG=' ' ;;
notification_format=${3} 'tasklog' ) FINAL_MSG="[ \e[0;92mTASKLOG\e[0m ] ${MSG}" ;; # light green
msg="" 'warn' ) FINAL_MSG="[ \e[0;93mWARNING\e[0m ] ${MSG}" ;; # light yellow
'err' ) FINAL_MSG="[ \e[0;31mERROR\e[0m ] ${MSG}" ;; # light red
case "${notification_type}" in 'fatal' ) FINAL_MSG="[ \e[0;91mFATAL\e[0m ] ${MSG}" ;; # red
'taskgrp' ) msg="${c_bold}${notification_msg}${c_reset}" ;; 'inf' ) [[ ${DMS_DEBUG} -eq 1 ]] && FINAL_MSG="[[ \e[0;34mINFO\e[0m ]] ${MSG}" ;; # light blue
'task' ) 'task' ) [[ ${DMS_DEBUG} -eq 1 ]] && FINAL_MSG="[[ \e[0;37mTASK\e[0m ]] ${MSG}" ;; # light grey
if [[ ${DEFAULT_VARS["DMS_DEBUG"]} -eq 1 ]] * ) ;;
then
msg=" ${notification_msg}${c_reset}"
fi
;;
'inf' )
if [[ ${DEFAULT_VARS["DMS_DEBUG"]} -eq 1 ]]
then
msg="${c_green} * ${notification_msg}${c_reset}"
fi
;;
'started' ) msg="${c_green} ${notification_msg}${c_reset}" ;;
'warn' ) msg="${c_brown} Warning ${notification_msg}${c_reset}" ;;
'err' ) msg="${c_blue} Error ${notification_msg}${c_reset}" ;;
'fatal' ) msg="${c_red} Fatal Error: ${notification_msg}${c_reset}" ;;
* ) msg="" ;;
esac esac
case "${notification_format}" in [[ -n ${FINAL_MSG} ]] && echo "-e${3:-}" "${FINAL_MSG}"
'n' ) options="-ne" ;;
* ) options="-e" ;;
esac
[[ -n "${msg}" ]] && echo "${options}" "${msg}"
} }
export -f _notify export -f _notify
# ? Relay Host Map
# ? Relay Host Map ----------------------------------------
# setup /etc/postfix/relayhost_map # setup /etc/postfix/relayhost_map
# -- # --
@ -184,9 +166,7 @@ function _populate_relayhost_map
} }
export -f _populate_relayhost_map export -f _populate_relayhost_map
# ? File Checksums
# ? File checksums ----------------------------------------
# file storing the checksums of the monitored files. # file storing the checksums of the monitored files.
# shellcheck disable=SC2034 # shellcheck disable=SC2034

View File

@ -1,6 +1,6 @@
#! /bin/bash #! /bin/bash
function _generate_secret { ( umask 0077 ; dd if=/dev/urandom bs=24 count=1 2>/dev/null | base64 -w0 > "${1}" ) } function _generate_secret { ( umask 0077 ; dd if=/dev/urandom bs=24 count=1 2>/dev/null | base64 -w0 > "${1}" ; ) ; }
if [[ -n ${SRS_DOMAINNAME} ]] if [[ -n ${SRS_DOMAINNAME} ]]
then then
@ -23,7 +23,7 @@ POSTSRSD_STATE_SECRET_FILE="${POSTSRSD_STATE_DIR}/postsrsd.secret"
if [[ -n ${SRS_SECRET} ]] if [[ -n ${SRS_SECRET} ]]
then then
( umask 0077 ; echo "${SRS_SECRET}" | tr ',' '\n' > "${POSTSRSD_SECRET_FILE}" ) ( umask 0077 ; echo "${SRS_SECRET}" | tr ',' '\n' > "${POSTSRSD_SECRET_FILE}" ; )
else else
if [[ ${ONE_DIR} -eq 1 ]] if [[ ${ONE_DIR} -eq 1 ]]
then then

14
target/scripts/quota-warning.sh Executable file
View File

@ -0,0 +1,14 @@
#! /bin/bash
# Report a quota usage warning to an user
PERCENT="${1}"
USER="${2}"
DOMAIN="${3}"
cat << EOF | /usr/lib/dovecot/dovecot-lda -d "${USER}" -o "plugin/quota=maildir:User quota:noenforcing"
From: postmaster@${DOMAIN}
Subject: quota warning
Your mailbox is now ${PERCENT}% full.
EOF

View File

@ -1,108 +1,92 @@
#! /bin/bash #! /bin/bash
########################################################################## ##########################################################################
# >> DEFAULT VARS # >> SETUP DEFAULT VALUES
#
# add them here.
# Example: DEFAULT_VARS["KEY"]="VALUE"
########################################################################## ##########################################################################
declare -A DEFAULT_VARS DOVECOT_MAILBOX_FORMAT="${DOVECOT_MAILBOX_FORMAT:=maildir}"
DOVECOT_TLS="${DOVECOT_TLS:=no}"
DEFAULT_VARS["ENABLE_CLAMAV"]="${ENABLE_CLAMAV:=0}" ENABLE_CLAMAV="${ENABLE_CLAMAV:=0}"
DEFAULT_VARS["ENABLE_SPAMASSASSIN"]="${ENABLE_SPAMASSASSIN:=0}" ENABLE_FAIL2BAN="${ENABLE_FAIL2BAN:=0}"
DEFAULT_VARS["ENABLE_POP3"]="${ENABLE_POP3:=0}" ENABLE_FETCHMAIL="${ENABLE_FETCHMAIL:=0}"
DEFAULT_VARS["ENABLE_FAIL2BAN"]="${ENABLE_FAIL2BAN:=0}" ENABLE_LDAP="${ENABLE_LDAP:=0}"
DEFAULT_VARS["ENABLE_MANAGESIEVE"]="${ENABLE_MANAGESIEVE:=0}" ENABLE_MANAGESIEVE="${ENABLE_MANAGESIEVE:=0}"
DEFAULT_VARS["ENABLE_FETCHMAIL"]="${ENABLE_FETCHMAIL:=0}" ENABLE_POP3="${ENABLE_POP3:=0}"
DEFAULT_VARS["FETCHMAIL_POLL"]="${FETCHMAIL_POLL:=300}" ENABLE_POSTGREY="${ENABLE_POSTGREY:=0}"
DEFAULT_VARS["ENABLE_LDAP"]="${ENABLE_LDAP:=0}" ENABLE_QUOTAS="${ENABLE_QUOTAS:=1}"
DEFAULT_VARS["ENABLE_QUOTAS"]="${ENABLE_QUOTAS:=1}" ENABLE_SASLAUTHD="${ENABLE_SASLAUTHD:=0}"
DEFAULT_VARS["LDAP_START_TLS"]="${LDAP_START_TLS:="no"}" ENABLE_SPAMASSASSIN="${ENABLE_SPAMASSASSIN:=0}"
DEFAULT_VARS["DOVECOT_TLS"]="${DOVECOT_TLS:="no"}" ENABLE_SRS="${ENABLE_SRS:=0}"
DEFAULT_VARS["DOVECOT_MAILBOX_FORMAT"]="${DOVECOT_MAILBOX_FORMAT:="maildir"}" FETCHMAIL_POLL="${FETCHMAIL_POLL:=300}"
DEFAULT_VARS["ENABLE_POSTGREY"]="${ENABLE_POSTGREY:=0}" LDAP_START_TLS="${LDAP_START_TLS:=no}"
DEFAULT_VARS["POSTGREY_DELAY"]="${POSTGREY_DELAY:=300}" LOGROTATE_INTERVAL="${LOGROTATE_INTERVAL:=${REPORT_INTERVAL:-daily}}"
DEFAULT_VARS["POSTGREY_MAX_AGE"]="${POSTGREY_MAX_AGE:=35}" LOGWATCH_INTERVAL="${LOGWATCH_INTERVAL:=none}"
DEFAULT_VARS["POSTGREY_AUTO_WHITELIST_CLIENTS"]="${POSTGREY_AUTO_WHITELIST_CLIENTS:=5}" MOVE_SPAM_TO_JUNK="${MOVE_SPAM_TO_JUNK:=1}"
DEFAULT_VARS["POSTGREY_TEXT"]="${POSTGREY_TEXT:="Delayed by postgrey"}" NETWORK_INTERFACE="${NETWORK_INTERFACE:=eth0}"
DEFAULT_VARS["POSTFIX_MESSAGE_SIZE_LIMIT"]="${POSTFIX_MESSAGE_SIZE_LIMIT:=10240000}" # ~10 MB by default ONE_DIR="${ONE_DIR:=0}"
DEFAULT_VARS["POSTFIX_MAILBOX_SIZE_LIMIT"]="${POSTFIX_MAILBOX_SIZE_LIMIT:=0}" # no limit by default OVERRIDE_HOSTNAME="${OVERRIDE_HOSTNAME}"
DEFAULT_VARS["POSTFIX_INET_PROTOCOLS"]="${POSTFIX_INET_PROTOCOLS:="all"}" POSTGREY_AUTO_WHITELIST_CLIENTS="${POSTGREY_AUTO_WHITELIST_CLIENTS:=5}"
DEFAULT_VARS["ENABLE_SASLAUTHD"]="${ENABLE_SASLAUTHD:=0}" POSTGREY_DELAY="${POSTGREY_DELAY:=300}"
DEFAULT_VARS["SMTP_ONLY"]="${SMTP_ONLY:=0}" POSTGREY_MAX_AGE="${POSTGREY_MAX_AGE:=35}"
DEFAULT_VARS["OVERRIDE_HOSTNAME"]="${OVERRIDE_HOSTNAME}" POSTGREY_TEXT="${POSTGREY_TEXT:=Delayed by Postgrey}"
DEFAULT_VARS["POSTSCREEN_ACTION"]="${POSTSCREEN_ACTION:="enforce"}" POSTFIX_INET_PROTOCOLS="${POSTFIX_INET_PROTOCOLS:=all}"
DEFAULT_VARS["SPOOF_PROTECTION"]="${SPOOF_PROTECTION:=0}" POSTFIX_MAILBOX_SIZE_LIMIT="${POSTFIX_MAILBOX_SIZE_LIMIT:=0}" # no limit by default
DEFAULT_VARS["TLS_LEVEL"]="${TLS_LEVEL:="modern"}" POSTFIX_MESSAGE_SIZE_LIMIT="${POSTFIX_MESSAGE_SIZE_LIMIT:=10240000}" # ~10 MB by default
DEFAULT_VARS["ENABLE_SRS"]="${ENABLE_SRS:=0}" POSTSCREEN_ACTION="${POSTSCREEN_ACTION:=enforce}"
DEFAULT_VARS["SRS_SENDER_CLASSES"]="${SRS_SENDER_CLASSES:="envelope_sender"}" REPORT_RECIPIENT="${REPORT_RECIPIENT:="0"}"
DEFAULT_VARS["REPORT_RECIPIENT"]="${REPORT_RECIPIENT:=0}" SMTP_ONLY="${SMTP_ONLY:=0}"
DEFAULT_VARS["LOGROTATE_INTERVAL"]="${LOGROTATE_INTERVAL:=${REPORT_INTERVAL:-"daily"}}" SPAMASSASSIN_SPAM_TO_INBOX_IS_SET="$( if [[ -n ${SPAMASSASSIN_SPAM_TO_INBOX+'set'} ]]; then echo true ; else echo false ; fi )"
DEFAULT_VARS["LOGWATCH_INTERVAL"]="${LOGWATCH_INTERVAL:="none"}" SPAMASSASSIN_SPAM_TO_INBOX="${SPAMASSASSIN_SPAM_TO_INBOX:=0}"
DEFAULT_VARS["EXPLICITLY_DEFINED_SPAMASSASSIN_SPAM_TO_INBOX"]="$( [ -z "${SPAMASSASSIN_SPAM_TO_INBOX}" ] && echo "0" || echo "1" )" # used for backward compatibility SPOOF_PROTECTION="${SPOOF_PROTECTION:=0}"
DEFAULT_VARS["SPAMASSASSIN_SPAM_TO_INBOX"]="${SPAMASSASSIN_SPAM_TO_INBOX:=0}" SRS_SENDER_CLASSES="${SRS_SENDER_CLASSES:=envelope_sender}"
DEFAULT_VARS["MOVE_SPAM_TO_JUNK"]="${MOVE_SPAM_TO_JUNK:=1}" SSL_TYPE="${SSL_TYPE:=''}"
DEFAULT_VARS["VIRUSMAILS_DELETE_DELAY"]="${VIRUSMAILS_DELETE_DELAY:=7}" TLS_LEVEL="${TLS_LEVEL:=modern}"
DEFAULT_VARS["NETWORK_INTERFACE"]="${NETWORK_INTERFACE:="eth0"}" VIRUSMAILS_DELETE_DELAY="${VIRUSMAILS_DELETE_DELAY:=7}"
# DEFAULT_VARS["DMS_DEBUG"] defined in helper-functions.sh
########################################################################## ##########################################################################
# << DEFAULT VARS # >> GLOBAL VARIABLES
##########################################################################
##########################################################################
# >> GLOBAL VARS
#
# add your global script variables here.
#
# Example: KEY="VALUE"
########################################################################## ##########################################################################
HOSTNAME="$(hostname -f)" HOSTNAME="$(hostname -f)"
DOMAINNAME="$(hostname -d)" DOMAINNAME="$(hostname -d)"
CHKSUM_FILE=/tmp/docker-mailserver-config-chksum CHKSUM_FILE=/tmp/docker-mailserver-config-chksum
##########################################################################
# << GLOBAL VARS
##########################################################################
########################################################################## ##########################################################################
# >> REGISTER FUNCTIONS # >> REGISTER FUNCTIONS
# #
# add your new functions/methods here. # Add your new functions/methods here.
# #
# NOTE: position matters when registering a function in stacks. First in First out # NOTE: Position matters when registering a function in stacks.
# Execution Logic: # First in First out
# > check functions #
# > setup functions # Execution Logic:
# > fix functions # > check functions
# > misc functions # > setup functions
# > start-daemons # > fix functions
# > misc functions
# > start-daemons
# #
# Example: # Example:
#
# if [[ CONDITION IS MET ]] # if [[ CONDITION IS MET ]]
# then # then
# _register_{setup,fix,check,start}_{functions,daemons} "$FUNCNAME" # _register_{setup,fix,check,start}_{functions,daemons} "${FUNCNAME}"
# fi # fi
# #
# Implement them in the section-group: {check,setup,fix,start} # Implement them in the section-group: {check, setup, fix, start}
#
########################################################################## ##########################################################################
function register_functions function register_functions
{ {
_notify 'taskgrp' 'Initializing setup' _notify 'tasklog' 'Initializing setup'
_notify 'task' 'Registering check,setup,fix,misc and start-daemons functions' _notify 'task' 'Registering check, setup, fix, misc and start-daemons functions'
################### >> check funcs ################### >> check funcs
_register_check_function "_check_environment_variables" _register_check_function "_check_environment_variables"
_register_check_function "_check_hostname" _register_check_function "_check_hostname"
################### << check funcs
################### >> setup funcs ################### >> setup funcs
_register_setup_function "_setup_default_vars" _register_setup_function "_setup_default_vars"
@ -153,14 +137,9 @@ function register_functions
_register_setup_function "_setup_postfix_access_control" _register_setup_function "_setup_postfix_access_control"
if [[ -n ${AWS_SES_HOST} ]] && [[ -n ${AWS_SES_USERPASS} ]] [[ -n ${DEFAULT_RELAY_HOST:-''} ]] && _register_setup_function "_setup_postfix_default_relay_host"
then [[ -n ${RELAY_HOST:-''} ]] && _register_setup_function "_setup_postfix_relay_hosts"
_register_setup_function "_setup_postfix_relay_hosts" [[ ${ENABLE_POSTFIX_VIRTUAL_TRANSPORT:-0} -eq 1 ]] && _register_setup_function "_setup_postfix_virtual_transport"
fi
[[ -n ${DEFAULT_RELAY_HOST} ]] && _register_setup_function "_setup_postfix_default_relay_host"
[[ -n ${RELAY_HOST} ]] && _register_setup_function "_setup_postfix_relay_hosts"
[[ ${ENABLE_POSTFIX_VIRTUAL_TRANSPORT} -eq 1 ]] && _register_setup_function "_setup_postfix_virtual_transport"
_register_setup_function "_setup_postfix_override_configuration" _register_setup_function "_setup_postfix_override_configuration"
_register_setup_function "_setup_environment" _register_setup_function "_setup_environment"
@ -171,11 +150,9 @@ function register_functions
_register_setup_function "_setup_user_patches" _register_setup_function "_setup_user_patches"
# Compute last as the config files are modified in-place # compute last as the config files are modified in-place
_register_setup_function "_setup_chksum_file" _register_setup_function "_setup_chksum_file"
################### << setup funcs
################### >> fix funcs ################### >> fix funcs
_register_fix_function "_fix_var_mail_permissions" _register_fix_function "_fix_var_mail_permissions"
@ -184,14 +161,10 @@ function register_functions
[[ ${ENABLE_CLAMAV} -eq 0 ]] && _register_fix_function "_fix_cleanup_clamav" [[ ${ENABLE_CLAMAV} -eq 0 ]] && _register_fix_function "_fix_cleanup_clamav"
[[ ${ENABLE_SPAMASSASSIN} -eq 0 ]] && _register_fix_function "_fix_cleanup_spamassassin" [[ ${ENABLE_SPAMASSASSIN} -eq 0 ]] && _register_fix_function "_fix_cleanup_spamassassin"
################### << fix funcs
################### >> misc funcs ################### >> misc funcs
_register_misc_function "_misc_save_states" _register_misc_function "_misc_save_states"
################### << misc funcs
################### >> daemon funcs ################### >> daemon funcs
_register_start_daemon "_start_daemons_cron" _register_start_daemon "_start_daemons_cron"
@ -209,14 +182,13 @@ function register_functions
_register_start_daemon "_start_daemons_postfix" _register_start_daemon "_start_daemons_postfix"
[[ ${ENABLE_SASLAUTHD} -eq 1 ]] && _register_start_daemon "_start_daemons_saslauthd" [[ ${ENABLE_SASLAUTHD} -eq 1 ]] && _register_start_daemon "_start_daemons_saslauthd"
[[ ${ENABLE_FAIL2BAN} -eq 1 ]] && _register_start_daemon "_start_daemons_fail2ban" # care :: needs to run after postfix # care :: needs to run after postfix
[[ ${ENABLE_FAIL2BAN} -eq 1 ]] && _register_start_daemon "_start_daemons_fail2ban"
[[ ${ENABLE_FETCHMAIL} -eq 1 ]] && _register_start_daemon "_start_daemons_fetchmail" [[ ${ENABLE_FETCHMAIL} -eq 1 ]] && _register_start_daemon "_start_daemons_fetchmail"
[[ ${ENABLE_CLAMAV} -eq 1 ]] && _register_start_daemon "_start_daemons_clamav" [[ ${ENABLE_CLAMAV} -eq 1 ]] && _register_start_daemon "_start_daemons_clamav"
[[ ${ENABLE_LDAP} -eq 0 ]] && _register_start_daemon "_start_changedetector" [[ ${ENABLE_LDAP} -eq 0 ]] && _register_start_daemon "_start_changedetector"
_register_start_daemon "_start_daemons_amavis" _register_start_daemon "_start_daemons_amavis"
################### << daemon funcs
} }
########################################################################## ##########################################################################
@ -224,9 +196,9 @@ function register_functions
########################################################################## ##########################################################################
# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! # !
# ! CARE --> DON'T CHANGE, unless you exactly know what you are doing # ! CARE BEGIN
# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! # !
########################################################################## ##########################################################################
@ -238,7 +210,6 @@ declare -a FUNCS_FIX
declare -a FUNCS_CHECK declare -a FUNCS_CHECK
declare -a FUNCS_MISC declare -a FUNCS_MISC
declare -a DAEMONS_START declare -a DAEMONS_START
# declare -A HELPERS_EXEC_STATE
########################################################################## ##########################################################################
# << CONSTANTS # << CONSTANTS
@ -294,23 +265,22 @@ function display_startup_daemon
${1} &>/dev/null ${1} &>/dev/null
local RES=${?} local RES=${?}
if [[ ${DEFAULT_VARS["DMS_DEBUG"]} -eq 1 ]] if [[ ${DMS_DEBUG} -eq 1 ]]
then then
if [[ ${RES} -eq 0 ]] if [[ ${RES} -eq 0 ]]
then then
_notify 'started' " [ OK ]" _notify 'inf' " OK"
else else
echo "false" _notify 'err' " STARTUP FAILED"
_notify 'err' " [ FAILED ]"
fi fi
fi fi
return "${RES}" return "${RES}"
} }
# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! # !
# ! CARE --> DON'T CHANGE, except you know exactly what you are doing # ! CARE END
# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! # !
########################################################################## ##########################################################################
@ -321,7 +291,7 @@ function display_startup_daemon
function check function check
{ {
_notify 'taskgrp' 'Checking configuration' _notify 'tasklog' 'Checking configuration'
for FUNC in "${FUNCS_CHECK[@]}" for FUNC in "${FUNCS_CHECK[@]}"
do do
@ -336,16 +306,16 @@ function _check_hostname
{ {
_notify "task" "Check that hostname/domainname is provided or overridden (no default docker hostname/kubernetes) [in ${FUNCNAME[0]}]" _notify "task" "Check that hostname/domainname is provided or overridden (no default docker hostname/kubernetes) [in ${FUNCNAME[0]}]"
if [[ -n ${DEFAULT_VARS["OVERRIDE_HOSTNAME"]} ]] if [[ -n ${OVERRIDE_HOSTNAME} ]]
then then
export HOSTNAME=${DEFAULT_VARS["OVERRIDE_HOSTNAME"]} export HOSTNAME=${OVERRIDE_HOSTNAME}
export DOMAINNAME="${HOSTNAME#*.}" export DOMAINNAME="${HOSTNAME#*.}"
fi fi
_notify 'inf' "Domain has been set to ${DOMAINNAME}" _notify 'inf' "Domain has been set to ${DOMAINNAME}"
_notify 'inf' "Hostname has been set to ${HOSTNAME}" _notify 'inf' "Hostname has been set to ${HOSTNAME}"
if ( ! echo "${HOSTNAME}" | grep -E '^(\S+[.]\S+)$' > /dev/null ) if ( ! grep -E '^(\S+[.]\S+)$' <<< "${HOSTNAME}" >/dev/null )
then then
_notify 'err' "Setting hostname/domainname is required" _notify 'err' "Setting hostname/domainname is required"
kill "$(< /var/run/supervisord.pid)" && return 1 kill "$(< /var/run/supervisord.pid)" && return 1
@ -373,7 +343,7 @@ function _check_environment_variables
function setup function setup
{ {
_notify 'taskgrp' 'Configuring mail server' _notify 'tasklog' 'Configuring mail server'
for FUNC in "${FUNCS_SETUP[@]}" for FUNC in "${FUNCS_SETUP[@]}"
do do
${FUNC} ${FUNC}
@ -382,45 +352,75 @@ function setup
function _setup_default_vars function _setup_default_vars
{ {
_notify 'task' "Setting up default variables [in ${FUNCNAME[0]}]" _notify 'task' "Setting up default variables"
# update POSTMASTER_ADDRESS - must be done done after _check_hostname # update POSTMASTER_ADDRESS - must be done done after _check_hostname
DEFAULT_VARS["POSTMASTER_ADDRESS"]="${POSTMASTER_ADDRESS:=postmaster@${DOMAINNAME}}" POSTMASTER_ADDRESS="${POSTMASTER_ADDRESS:="postmaster@${DOMAINNAME}"}"
# update REPORT_SENDER - must be done done after _check_hostname # update REPORT_SENDER - must be done done after _check_hostname
DEFAULT_VARS["REPORT_SENDER"]="${REPORT_SENDER:=mailserver-report@${HOSTNAME}}" REPORT_SENDER="${REPORT_SENDER:="mailserver-report@${HOSTNAME}"}"
DEFAULT_VARS["PFLOGSUMM_SENDER"]="${PFLOGSUMM_SENDER:=${REPORT_SENDER}}" PFLOGSUMM_SENDER="${PFLOGSUMM_SENDER:=${REPORT_SENDER}}"
# set PFLOGSUMM_TRIGGER here for backwards compatibility # set PFLOGSUMM_TRIGGER here for backwards compatibility
# when REPORT_RECIPIENT is on the old method should be used # when REPORT_RECIPIENT is on the old method should be used
# ! needs to be a string comparison
if [[ ${REPORT_RECIPIENT} == "0" ]] if [[ ${REPORT_RECIPIENT} == "0" ]]
then then
DEFAULT_VARS["PFLOGSUMM_TRIGGER"]="${PFLOGSUMM_TRIGGER:="none"}" PFLOGSUMM_TRIGGER="${PFLOGSUMM_TRIGGER:="none"}"
else else
DEFAULT_VARS["PFLOGSUMM_TRIGGER"]="${PFLOGSUMM_TRIGGER:="logrotate"}" PFLOGSUMM_TRIGGER="${PFLOGSUMM_TRIGGER:="logrotate"}"
fi fi
# expand address to simplify the rest of the script # expand address to simplify the rest of the script
if [[ ${REPORT_RECIPIENT} == "0" ]] || [[ ${REPORT_RECIPIENT} == "1" ]] if [[ ${REPORT_RECIPIENT} == "0" ]] || [[ ${REPORT_RECIPIENT} == "0" ]]
then then
REPORT_RECIPIENT="${POSTMASTER_ADDRESS}" REPORT_RECIPIENT="${POSTMASTER_ADDRESS}"
DEFAULT_VARS["REPORT_RECIPIENT"]="${REPORT_RECIPIENT}" REPORT_RECIPIENT="${REPORT_RECIPIENT}"
fi fi
DEFAULT_VARS["PFLOGSUMM_RECIPIENT"]="${PFLOGSUMM_RECIPIENT:=${REPORT_RECIPIENT}}" PFLOGSUMM_RECIPIENT="${PFLOGSUMM_RECIPIENT:=${REPORT_RECIPIENT}}"
DEFAULT_VARS["LOGWATCH_RECIPIENT"]="${LOGWATCH_RECIPIENT:=${REPORT_RECIPIENT}}" LOGWATCH_RECIPIENT="${LOGWATCH_RECIPIENT:=${REPORT_RECIPIENT}}"
for var in "${!DEFAULT_VARS[@]}" {
do echo "DOVECOT_MAILBOX_FORMAT=${DOVECOT_MAILBOX_FORMAT}"
if ! echo "export ${var}=\"${DEFAULT_VARS[${var}]}\"" >>/root/.bashrc echo "DOVECOT_TLS=${DOVECOT_TLS}"
then echo "ENABLE_CLAMAV=${ENABLE_CLAMAV}"
_notify 'err' "Unable to set ${var}=${DEFAULT_VARS[${var}]}" echo "ENABLE_FAIL2BAN=${ENABLE_FAIL2BAN}"
kill -15 "$(< /var/run/supervisord.pid)" echo "ENABLE_FETCHMAIL=${ENABLE_FETCHMAIL}"
return 1 echo "ENABLE_LDAP=${ENABLE_LDAP}"
fi echo "ENABLE_MANAGESIEVE=${ENABLE_MANAGESIEVE}"
echo "ENABLE_POP3=${ENABLE_POP3}"
_notify 'inf' "Set ${var}=${DEFAULT_VARS[${var}]}" echo "ENABLE_POSTGREY=${ENABLE_POSTGREY}"
done echo "ENABLE_QUOTAS=${ENABLE_QUOTAS}"
echo "ENABLE_SASLAUTHD=${ENABLE_SASLAUTHD}"
echo "ENABLE_SPAMASSASSIN=${ENABLE_SPAMASSASSIN}"
echo "ENABLE_SRS=${ENABLE_SRS}"
echo "FETCHMAIL_POLL=${FETCHMAIL_POLL}"
echo "LDAP_START_TLS=${LDAP_START_TLS}"
echo "LOGROTATE_INTERVAL=${LOGROTATE_INTERVAL}"
echo "LOGWATCH_INTERVAL=${LOGWATCH_INTERVAL}"
echo "MOVE_SPAM_TO_JUNK=${MOVE_SPAM_TO_JUNK}"
echo "NETWORK_INTERFACE=${NETWORK_INTERFACE}"
echo "ONE_DIR=${ONE_DIR}"
echo "OVERRIDE_HOSTNAME=${OVERRIDE_HOSTNAME}"
echo "POSTGREY_AUTO_WHITELIST_CLIENTS=${POSTGREY_AUTO_WHITELIST_CLIENTS}"
echo "POSTGREY_DELAY=${POSTGREY_DELAY}"
echo "POSTGREY_MAX_AGE=${POSTGREY_MAX_AGE}"
echo "POSTGREY_TEXT=${POSTGREY_TEXT}"
echo "POSTFIX_INET_PROTOCOLS=${POSTFIX_INET_PROTOCOLS}"
echo "POSTFIX_MAILBOX_SIZE_LIMIT=${POSTFIX_MAILBOX_SIZE_LIMIT}"
echo "POSTFIX_MESSAGE_SIZE_LIMIT=${POSTFIX_MESSAGE_SIZE_LIMIT}"
echo "POSTSCREEN_ACTION=${POSTSCREEN_ACTION}"
echo "REPORT_RECIPIENT=${REPORT_RECIPIENT}"
echo "SMTP_ONLY=${SMTP_ONLY}"
echo "SPAMASSASSIN_SPAM_TO_INBOX=${SPAMASSASSIN_SPAM_TO_INBOX}"
echo "SPOOF_PROTECTION=${SPOOF_PROTECTION}"
echo "SRS_SENDER_CLASSES=${SRS_SENDER_CLASSES}"
echo "SSL_TYPE=${SSL_TYPE}"
echo "TLS_LEVEL=${TLS_LEVEL}"
echo "VIRUSMAILS_DELETE_DELAY=${VIRUSMAILS_DELETE_DELAY}"
echo "DMS_DEBUG=${DMS_DEBUG}"
} >>/root/.bashrc
} }
# File/folder permissions are fine when using docker volumes, but may be wrong # File/folder permissions are fine when using docker volumes, but may be wrong
@ -631,11 +631,11 @@ function _setup_dovecot_quota
sed -i "s/mail_plugins = \$mail_plugin/mail_plugins = \$mail_plugins imap_quota/g" /etc/dovecot/conf.d/20-imap.conf sed -i "s/mail_plugins = \$mail_plugin/mail_plugins = \$mail_plugins imap_quota/g" /etc/dovecot/conf.d/20-imap.conf
fi fi
message_size_limit_mb=$((DEFAULT_VARS["POSTFIX_MESSAGE_SIZE_LIMIT"] / 1000000)) local MESSAGE_SIZE_LIMIT_MB=$((POSTFIX_MESSAGE_SIZE_LIMIT / 1000000))
mailbox_limit_mb=$((DEFAULT_VARS["POSTFIX_MAILBOX_SIZE_LIMIT"] / 1000000)) local MAILBOX_LIMIT_MB=$((POSTFIX_MAILBOX_SIZE_LIMIT / 1000000))
sed -i "s/quota_max_mail_size =.*/quota_max_mail_size = ${message_size_limit_mb}$([[ ${message_size_limit_mb} -eq 0 ]] && echo "" || echo "M")/g" /etc/dovecot/conf.d/90-quota.conf sed -i "s/quota_max_mail_size =.*/quota_max_mail_size = ${MESSAGE_SIZE_LIMIT_MB}$([[ ${MESSAGE_SIZE_LIMIT_MB} -eq 0 ]] && echo "" || echo "M")/g" /etc/dovecot/conf.d/90-quota.conf
sed -i "s/quota_rule = \*:storage=.*/quota_rule = *:storage=${mailbox_limit_mb}$([[ ${mailbox_limit_mb} -eq 0 ]] && echo "" || echo "M")/g" /etc/dovecot/conf.d/90-quota.conf sed -i "s/quota_rule = \*:storage=.*/quota_rule = *:storage=${MAILBOX_LIMIT_MB}$([[ ${MAILBOX_LIMIT_MB} -eq 0 ]] && echo "" || echo "M")/g" /etc/dovecot/conf.d/90-quota.conf
if [[ ! -f /tmp/docker-mailserver/dovecot-quotas.cf ]] if [[ ! -f /tmp/docker-mailserver/dovecot-quotas.cf ]]
then then
@ -843,13 +843,13 @@ function _setup_postfix_postscreen
function _setup_postfix_sizelimits function _setup_postfix_sizelimits
{ {
_notify 'inf' "Configuring postfix message size limit" _notify 'inf' "Configuring postfix message size limit"
postconf -e "message_size_limit = ${DEFAULT_VARS["POSTFIX_MESSAGE_SIZE_LIMIT"]}" postconf -e "message_size_limit = ${POSTFIX_MESSAGE_SIZE_LIMIT}"
_notify 'inf' "Configuring postfix mailbox size limit" _notify 'inf' "Configuring postfix mailbox size limit"
postconf -e "mailbox_size_limit = ${DEFAULT_VARS["POSTFIX_MAILBOX_SIZE_LIMIT"]}" postconf -e "mailbox_size_limit = ${POSTFIX_MAILBOX_SIZE_LIMIT}"
_notify 'inf' "Configuring postfix virtual mailbox size limit" _notify 'inf' "Configuring postfix virtual mailbox size limit"
postconf -e "virtual_mailbox_limit = ${DEFAULT_VARS["POSTFIX_MAILBOX_SIZE_LIMIT"]}" postconf -e "virtual_mailbox_limit = ${POSTFIX_MAILBOX_SIZE_LIMIT}"
} }
function _setup_postfix_smtputf8 function _setup_postfix_smtputf8
@ -909,8 +909,8 @@ function _setup_saslauthd
_notify 'inf' "Configuring Cyrus SASL" _notify 'inf' "Configuring Cyrus SASL"
# checking env vars and setting defaults # checking env vars and setting defaults
[[ -z ${SASLAUTHD_MECHANISMS} ]] && SASLAUTHD_MECHANISMS=pam [[ -z ${SASLAUTHD_MECHANISMS:-} ]] && SASLAUTHD_MECHANISMS=pam
[[ ${SASLAUTHD_MECHANISMS} == ldap ]] && [[ -z ${SASLAUTHD_LDAP_SEARCH_BASE} ]] && SASLAUTHD_MECHANISMS=pam [[ ${SASLAUTHD_MECHANISMS:-} == ldap ]] && [[ -z ${SASLAUTHD_LDAP_SEARCH_BASE} ]] && SASLAUTHD_MECHANISMS=pam
[[ -z ${SASLAUTHD_LDAP_SERVER} ]] && SASLAUTHD_LDAP_SERVER=localhost [[ -z ${SASLAUTHD_LDAP_SERVER} ]] && SASLAUTHD_LDAP_SERVER=localhost
[[ -z ${SASLAUTHD_LDAP_FILTER} ]] && SASLAUTHD_LDAP_FILTER='(&(uniqueIdentifier=%u)(mailEnabled=TRUE))' [[ -z ${SASLAUTHD_LDAP_FILTER} ]] && SASLAUTHD_LDAP_FILTER='(&(uniqueIdentifier=%u)(mailEnabled=TRUE))'
@ -1109,6 +1109,7 @@ function _setup_ssl
_notify 'inf' "TLS configured with 'modern' ciphers" _notify 'inf' "TLS configured with 'modern' ciphers"
;; ;;
"intermediate" ) "intermediate" )
# Postfix configuration # Postfix configuration
sed -i -r 's/^smtpd_tls_mandatory_protocols =.*$/smtpd_tls_mandatory_protocols = !SSLv2,!SSLv3/' /etc/postfix/main.cf sed -i -r 's/^smtpd_tls_mandatory_protocols =.*$/smtpd_tls_mandatory_protocols = !SSLv2,!SSLv3/' /etc/postfix/main.cf
@ -1122,7 +1123,11 @@ function _setup_ssl
_notify 'inf' "TLS configured with 'intermediate' ciphers" _notify 'inf' "TLS configured with 'intermediate' ciphers"
;; ;;
* ) _notify 'err' 'TLS_LEVEL not found _setup_ssl' ;;
* )
_notify 'err' 'TLS_LEVEL not found [ in _setup_ssl ]'
;;
esac esac
# SSL certificate Configuration # SSL certificate Configuration
@ -1265,7 +1270,7 @@ function _setup_ssl
fi fi
;; ;;
'' ) '' )
# ${SSL_TYPE}=empty, no SSL certificate, plain text access # no SSL certificate, plain text access
# Dovecot configuration # Dovecot configuration
sed -i -e 's~#disable_plaintext_auth = yes~disable_plaintext_auth = no~g' /etc/dovecot/conf.d/10-auth.conf sed -i -e 's~#disable_plaintext_auth = yes~disable_plaintext_auth = no~g' /etc/dovecot/conf.d/10-auth.conf
@ -1304,10 +1309,11 @@ function _setup_docker_permit
_notify 'task' 'Setting up PERMIT_DOCKER Option' _notify 'task' 'Setting up PERMIT_DOCKER Option'
local CONTAINER_IP CONTAINER_NETWORK local CONTAINER_IP CONTAINER_NETWORK
unset CONTAINER_NETWORKS unset CONTAINER_NETWORKS
declare -a CONTAINER_NETWORKS declare -a CONTAINER_NETWORKS
CONTAINER_IP=$(ip addr show "${DEFAULT_VARS['NETWORK_INTERFACE']}" | grep 'inet ' | sed 's/[^0-9\.\/]*//g' | cut -d '/' -f 1) CONTAINER_IP=$(ip addr show "${NETWORK_INTERFACE}" | grep 'inet ' | sed 's/[^0-9\.\/]*//g' | cut -d '/' -f 1)
CONTAINER_NETWORK="$(echo "${CONTAINER_IP}" | cut -d '.' -f1-2).0.0" CONTAINER_NETWORK="$(echo "${CONTAINER_IP}" | cut -d '.' -f1-2).0.0"
while read -r IP while read -r IP
@ -1430,35 +1436,7 @@ function _setup_postfix_relay_hosts
{ {
_notify 'task' 'Setting up Postfix Relay Hosts' _notify 'task' 'Setting up Postfix Relay Hosts'
# copy old AWS_SES variables to new variables [[ -z ${RELAY_PORT} ]] && RELAY_PORT=25
if [[ -z ${RELAY_HOST} ]]
then
if [[ -n ${AWS_SES_HOST} ]]
then
_notify 'inf' "Using deprecated AWS_SES environment variables"
RELAY_HOST="${AWS_SES_HOST}"
fi
fi
if [[ -z ${RELAY_PORT} ]]
then
if [[ -z ${AWS_SES_PORT} ]]
then
RELAY_PORT=25
else
RELAY_PORT=${AWS_SES_PORT}
fi
fi
if [[ -z ${RELAY_USER} ]]
then
if [[ -n ${AWS_SES_USERPASS} ]]
then
# NB this will fail if the password contains a colon!
RELAY_USER=$(echo "${AWS_SES_USERPASS}" | cut -f 1 -d ":")
RELAY_PASSWORD=$(echo "${AWS_SES_USERPASS}" | cut -f 2 -d ":")
fi
fi
_notify 'inf' "Setting up outgoing email relaying via ${RELAY_HOST}:${RELAY_PORT}" _notify 'inf' "Setting up outgoing email relaying via ${RELAY_HOST}:${RELAY_PORT}"
@ -1676,7 +1654,7 @@ function _setup_security_stack
sed -i "s/\$final_spam_destiny.*=.*$/\$final_spam_destiny = D_BOUNCE;/g" /etc/amavis/conf.d/49-docker-mailserver sed -i "s/\$final_spam_destiny.*=.*$/\$final_spam_destiny = D_BOUNCE;/g" /etc/amavis/conf.d/49-docker-mailserver
sed -i "s/\$final_bad_header_destiny.*=.*$/\$final_bad_header_destiny = D_BOUNCE;/g" /etc/amavis/conf.d/49-docker-mailserver sed -i "s/\$final_bad_header_destiny.*=.*$/\$final_bad_header_destiny = D_BOUNCE;/g" /etc/amavis/conf.d/49-docker-mailserver
if [[ ${DEFAULT_VARS['EXPLICITLY_DEFINED_SPAMASSASSIN_SPAM_TO_INBOX']} == "0" ]] if ! ${SPAMASSASSIN_SPAM_TO_INBOX_IS_SET}
then then
_notify 'warn' "Spam messages WILL NOT BE DELIVERED, you will NOT be notified of ANY message bounced. Please define SPAMASSASSIN_SPAM_TO_INBOX explicitly." _notify 'warn' "Spam messages WILL NOT BE DELIVERED, you will NOT be notified of ANY message bounced. Please define SPAMASSASSIN_SPAM_TO_INBOX explicitly."
fi fi
@ -1799,7 +1777,7 @@ function _setup_logwatch
esac esac
} }
function _setup_user_patches() function _setup_user_patches
{ {
if [[ -f /tmp/docker-mailserver/user-patches.sh ]] if [[ -f /tmp/docker-mailserver/user-patches.sh ]]
then then
@ -1818,16 +1796,16 @@ function _setup_user_patches()
fi fi
} }
function _setup_environment() { function _setup_environment
{
_notify 'task' 'Setting up /etc/environment' _notify 'task' 'Setting up /etc/environment'
local banner="# docker environment" local BANNER="# Docker Environment"
local var
if ! grep -q "${banner}" /etc/environment if ! grep -q "${BANNER}" /etc/environment
then then
echo "${banner}" >> /etc/environment echo "${BANNER}" >> /etc/environment
echo "VIRUSMAILS_DELETE_DELAY=${DEFAULT_VARS["VIRUSMAILS_DELETE_DELAY"]}" >> /etc/environment echo "VIRUSMAILS_DELETE_DELAY=${VIRUSMAILS_DELETE_DELAY}" >> /etc/environment
fi fi
} }
@ -1924,7 +1902,7 @@ function _fix_cleanup_spamassassin
function misc function misc
{ {
_notify 'taskgrp' 'Starting Misc' _notify 'tasklog' 'Startin misc'
for FUNC in "${FUNCS_MISC[@]}" for FUNC in "${FUNCS_MISC[@]}"
do do
@ -1992,7 +1970,7 @@ function _misc_save_states
function start_daemons function start_daemons
{ {
_notify 'taskgrp' 'Starting mail server' _notify 'tasklog' 'Starting mail server'
for FUNC in "${DAEMONS_START[@]}" for FUNC in "${DAEMONS_START[@]}"
do do
@ -2129,32 +2107,25 @@ function _start_changedetector
supervisorctl start changedetector supervisorctl start changedetector
} }
# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! # !
# ! CARE --> DON'T CHANGE, unless you exactly know what you are doing # ! CARE BEGIN
# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! # !
# shellcheck source=./helper-functions.sh # shellcheck source=./helper-functions.sh
. /usr/local/bin/helper-functions.sh . /usr/local/bin/helper-functions.sh
if [[ ${DEFAULT_VARS["DMS_DEBUG"]} -eq 1 ]] if [[ ${DMS_DEBUG:-0} -eq 1 ]]
then then
_notify 'taskgrp' "" _notify 'none'
_notify 'taskgrp' "#" _notify 'tasklog' 'ENVIRONMENT'
_notify 'taskgrp' "#" _notify 'none'
_notify 'taskgrp' "# ENV"
_notify 'taskgrp' "#"
_notify 'taskgrp' "#"
_notify 'taskgrp' ""
printenv printenv
fi fi
_notify 'taskgrp' "" _notify 'none'
_notify 'taskgrp' "#" _notify 'tasklog' 'Welcome to docker-mailserver!'
_notify 'taskgrp' "#" _notify 'none'
_notify 'taskgrp' "# docker-mailserver"
_notify 'taskgrp' "#"
_notify 'taskgrp' "#"
_notify 'taskgrp' ""
register_functions register_functions
@ -2164,17 +2135,15 @@ fix
misc misc
start_daemons start_daemons
_notify 'taskgrp' "" _notify 'none'
_notify 'taskgrp' "#" _notify 'tasklog' "${HOSTNAME} is up and running"
_notify 'taskgrp' "# ${HOSTNAME} is up and running" _notify 'none'
_notify 'taskgrp' "#"
_notify 'taskgrp' ""
touch /var/log/mail/mail.log touch /var/log/mail/mail.log
tail -fn 0 /var/log/mail/mail.log tail -fn 0 /var/log/mail/mail.log
# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! # !
# ! CARE --> DON'T CHANGE, unless you exactly know what you are doing # ! CARE END
# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! # !
exit 0 exit 0

@ -1 +1 @@
Subproject commit 03608115df2071fff4eaaff1605768c275e5f81f Subproject commit dcaec03e32e0b152f8ef9cf14b75296cf5caeaff

View File

@ -2,8 +2,8 @@ load 'test_helper/bats-support/load'
load 'test_helper/bats-assert/load' load 'test_helper/bats-assert/load'
# load the helper function into current context # load the helper function into current context
# shellcheck source=../target/helper-functions.sh # shellcheck source=../target/scripts/helper-functions.sh
. ./target/helper-functions.sh . ./target/scripts/helper-functions.sh
@test "check helper function: _sanitize_ipv4_to_subnet_cidr" { @test "check helper function: _sanitize_ipv4_to_subnet_cidr" {
output=$(_sanitize_ipv4_to_subnet_cidr 255.255.255.255/0) output=$(_sanitize_ipv4_to_subnet_cidr 255.255.255.255/0)

View File

@ -1,5 +1,8 @@
ignored: ignored:
# disable explicit version for apt install
- DL3008 - DL3008
- DL3015
trustedRegistries: trustedRegistries:
- docker.io - docker.io
- quay.io
- ghcr.io

View File

@ -1,7 +1,7 @@
#! /bin/bash #! /bin/bash
# version v0.1.2 stable # version v0.1.3 stable
# executed by TravisCI / manually # executed by CI / manually (via Make)
# task checks files agains linting targets # task checks files agains linting targets
SCRIPT="lint.sh" SCRIPT="lint.sh"
@ -10,7 +10,7 @@ function _get_current_directory
{ {
if dirname "$(readlink -f "${0}")" &>/dev/null if dirname "$(readlink -f "${0}")" &>/dev/null
then then
CDIR="$(cd "$(dirname "$(readlink -f "${0}")")" && pwd)" CDIR="$(dirname "$(readlink -f "${0}")")"
elif realpath -e -L "${0}" &>/dev/null elif realpath -e -L "${0}" &>/dev/null
then then
CDIR="$(realpath -e -L "${0}")" CDIR="$(realpath -e -L "${0}")"
@ -188,13 +188,13 @@ function _shellcheck
function _main function _main
{ {
case ${1:- } in case ${1:-} in
'eclint' ) _eclint ;; 'eclint' ) _eclint ;;
'hadolint' ) _hadolint ;; 'hadolint' ) _hadolint ;;
'shellcheck' ) _shellcheck ;; 'shellcheck' ) _shellcheck ;;
*) *)
__log_failure \ __log_failure \
"${SCRIPT}: '${1}' is not a command nor an option. See 'make help'." "${SCRIPT}: '${1}' is not a command nor an option."
exit 3 exit 3
;; ;;
esac esac

View File

@ -18,7 +18,7 @@ function setup_file() {
-e POSTGREY_DELAY=15 \ -e POSTGREY_DELAY=15 \
-e POSTGREY_MAX_AGE=35 \ -e POSTGREY_MAX_AGE=35 \
-e POSTGREY_AUTO_WHITELIST_CLIENTS=5 \ -e POSTGREY_AUTO_WHITELIST_CLIENTS=5 \
-e POSTGREY_TEXT="Delayed by postgrey" \ -e POSTGREY_TEXT="Delayed by Postgrey" \
-e DMS_DEBUG=0 \ -e DMS_DEBUG=0 \
-h mail.my-domain.com -t "${NAME}" -h mail.my-domain.com -t "${NAME}"
# using postfix availability as start indicator, this might be insufficient for postgrey # using postfix availability as start indicator, this might be insufficient for postgrey
@ -43,7 +43,7 @@ function teardown_file() {
run docker exec mail_with_postgrey /bin/bash -c "grep '^POSTGREY_OPTS=\"--inet=127.0.0.1:10023 --delay=15 --max-age=35 --auto-whitelist-clients=5\"$' /etc/default/postgrey | wc -l" run docker exec mail_with_postgrey /bin/bash -c "grep '^POSTGREY_OPTS=\"--inet=127.0.0.1:10023 --delay=15 --max-age=35 --auto-whitelist-clients=5\"$' /etc/default/postgrey | wc -l"
assert_success assert_success
assert_output 1 assert_output 1
run docker exec mail_with_postgrey /bin/bash -c "grep '^POSTGREY_TEXT=\"Delayed by postgrey\"$' /etc/default/postgrey | wc -l" run docker exec mail_with_postgrey /bin/bash -c "grep '^POSTGREY_TEXT=\"Delayed by Postgrey\"$' /etc/default/postgrey | wc -l"
assert_success assert_success
assert_output 1 assert_output 1
} }

View File

@ -3,8 +3,7 @@
load 'test_helper/bats-support/load' load 'test_helper/bats-support/load'
load 'test_helper/bats-assert/load' load 'test_helper/bats-assert/load'
# shellcheck disable=SC2034 NAME=${NAME:-'docker.io/mailserver/testing:latest'}
NAME=tvial/docker-mailserver:testing
# default timeout is 120 seconds # default timeout is 120 seconds
TEST_TIMEOUT_IN_SECONDS=${TEST_TIMEOUT_IN_SECONDS-120} TEST_TIMEOUT_IN_SECONDS=${TEST_TIMEOUT_IN_SECONDS-120}
@ -180,6 +179,7 @@ function wait_for_service() {
function wait_for_changes_to_be_detected_in_container() { function wait_for_changes_to_be_detected_in_container() {
local CONTAINER_NAME="${1}" local CONTAINER_NAME="${1}"
local TIMEOUT=${TEST_TIMEOUT_IN_SECONDS} local TIMEOUT=${TEST_TIMEOUT_IN_SECONDS}
# shellcheck disable=SC2016 # shellcheck disable=SC2016
repeat_in_container_until_success_or_timeout "${TIMEOUT}" "${CONTAINER_NAME}" bash -c 'source /usr/local/bin/helper-functions.sh; cmp --silent -- <(_monitored_files_checksums) "${CHKSUM_FILE}" >/dev/null' repeat_in_container_until_success_or_timeout "${TIMEOUT}" "${CONTAINER_NAME}" bash -c 'source /usr/local/bin/helper-functions.sh; cmp --silent -- <(_monitored_files_checksums) "${CHKSUM_FILE}" >/dev/null'
} }
@ -187,5 +187,7 @@ function wait_for_changes_to_be_detected_in_container() {
function wait_for_empty_mail_queue_in_container() { function wait_for_empty_mail_queue_in_container() {
local CONTAINER_NAME="${1}" local CONTAINER_NAME="${1}"
local TIMEOUT=${TEST_TIMEOUT_IN_SECONDS} local TIMEOUT=${TEST_TIMEOUT_IN_SECONDS}
# shellcheck disable=SC2016
repeat_in_container_until_success_or_timeout "${TIMEOUT}" "${CONTAINER_NAME}" bash -c '[[ $(mailq) == *"Mail queue is empty"* ]]' repeat_in_container_until_success_or_timeout "${TIMEOUT}" "${CONTAINER_NAME}" bash -c '[[ $(mailq) == *"Mail queue is empty"* ]]'
} }

View File

@ -1138,7 +1138,7 @@ EOF
# dovecot and postfix has been restarted # dovecot and postfix has been restarted
wait_for_service mail postfix wait_for_service mail postfix
wait_for_service mail dovecot wait_for_service mail dovecot
sleep 5 sleep 10
# send some big emails # send some big emails
run docker exec mail /bin/sh -c "nc 0.0.0.0 25 < /tmp/docker-mailserver-test/email-templates/quota-exceeded.txt" run docker exec mail /bin/sh -c "nc 0.0.0.0 25 < /tmp/docker-mailserver-test/email-templates/quota-exceeded.txt"
@ -1151,6 +1151,7 @@ EOF
# check for quota warn message existence # check for quota warn message existence
run repeat_until_success_or_timeout 20 sh -c "docker exec mail sh -c 'grep \"Subject: quota warning\" /var/mail/otherdomain.tld/quotauser/new/ -R'" run repeat_until_success_or_timeout 20 sh -c "docker exec mail sh -c 'grep \"Subject: quota warning\" /var/mail/otherdomain.tld/quotauser/new/ -R'"
assert_success assert_success
run repeat_until_success_or_timeout 20 sh -c "docker logs mail | grep 'Quota exceeded (mailbox for user is full)'" run repeat_until_success_or_timeout 20 sh -c "docker logs mail | grep 'Quota exceeded (mailbox for user is full)'"
assert_success assert_success
@ -1411,7 +1412,7 @@ EOF
@test "checking setup.sh: setup.sh debug inspect" { @test "checking setup.sh: setup.sh debug inspect" {
run ./setup.sh -c mail debug inspect run ./setup.sh -c mail debug inspect
assert_success assert_success
assert_line --index 0 "Image: tvial/docker-mailserver:testing" assert_line --index 0 "Image: ${NAME}"
assert_line --index 1 "Container: mail" assert_line --index 1 "Container: mail"
} }
@test "checking setup.sh: setup.sh debug login ls" { @test "checking setup.sh: setup.sh debug login ls" {