Merge branch 'master' into mta-sts-support
This commit is contained in:
commit
cef26a9d59
|
@ -20,9 +20,8 @@
|
||||||
|
|
||||||
## BUILD:
|
## BUILD:
|
||||||
.dockerignore text
|
.dockerignore text
|
||||||
Dockerfile text
|
Dockerfile text eol=lf
|
||||||
Makefile
|
Makefile
|
||||||
VERSION
|
|
||||||
|
|
||||||
## EXAMPLE (RUNTIME):
|
## EXAMPLE (RUNTIME):
|
||||||
*.env text
|
*.env text
|
||||||
|
@ -75,8 +74,8 @@ target/postsrsd/** text
|
||||||
#################################################
|
#################################################
|
||||||
|
|
||||||
## BATS
|
## BATS
|
||||||
*.bash text
|
*.bash text eol=lf
|
||||||
*.bats text
|
*.bats text eol=lf
|
||||||
|
|
||||||
## CONFIG (test/config/)
|
## CONFIG (test/config/)
|
||||||
### OpenLDAP image
|
### OpenLDAP image
|
||||||
|
|
|
@ -23,7 +23,7 @@ jobs:
|
||||||
|
|
||||||
- name: 'Prepare tags'
|
- name: 'Prepare tags'
|
||||||
id: prep
|
id: prep
|
||||||
uses: docker/metadata-action@v5.4.0
|
uses: docker/metadata-action@v5.5.0
|
||||||
with:
|
with:
|
||||||
images: |
|
images: |
|
||||||
${{ secrets.DOCKER_REPOSITORY }}
|
${{ secrets.DOCKER_REPOSITORY }}
|
||||||
|
|
|
@ -55,7 +55,7 @@ jobs:
|
||||||
provenance: false
|
provenance: false
|
||||||
|
|
||||||
- name: 'Run the Anchore Grype scan action'
|
- name: 'Run the Anchore Grype scan action'
|
||||||
uses: anchore/scan-action@v3.3.8
|
uses: anchore/scan-action@v3.4.0
|
||||||
id: scan
|
id: scan
|
||||||
with:
|
with:
|
||||||
image: mailserver-testing:ci
|
image: mailserver-testing:ci
|
||||||
|
|
26
CHANGELOG.md
26
CHANGELOG.md
|
@ -2,13 +2,33 @@
|
||||||
|
|
||||||
All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
## [Unreleased](https://github.com/docker-mailserver/docker-mailserver/compare/v13.1.0...HEAD)
|
## [Unreleased](https://github.com/docker-mailserver/docker-mailserver/compare/v13.2.0...HEAD)
|
||||||
|
|
||||||
> **Note**: Changes and additions listed here are contained in the `:edge` image tag. These changes may not be as stable as released changes.
|
> **Note**: Changes and additions listed here are contained in the `:edge` image tag. These changes may not be as stable as released changes.
|
||||||
|
|
||||||
|
### Updates
|
||||||
|
|
||||||
|
- **Internal:**
|
||||||
|
- tests: Replace `wc -l` with `grep -c` ([#3752](https://github.com/docker-mailserver/docker-mailserver/pull/3752))
|
||||||
|
- Postfix is now configured with `smtputf8_enable = no` in our default `main.cf` config (_instead of during container startup_). ([#3750](https://github.com/docker-mailserver/docker-mailserver/pull/3750))
|
||||||
|
- **Rspamd** ([#3726](https://github.com/docker-mailserver/docker-mailserver/pull/3726)):
|
||||||
|
- symbol scores for SPF, DKIM & DMARC were updated to more closely align with [RFC7489](https://www.rfc-editor.org/rfc/rfc7489#page-24); please note though that complete alignment is undesirable, because other symbols might be added as well, which changes the overall score calculation again, see [this issue](https://github.com/docker-mailserver/docker-mailserver/issues/3690#issuecomment-1866871996)
|
||||||
|
- **Docs:**
|
||||||
|
- Revised the SpamAssassin ENV docs to better communicate configuration and their relation to other ENV settings. ([#3756](https://github.com/docker-mailserver/docker-mailserver/pull/3756))
|
||||||
|
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
|
||||||
|
- **Internal:**
|
||||||
|
- `.gitattributes`: Always use LF line endings on checkout for files with shell script content ([#3755](https://github.com/docker-mailserver/docker-mailserver/pull/3755))
|
||||||
|
- Fix missing 'jaq' binary for ARM architecture ([#3766](https://github.com/docker-mailserver/docker-mailserver/pull/3766))
|
||||||
|
|
||||||
|
## [v13.2.0](https://github.com/docker-mailserver/docker-mailserver/releases/tag/v13.2.0)
|
||||||
|
|
||||||
### Security
|
### Security
|
||||||
|
|
||||||
DMS is now secured against the [recently published spoofing attack "SMTP Smuggling"](https://www.postfix.org/smtp-smuggling.html) that affected Postfix ([#3727](https://github.com/docker-mailserver/docker-mailserver/pull/3727)):
|
DMS is now secured against the [recently published spoofing attack "SMTP Smuggling"](https://www.postfix.org/smtp-smuggling.html) that affected Postfix ([#3727](https://github.com/docker-mailserver/docker-mailserver/pull/3727)):
|
||||||
|
|
||||||
- Postfix upgraded from `3.5.18` to `3.5.23` which provides the [long-term fix with `smtpd_forbid_bare_newline = yes`](https://www.postfix.org/smtp-smuggling.html#long)
|
- Postfix upgraded from `3.5.18` to `3.5.23` which provides the [long-term fix with `smtpd_forbid_bare_newline = yes`](https://www.postfix.org/smtp-smuggling.html#long)
|
||||||
- If you are unable to upgrade to this release of DMS, you may follow [these instructions](https://github.com/docker-mailserver/docker-mailserver/issues/3719#issuecomment-1870865118) for applying the [short-term workaround](https://www.postfix.org/smtp-smuggling.html#short).
|
- If you are unable to upgrade to this release of DMS, you may follow [these instructions](https://github.com/docker-mailserver/docker-mailserver/issues/3719#issuecomment-1870865118) for applying the [short-term workaround](https://www.postfix.org/smtp-smuggling.html#short).
|
||||||
- This change should not cause compatibility concerns for legitimate mail clients, however if you use software like `netcat` to send mail to DMS (_like our test-suite previously did_) it may now be rejected (_especially with the the short-term workaround `smtpd_data_restrictions = reject_unauth_pipelining`_).
|
- This change should not cause compatibility concerns for legitimate mail clients, however if you use software like `netcat` to send mail to DMS (_like our test-suite previously did_) it may now be rejected (_especially with the the short-term workaround `smtpd_data_restrictions = reject_unauth_pipelining`_).
|
||||||
|
@ -25,6 +45,10 @@ DMS is now secured against the [recently published spoofing attack "SMTP Smuggli
|
||||||
- `swaks` handles pipelining correctly, hence we can now use `reject_unauth_pipelining` in Postfix's configuration.
|
- `swaks` handles pipelining correctly, hence we can now use `reject_unauth_pipelining` in Postfix's configuration.
|
||||||
- `swaks` provides better CLI options that make many files superflous.
|
- `swaks` provides better CLI options that make many files superflous.
|
||||||
- `swaks` can also replace `openssl s_client` and handles authentication on submission ports better.
|
- `swaks` can also replace `openssl s_client` and handles authentication on submission ports better.
|
||||||
|
- **Postfix:**
|
||||||
|
- We now defer rejection from unauthorized pipelining until the SMTP `DATA` command via `smtpd_data_restrictions` (_i.e. at the end of the mail transfer transaction_) ([#3744](https://github.com/docker-mailserver/docker-mailserver/pull/3744))
|
||||||
|
- Prevously our configuration only handled this during the client and recipient restriction stages. Postfix will flag this activity when encountered, but the rejection now is handled at `DATA` where unauthorized pipelining would have been valid from this point.
|
||||||
|
- If you had the Amavis service enabled (default), this restriction was already in place. Otherwise the concerns expressed with `smtpd_data_restrictions = reject_unauth_pipelining` from the security section above apply. We have permitted trusted clients (_`$mynetworks` or authenticated_) to bypass this restriction.
|
||||||
|
|
||||||
## [v13.1.0](https://github.com/docker-mailserver/docker-mailserver/releases/tag/v13.1.0)
|
## [v13.1.0](https://github.com/docker-mailserver/docker-mailserver/releases/tag/v13.1.0)
|
||||||
|
|
||||||
|
|
2108
CONTRIBUTORS.md
2108
CONTRIBUTORS.md
File diff suppressed because it is too large
Load Diff
|
@ -106,6 +106,7 @@ EOF
|
||||||
# -----------------------------------------------
|
# -----------------------------------------------
|
||||||
|
|
||||||
COPY target/rspamd/local.d/ /etc/rspamd/local.d/
|
COPY target/rspamd/local.d/ /etc/rspamd/local.d/
|
||||||
|
COPY target/rspamd/scores.d/* /etc/rspamd/scores.d/
|
||||||
|
|
||||||
# -----------------------------------------------
|
# -----------------------------------------------
|
||||||
# --- LDAP & SpamAssassin's Cron ----------------
|
# --- LDAP & SpamAssassin's Cron ----------------
|
||||||
|
@ -327,7 +328,7 @@ LABEL org.opencontainers.image.title="docker-mailserver"
|
||||||
LABEL org.opencontainers.image.vendor="The Docker Mailserver Organization"
|
LABEL org.opencontainers.image.vendor="The Docker Mailserver Organization"
|
||||||
LABEL org.opencontainers.image.authors="The Docker Mailserver Organization on GitHub"
|
LABEL org.opencontainers.image.authors="The Docker Mailserver Organization on GitHub"
|
||||||
LABEL org.opencontainers.image.licenses="MIT"
|
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.description="A fullstack but simple mail server (SMTP, IMAP, LDAP, Anti-spam, Anti-virus, etc.). Only configuration files, no SQL database."
|
||||||
LABEL org.opencontainers.image.url="https://github.com/docker-mailserver"
|
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.documentation="https://github.com/docker-mailserver/docker-mailserver/blob/master/README.md"
|
||||||
LABEL org.opencontainers.image.source="https://github.com/docker-mailserver/docker-mailserver"
|
LABEL org.opencontainers.image.source="https://github.com/docker-mailserver/docker-mailserver"
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
|
|
||||||
## :page_with_curl: About
|
## :page_with_curl: About
|
||||||
|
|
||||||
A production-ready fullstack but simple containerized mail server (SMTP, IMAP, LDAP, Antispam, Antivirus, etc.). Only configuration files, no SQL database. Keep it simple and versioned. Easy to deploy and upgrade. Originally created by @tomav, this project is now maintained by volunteers since January 2021.
|
A production-ready fullstack but simple containerized mail server (SMTP, IMAP, LDAP, Anti-spam, Anti-virus, etc.). Only configuration files, no SQL database. Keep it simple and versioned. Easy to deploy and upgrade. Originally created by @tomav, this project is now maintained by volunteers since January 2021.
|
||||||
|
|
||||||
## :bulb: Documentation
|
## :bulb: Documentation
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,7 @@ This is a list of all configuration files and directories which are optional or
|
||||||
- **ldap-aliases.cf:** Configuration for the virtual alias mapping `virtual_alias_maps`. See the [`setup-stack.sh`][github-commit-setup-stack.sh-L411] script.
|
- **ldap-aliases.cf:** Configuration for the virtual alias mapping `virtual_alias_maps`. See the [`setup-stack.sh`][github-commit-setup-stack.sh-L411] script.
|
||||||
- **ldap-domains.cf:** Configuration for the virtual domain mapping `virtual_mailbox_domains`. See the [`setup-stack.sh`][github-commit-setup-stack.sh-L411] script.
|
- **ldap-domains.cf:** Configuration for the virtual domain mapping `virtual_mailbox_domains`. See the [`setup-stack.sh`][github-commit-setup-stack.sh-L411] script.
|
||||||
- **whitelist_clients.local:** Whitelisted domains, not considered by postgrey. Enter one host or domain per line.
|
- **whitelist_clients.local:** Whitelisted domains, not considered by postgrey. Enter one host or domain per line.
|
||||||
- **spamassassin-rules.cf:** Antispam rules for Spamassassin. (Docs: [FAQ - SpamAssassin Rules][docs-faq-spamrules])
|
- **spamassassin-rules.cf:** Anti-spam rules for Spamassassin. (Docs: [FAQ - SpamAssassin Rules][docs-faq-spamrules])
|
||||||
- **fail2ban-fail2ban.cf:** Additional config options for `fail2ban.cf`. (Docs: [Fail2Ban][docs-fail2ban])
|
- **fail2ban-fail2ban.cf:** Additional config options for `fail2ban.cf`. (Docs: [Fail2Ban][docs-fail2ban])
|
||||||
- **fail2ban-jail.cf:** Additional config options for fail2ban's jail behaviour. (Docs: [Fail2Ban][docs-fail2ban])
|
- **fail2ban-jail.cf:** Additional config options for fail2ban's jail behaviour. (Docs: [Fail2Ban][docs-fail2ban])
|
||||||
- **amavis.cf:** replaces the `/etc/amavis/conf.d/50-user` file
|
- **amavis.cf:** replaces the `/etc/amavis/conf.d/50-user` file
|
||||||
|
|
|
@ -325,28 +325,32 @@ Note: More information at <https://dovecot.org/doc/dovecot-example.conf>
|
||||||
|
|
||||||
##### MOVE_SPAM_TO_JUNK
|
##### MOVE_SPAM_TO_JUNK
|
||||||
|
|
||||||
When enabled, e-mails marked with the
|
|
||||||
|
|
||||||
1. `X-Spam: Yes` header added by Rspamd
|
|
||||||
2. `X-Spam-Flag: YES` header added by SpamAssassin (requires [`SPAMASSASSIN_SPAM_TO_INBOX=1`](#spamassassin_spam_to_inbox))
|
|
||||||
|
|
||||||
will be automatically moved to the Junk folder (with the help of a Sieve script).
|
|
||||||
|
|
||||||
- 0 => Spam messages will be delivered in the mailbox.
|
- 0 => Spam messages will be delivered in the mailbox.
|
||||||
- **1** => Spam messages will be delivered in the `Junk` folder.
|
- **1** => Spam messages will be delivered in the `Junk` folder.
|
||||||
|
|
||||||
|
Routes mail identified as spam into the recipient(s) Junk folder (_via a Dovecot Sieve script_).
|
||||||
|
|
||||||
|
!!! info
|
||||||
|
|
||||||
|
Mail is received as spam when it has been marked with either header:
|
||||||
|
|
||||||
|
- `X-Spam: Yes` (_added by Rspamd_)
|
||||||
|
- `X-Spam-Flag: YES` (_added by SpamAssassin - requires [`SPAMASSASSIN_SPAM_TO_INBOX=1`](#spamassassin_spam_to_inbox)_)
|
||||||
|
|
||||||
##### MARK_SPAM_AS_READ
|
##### MARK_SPAM_AS_READ
|
||||||
|
|
||||||
Enable to treat received spam as "read" (_avoids notification to MUA client of new mail_).
|
|
||||||
|
|
||||||
Mail is received as spam when it has been marked with either header:
|
|
||||||
|
|
||||||
1. `X-Spam: Yes` (_by Rspamd_)
|
|
||||||
2. `X-Spam-Flag: YES` (_by SpamAssassin - requires [`SPAMASSASSIN_SPAM_TO_INBOX=1`](#spamassassin_spam_to_inbox)_)
|
|
||||||
|
|
||||||
- **0** => disabled
|
- **0** => disabled
|
||||||
- 1 => Spam messages will be marked as read
|
- 1 => Spam messages will be marked as read
|
||||||
|
|
||||||
|
Enable to treat received spam as "read" (_avoids notification to MUA client of new mail_).
|
||||||
|
|
||||||
|
!!! info
|
||||||
|
|
||||||
|
Mail is received as spam when it has been marked with either header:
|
||||||
|
|
||||||
|
- `X-Spam: Yes` (_added by Rspamd_)
|
||||||
|
- `X-Spam-Flag: YES` (_added by SpamAssassin - requires [`SPAMASSASSIN_SPAM_TO_INBOX=1`](#spamassassin_spam_to_inbox)_)
|
||||||
|
|
||||||
#### Rspamd
|
#### Rspamd
|
||||||
|
|
||||||
##### ENABLE_RSPAMD
|
##### ENABLE_RSPAMD
|
||||||
|
@ -524,63 +528,170 @@ Changes the interval in which log files are rotated.
|
||||||
- **0** => SpamAssassin is disabled
|
- **0** => SpamAssassin is disabled
|
||||||
- 1 => SpamAssassin is enabled
|
- 1 => SpamAssassin is enabled
|
||||||
|
|
||||||
##### SPAMASSASSIN_SPAM_TO_INBOX
|
??? info "SpamAssassin analyzes incoming mail and assigns a spam score"
|
||||||
|
|
||||||
- 0 => Spam messages will be bounced (_rejected_) without any notification (_dangerous_).
|
Integration with Amavis involves processing mail based on the assigned spam score via [`SA_TAG`, `SA_TAG2` and `SA_KILL`][amavis-docs::spam-score].
|
||||||
- **1** => Spam messages will be delivered to the inbox and tagged as spam using `SA_SPAM_SUBJECT`.
|
|
||||||
|
These settings have equivalent ENV supported by DMS for easy adjustments, as documented below.
|
||||||
|
|
||||||
|
[amavis-docs::spam-score]: https://www.ijs.si/software/amavisd/amavisd-new-docs.html#tagkill
|
||||||
|
|
||||||
##### ENABLE_SPAMASSASSIN_KAM
|
##### ENABLE_SPAMASSASSIN_KAM
|
||||||
|
|
||||||
[KAM](https://mcgrail.com/template/projects#KAM1) is a 3rd party SpamAssassin ruleset, provided by the McGrail Foundation. If SpamAssassin is enabled, KAM can be used in addition to the default ruleset.
|
|
||||||
|
|
||||||
- **0** => KAM disabled
|
- **0** => KAM disabled
|
||||||
- 1 => KAM enabled
|
- 1 => KAM enabled
|
||||||
|
|
||||||
|
[KAM](https://mcgrail.com/template/projects#KAM1) is a 3rd party SpamAssassin ruleset, provided by the McGrail Foundation. If SpamAssassin is enabled, KAM can be used in addition to the default ruleset.
|
||||||
|
|
||||||
|
##### SPAMASSASSIN_SPAM_TO_INBOX
|
||||||
|
|
||||||
|
- 0 => (_Amavis action: `D_BOUNCE`_): Spam messages will be bounced (_rejected_) without any notification (_dangerous_).
|
||||||
|
- **1** => (_Amavis action: `D_PASS`_): Spam messages will be delivered to the inbox.
|
||||||
|
|
||||||
|
!!! note
|
||||||
|
|
||||||
|
The Amavis action configured by this setting:
|
||||||
|
|
||||||
|
- Influences the behaviour of the [`SA_KILL`](#sa_kill) setting.
|
||||||
|
- Applies to the Amavis config parameters `$final_spam_destiny` and `$final_bad_header_destiny`.
|
||||||
|
|
||||||
|
!!! note "This ENV setting is related to"
|
||||||
|
|
||||||
|
- [`MOVE_SPAM_TO_JUNK=1`](#move_spam_to_junk)
|
||||||
|
- [`MARK_SPAM_AS_READ=1`](#mark_spam_as_read)
|
||||||
|
- [`SA_SPAM_SUBJECT`](#sa_spam_subject)
|
||||||
|
|
||||||
##### SA_TAG
|
##### SA_TAG
|
||||||
|
|
||||||
- **2.0** => add spam info headers if at, or above that level
|
- **2.0** => add 'spam info' headers at, or above this spam score
|
||||||
|
|
||||||
Note: this SpamAssassin setting needs `ENABLE_SPAMASSASSIN=1`
|
Mail is not yet considered spam at this spam score, but for purposes like diagnostics it can be useful to identify mail with a spam score at a lower bound than `SA_TAG2`.
|
||||||
|
|
||||||
|
??? example "`X-Spam` headers appended to mail"
|
||||||
|
|
||||||
|
Send a simple mail to a local DMS account `hello@example.com`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker exec dms swaks --server 0.0.0.0 --to hello@example.com --body 'spam'
|
||||||
|
```
|
||||||
|
|
||||||
|
Inspecting the raw mail you will notice several `X-Spam` headers were added to the mail like this:
|
||||||
|
|
||||||
|
```
|
||||||
|
X-Spam-Flag: NO
|
||||||
|
X-Spam-Score: 4.162
|
||||||
|
X-Spam-Level: ****
|
||||||
|
X-Spam-Status: No, score=4.162 tagged_above=2 required=4
|
||||||
|
tests=[BODY_SINGLE_WORD=1, DKIM_ADSP_NXDOMAIN=0.8,
|
||||||
|
NO_DNS_FOR_FROM=0.379, NO_RECEIVED=-0.001, NO_RELAYS=-0.001,
|
||||||
|
PYZOR_CHECK=1.985] autolearn=no autolearn_force=no
|
||||||
|
```
|
||||||
|
|
||||||
|
!!! info "The `X-Spam-Score` is `4.162`"
|
||||||
|
|
||||||
|
High enough for `SA_TAG` to trigger adding these headers, but not high enough for `SA_TAG2` (_which would set `X-Spam-Flag: YES` instead_).
|
||||||
|
|
||||||
##### SA_TAG2
|
##### SA_TAG2
|
||||||
|
|
||||||
- **6.31** => add 'spam detected' headers at that level
|
- **6.31** => add 'spam detected' headers at, or above this level
|
||||||
|
|
||||||
Note: this SpamAssassin setting needs `ENABLE_SPAMASSASSIN=1`
|
When a spam score is high enough, mark mail as spam (_Appends the mail header: `X-Spam-Flag: YES`_).
|
||||||
|
|
||||||
|
!!! info "Interaction with other ENV"
|
||||||
|
|
||||||
|
- [`SA_SPAM_SUBJECT`](#sa_spam_subject) modifies the mail subject to better communicate spam mail to the user.
|
||||||
|
- [`MOVE_SPAM_TO_JUNK=1`](#move_spam_to_junk): The mail is still delivered, but to the recipient(s) junk folder instead. This feature reduces the usefulness of `SA_SPAM_SUBJECT`.
|
||||||
|
|
||||||
##### SA_KILL
|
##### SA_KILL
|
||||||
|
|
||||||
- **10.0** => triggers spam evasive actions
|
- **10.0** => quarantine + triggers action to handle spam
|
||||||
|
|
||||||
!!! note "This SpamAssassin setting needs `ENABLE_SPAMASSASSIN=1`"
|
Controls the spam score threshold for triggering an action on mail that has a high spam score.
|
||||||
|
|
||||||
By default, DMS is configured to quarantine spam emails.
|
??? tip "Choosing an appropriate `SA_KILL` value"
|
||||||
|
|
||||||
If emails are quarantined, they are compressed and stored in a location dependent on the `ONE_DIR` setting above. To inhibit this behaviour and deliver spam emails, set this to a very high value e.g. `100.0`.
|
The value should be high enough to be represent confidence in mail as spam:
|
||||||
|
|
||||||
If `ONE_DIR=1` (default) the location is `/var/mail-state/lib-amavis/virusmails/`, or if `ONE_DIR=0`: `/var/lib/amavis/virusmails/`. These paths are inside the docker container.
|
- Too low: The action taken may prevent legitimate mail (ham) that was incorrectly detected as spam from being delivered successfully.
|
||||||
|
- Too high: Allows more spam to bypass the `SA_KILL` trigger (_how to treat mail with high confidence that it is actually spam_).
|
||||||
|
|
||||||
|
Experiences from DMS users with these settings has been [collected here][gh-issue::sa-tunables-insights], along with [some direct configuration guides][gh-issue::sa-tunables-guides] (_under "Resources for references"_).
|
||||||
|
|
||||||
|
[gh-issue::sa-tunables-insights]: https://github.com/docker-mailserver/docker-mailserver/pull/3058#issuecomment-1420268148
|
||||||
|
[gh-issue::sa-tunables-guides]: https://github.com/docker-mailserver/docker-mailserver/pull/3058#issuecomment-1416547911
|
||||||
|
|
||||||
|
??? info "Trigger action"
|
||||||
|
|
||||||
|
DMS will configure Amavis with either of these actions based on the DMS [`SPAMASSASSIN_SPAM_TO_INBOX`](#spamassassin_spam_to_inbox) ENV setting:
|
||||||
|
|
||||||
|
- `D_PASS` (**default**):
|
||||||
|
- Accept mail and deliver it to the recipient(s), despite the high spam score. A copy is still stored in quarantine.
|
||||||
|
- This is a good default to start with until you are more confident in an `SA_KILL` threshold that won't accidentally discard / bounce legitimate mail users are expecting to arrive but is detected as spam.
|
||||||
|
- `D_BOUNCE`:
|
||||||
|
- Additionally sends a bounce notification (DSN).
|
||||||
|
- The [DSN is suppressed][amavis-docs::actions] (_no bounce sent_) when the spam score exceeds the Amavis `$sa_dsn_cutoff_level` config setting (default: `10`). With the DMS `SA_KILL` default also being `10`, no DSN will ever be sent.
|
||||||
|
- `D_REJECT` / `D_DISCARD`:
|
||||||
|
- These two aren't configured by DMS, but are valid alternative action values if configuring Amavis directly.
|
||||||
|
|
||||||
|
??? note "Quarantined mail"
|
||||||
|
|
||||||
|
When mail has a spam score that reaches the `SA_KILL` threshold:
|
||||||
|
|
||||||
|
- [It will be quarantined][amavis-docs::quarantine] regardless of the `SA_KILL` action to perform.
|
||||||
|
- With `D_PASS` the delivered mail also appends an `X-Quarantine-ID` mail header. The ID value of this header is part of the quarantined file name.
|
||||||
|
|
||||||
|
If emails are quarantined, they are compressed and stored at a location dependent on the [`ONE_DIR`](#one_dir) setting:
|
||||||
|
|
||||||
|
- `ONE_DIR=1` (default): `/var/mail-state/lib-amavis/virusmails/`
|
||||||
|
- `ONE_DIR=0`: `/var/lib/amavis/virusmails/`
|
||||||
|
|
||||||
|
!!! tip
|
||||||
|
|
||||||
|
Easily list mail stored in quarantine with `find` and the quarantine path:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
find /var/lib/amavis/virusmails -type f
|
||||||
|
```
|
||||||
|
|
||||||
|
[amavis-docs::actions]: https://www.ijs.si/software/amavisd/amavisd-new-docs.html#actions
|
||||||
|
[amavis-docs::quarantine]: https://www.ijs.si/software/amavisd/amavisd-new-docs.html#quarantine
|
||||||
|
|
||||||
##### SA_SPAM_SUBJECT
|
##### SA_SPAM_SUBJECT
|
||||||
|
|
||||||
- **\*\*\*SPAM\*\*\*** => add tag to subject if spam detected
|
Adds a prefix to the subject header when mail is marked as spam (_via [`SA_TAG2`](#sa_tag2)_).
|
||||||
|
|
||||||
Note: this SpamAssassin setting needs `ENABLE_SPAMASSASSIN=1`. Add the SpamAssassin score to the subject line by inserting the keyword \_SCORE\_: **\*\*\*SPAM(\_SCORE\_)\*\*\***.
|
- **`'***SPAM*** '`** => A string value to use as a mail subject prefix.
|
||||||
|
- `undef` => Opt-out of modifying the subject for mail marked as spam.
|
||||||
|
|
||||||
|
??? example "Including trailing white-space"
|
||||||
|
|
||||||
|
Add trailing white-space by quote wrapping the value: `SA_SPAM_SUBJECT='[SPAM] '`
|
||||||
|
|
||||||
|
??? example "Including the associated spam score"
|
||||||
|
|
||||||
|
The [`_SCORE_` tag][sa-docs::score-tag] will be substituted with the SpamAssassin score: `SA_SPAM_SUBJECT=***SPAM(_SCORE_)***`.
|
||||||
|
|
||||||
|
[sa-docs::score-tag]: https://spamassassin.apache.org/full/4.0.x/doc/Mail_SpamAssassin_Conf.html#rewrite_header-subject-from-to-STRING
|
||||||
|
|
||||||
##### SA_SHORTCIRCUIT_BAYES_SPAM
|
##### SA_SHORTCIRCUIT_BAYES_SPAM
|
||||||
|
|
||||||
- **1** => will activate SpamAssassin short circuiting for bayes spam detection.
|
- **1** => will activate SpamAssassin short circuiting for bayes spam detection.
|
||||||
|
|
||||||
This will uncomment the respective line in ```/etc/spamassasin/local.cf```
|
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.
|
!!! warning
|
||||||
|
|
||||||
|
Activate this only if you are confident in your bayes database for identifying spam.
|
||||||
|
|
||||||
##### SA_SHORTCIRCUIT_BAYES_HAM
|
##### SA_SHORTCIRCUIT_BAYES_HAM
|
||||||
|
|
||||||
- **1** => will activate SpamAssassin short circuiting for bayes ham detection
|
- **1** => will activate SpamAssassin short circuiting for bayes ham detection
|
||||||
|
|
||||||
This will uncomment the respective line in ```/etc/spamassasin/local.cf```
|
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.
|
!!! warning
|
||||||
|
|
||||||
|
Activate this only if you are confident in your bayes database for identifying ham.
|
||||||
|
|
||||||
#### Fetchmail
|
#### Fetchmail
|
||||||
|
|
||||||
|
|
|
@ -378,18 +378,7 @@ When you run DMS with the ENV variable `ONE_DIR=1` (default), this directory wil
|
||||||
|
|
||||||
#### How can I manage my custom SpamAssassin rules?
|
#### How can I manage my custom SpamAssassin rules?
|
||||||
|
|
||||||
Antispam rules are managed in `docker-data/dms/config/spamassassin-rules.cf`.
|
Anti-spam rules are managed in `docker-data/dms/config/spamassassin-rules.cf`.
|
||||||
|
|
||||||
#### What are acceptable `SA_SPAM_SUBJECT` values?
|
|
||||||
|
|
||||||
For no subject set `SA_SPAM_SUBJECT=undef`.
|
|
||||||
|
|
||||||
For a trailing white-space subject one can define the whole variable with quotes in `compose.yaml`:
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
environment:
|
|
||||||
- "SA_SPAM_SUBJECT=[SPAM] "
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Why are SpamAssassin `x-headers` not inserted into my `subdomain.example.com` subdomain emails?
|
#### Why are SpamAssassin `x-headers` not inserted into my `subdomain.example.com` subdomain emails?
|
||||||
|
|
||||||
|
@ -479,59 +468,39 @@ The following configuration works nicely:
|
||||||
file: ./docker-data/dms/cron/sa-learn
|
file: ./docker-data/dms/cron/sa-learn
|
||||||
```
|
```
|
||||||
|
|
||||||
With the default settings, SpamAssassin will require 200 mails trained for spam (for example with the method explained above) and 200 mails trained for ham (using the same command as above but using `--ham` and providing it with some ham mails). Until you provided these 200+200 mails, SpamAssassin will not take the learned mails into account. For further reference, see the [SpamAssassin Wiki](https://wiki.apache.org/spamassassin/BayesNotWorking).
|
With the default settings, SpamAssassin will require 200 mails trained for spam (for example with the method explained above) and 200 mails trained for ham (using the same command as above but using `--ham` and providing it with some ham mails).
|
||||||
|
|
||||||
|
- Until you provided these 200+200 mails, SpamAssassin will not take the learned mails into account.
|
||||||
|
- For further reference, see the [SpamAssassin Wiki](https://wiki.apache.org/spamassassin/BayesNotWorking).
|
||||||
|
|
||||||
#### How do I have more control about what SpamAssassin is filtering?
|
#### How do I have more control about what SpamAssassin is filtering?
|
||||||
|
|
||||||
By default, SPAM and INFECTED emails are put to a quarantine which is not very straight forward to access. Several config settings are affecting this behavior:
|
This is related to Amavis processing the mail after SpamAssassin has analyzed it and assigned a spam score.
|
||||||
|
|
||||||
First, make sure you have the proper thresholds set:
|
- DMS provides some [common SA tunables via ENV][docs::env::sa_env].
|
||||||
|
- Additional configuration can be managed with the DMS config volume by providing `docker-data/dms/config/amavis.cf`.
|
||||||
|
|
||||||
```conf
|
#### How can I send quarantined mail to a mailbox?
|
||||||
SA_TAG=-100000.0
|
|
||||||
SA_TAG2=3.75
|
|
||||||
SA_KILL=100000.0
|
|
||||||
```
|
|
||||||
|
|
||||||
- The very negative value in `SA_TAG` makes sure, that all emails have the SpamAssassin headers included.
|
SPAM and INFECTED emails that [reach the `SA_KILL` threshold are archived into quarantine][docs::env::sa_kill].
|
||||||
- `SA_TAG2` is the actual threshold to set the YES/NO flag for spam detection.
|
|
||||||
- `SA_KILL` needs to be very high, to make sure nothing is bounced at all (`SA_KILL` superseeds `SPAMASSASSIN_SPAM_TO_INBOX`)
|
|
||||||
|
|
||||||
Make sure everything (including SPAM) is delivered to the inbox and not quarantined:
|
Instead of a quarantine folder, you can use a dedicated mailbox instead. Create an account like `quarantine@example.com` and create `docker-data/dms/config/amavis.cf`:
|
||||||
|
|
||||||
```conf
|
|
||||||
SPAMASSASSIN_SPAM_TO_INBOX=1
|
|
||||||
```
|
|
||||||
|
|
||||||
Use `MOVE_SPAM_TO_JUNK=1` or create a sieve script which puts spam to the Junk folder:
|
|
||||||
|
|
||||||
```sieve
|
|
||||||
require ["comparator-i;ascii-numeric","relational","fileinto"];
|
|
||||||
|
|
||||||
if header :contains "X-Spam-Flag" "YES" {
|
|
||||||
fileinto "Junk";
|
|
||||||
} elsif allof (
|
|
||||||
not header :matches "x-spam-score" "-*",
|
|
||||||
header :value "ge" :comparator "i;ascii-numeric" "x-spam-score" "3.75"
|
|
||||||
) {
|
|
||||||
fileinto "Junk";
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Create a dedicated mailbox for emails which are infected/bad header and everything amavis is blocking by default and put its address into `docker-data/dms/config/amavis.cf`
|
|
||||||
|
|
||||||
```cf
|
```cf
|
||||||
$clean_quarantine_to = "amavis\@example.com";
|
$clean_quarantine_to = "quarantine\@example.com";
|
||||||
$virus_quarantine_to = "amavis\@example.com";
|
$virus_quarantine_to = "quarantine\@example.com";
|
||||||
$banned_quarantine_to = "amavis\@example.com";
|
$banned_quarantine_to = "quarantine\@example.com";
|
||||||
$bad_header_quarantine_to = "amavis\@example.com";
|
$bad_header_quarantine_to = "quarantine\@example.com";
|
||||||
$spam_quarantine_to = "amavis\@example.com";
|
$spam_quarantine_to = "quarantine\@example.com";
|
||||||
```
|
```
|
||||||
|
|
||||||
[fail2ban-customize]: ./config/security/fail2ban.md
|
[fail2ban-customize]: ./config/security/fail2ban.md
|
||||||
[docs-maintenance]: ./config/advanced/maintenance/update-and-cleanup.md
|
[docs-maintenance]: ./config/advanced/maintenance/update-and-cleanup.md
|
||||||
[docs-override-postfix]: ./config/advanced/override-defaults/postfix.md
|
[docs-override-postfix]: ./config/advanced/override-defaults/postfix.md
|
||||||
[docs-userpatches]: ./config/advanced/override-defaults/user-patches.md
|
[docs-userpatches]: ./config/advanced/override-defaults/user-patches.md
|
||||||
|
[docs-optional-configuration]: ./config/advanced/optional-config.md
|
||||||
|
[docs::env::sa_env]: ./config/environment.md#spamassassin
|
||||||
|
[docs::env::sa_kill]: ./config/environment.md#sa_kill
|
||||||
[github-comment-baredomain]: https://github.com/docker-mailserver/docker-mailserver/issues/3048#issuecomment-1432358353
|
[github-comment-baredomain]: https://github.com/docker-mailserver/docker-mailserver/issues/3048#issuecomment-1432358353
|
||||||
[github-comment-override-hostname]: https://github.com/docker-mailserver/docker-mailserver/issues/1731#issuecomment-753968425
|
[github-comment-override-hostname]: https://github.com/docker-mailserver/docker-mailserver/issues/1731#issuecomment-753968425
|
||||||
[github-issue-95]: https://github.com/docker-mailserver/docker-mailserver/issues/95
|
[github-issue-95]: https://github.com/docker-mailserver/docker-mailserver/issues/95
|
||||||
|
@ -542,4 +511,3 @@ $spam_quarantine_to = "amavis\@example.com";
|
||||||
[github-issue-1792]: https://github.com/docker-mailserver/docker-mailserver/pull/1792
|
[github-issue-1792]: https://github.com/docker-mailserver/docker-mailserver/pull/1792
|
||||||
[hanscees-userpatches]: https://github.com/hanscees/dockerscripts/blob/master/scripts/tomav-user-patches.sh
|
[hanscees-userpatches]: https://github.com/hanscees/dockerscripts/blob/master/scripts/tomav-user-patches.sh
|
||||||
[mail-state-folders]: https://github.com/docker-mailserver/docker-mailserver/blob/c7e498194546416fb7231cb03254e77e085d18df/target/scripts/startup/misc-stack.sh#L24-L33
|
[mail-state-folders]: https://github.com/docker-mailserver/docker-mailserver/blob/c7e498194546416fb7231cb03254e77e085d18df/target/scripts/startup/misc-stack.sh#L24-L33
|
||||||
[docs-optional-configuration]: ./config/advanced/optional-config.md
|
|
||||||
|
|
|
@ -14,7 +14,7 @@ This documentation provides you not only with the basic setup and configuration
|
||||||
|
|
||||||
## About
|
## About
|
||||||
|
|
||||||
`docker-mailserver`, or DMS for short, is a production-ready fullstack but simple mail server (SMTP, IMAP, LDAP, Antispam, Antivirus, etc.). It employs only configuration files, no SQL database. The image is focused around the slogan "Keep it simple and versioned".
|
`docker-mailserver`, or DMS for short, is a production-ready fullstack but simple mail server (SMTP, IMAP, LDAP, Anti-spam, Anti-virus, etc.). It employs only configuration files, no SQL database. The image is focused around the slogan "Keep it simple and versioned".
|
||||||
|
|
||||||
## Contents
|
## Contents
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# Site specific:
|
# Site specific:
|
||||||
site_name: 'Docker Mailserver'
|
site_name: 'Docker Mailserver'
|
||||||
site_description: 'A fullstack but simple mail-server (SMTP, IMAP, LDAP, Antispam, Antivirus, etc.) using Docker.'
|
site_description: 'A fullstack but simple mail-server (SMTP, IMAP, LDAP, Anti-spam, Anti-virus, etc.) using Docker.'
|
||||||
site_author: 'docker-mailserver (Github Organization)'
|
site_author: 'docker-mailserver (Github Organization)'
|
||||||
copyright: '<p>© <a href="https://github.com/docker-mailserver"><em>Docker Mailserver Organization</em></a><br/><span>This project is licensed under the MIT license.</span></p>'
|
copyright: '<p>© <a href="https://github.com/docker-mailserver"><em>Docker Mailserver Organization</em></a><br/><span>This project is licensed under the MIT license.</span></p>'
|
||||||
|
|
||||||
|
|
|
@ -374,9 +374,6 @@ DOVECOT_INET_PROTOCOLS=all
|
||||||
|
|
||||||
ENABLE_SPAMASSASSIN=0
|
ENABLE_SPAMASSASSIN=0
|
||||||
|
|
||||||
# deliver spam messages in the inbox (eventually tagged using SA_SPAM_SUBJECT)
|
|
||||||
SPAMASSASSIN_SPAM_TO_INBOX=1
|
|
||||||
|
|
||||||
# KAM is a 3rd party SpamAssassin ruleset, provided by the McGrail Foundation.
|
# KAM is a 3rd party SpamAssassin ruleset, provided by the McGrail Foundation.
|
||||||
# If SpamAssassin is enabled, KAM can be used in addition to the default ruleset.
|
# If SpamAssassin is enabled, KAM can be used in addition to the default ruleset.
|
||||||
# - **0** => KAM disabled
|
# - **0** => KAM disabled
|
||||||
|
@ -385,23 +382,26 @@ SPAMASSASSIN_SPAM_TO_INBOX=1
|
||||||
# Note: only has an effect if `ENABLE_SPAMASSASSIN=1`
|
# Note: only has an effect if `ENABLE_SPAMASSASSIN=1`
|
||||||
ENABLE_SPAMASSASSIN_KAM=0
|
ENABLE_SPAMASSASSIN_KAM=0
|
||||||
|
|
||||||
|
# deliver spam messages to the inbox (tagged using SA_SPAM_SUBJECT)
|
||||||
|
SPAMASSASSIN_SPAM_TO_INBOX=1
|
||||||
|
|
||||||
# spam messages will be moved in the Junk folder (SPAMASSASSIN_SPAM_TO_INBOX=1 required)
|
# spam messages will be moved in the Junk folder (SPAMASSASSIN_SPAM_TO_INBOX=1 required)
|
||||||
MOVE_SPAM_TO_JUNK=1
|
MOVE_SPAM_TO_JUNK=1
|
||||||
|
|
||||||
# spam messages wil be marked as read
|
# spam messages wil be marked as read
|
||||||
MARK_SPAM_AS_READ=0
|
MARK_SPAM_AS_READ=0
|
||||||
|
|
||||||
# add spam info headers if at, or above that level:
|
# add 'spam info' headers at, or above this level
|
||||||
SA_TAG=2.0
|
SA_TAG=2.0
|
||||||
|
|
||||||
# add 'spam detected' headers at that level
|
# add 'spam detected' headers at, or above this level
|
||||||
SA_TAG2=6.31
|
SA_TAG2=6.31
|
||||||
|
|
||||||
# triggers spam evasive actions
|
# triggers spam evasive actions
|
||||||
SA_KILL=10.0
|
SA_KILL=10.0
|
||||||
|
|
||||||
# add tag to subject if spam detected
|
# add tag to subject if spam detected
|
||||||
SA_SPAM_SUBJECT=***SPAM*****
|
SA_SPAM_SUBJECT='***SPAM*** '
|
||||||
|
|
||||||
# -----------------------------------------------
|
# -----------------------------------------------
|
||||||
# --- Fetchmail Section -------------------------
|
# --- Fetchmail Section -------------------------
|
||||||
|
|
|
@ -5,6 +5,9 @@ biff = no
|
||||||
append_dot_mydomain = no
|
append_dot_mydomain = no
|
||||||
readme_directory = no
|
readme_directory = no
|
||||||
|
|
||||||
|
# Disabled as not compatible with Dovecot
|
||||||
|
smtputf8_enable = no
|
||||||
|
|
||||||
# Basic configuration
|
# Basic configuration
|
||||||
# myhostname =
|
# myhostname =
|
||||||
alias_maps = hash:/etc/aliases
|
alias_maps = hash:/etc/aliases
|
||||||
|
@ -51,10 +54,11 @@ smtpd_helo_required = yes
|
||||||
smtpd_delay_reject = yes
|
smtpd_delay_reject = yes
|
||||||
smtpd_helo_restrictions = permit_mynetworks, reject_invalid_helo_hostname, permit
|
smtpd_helo_restrictions = permit_mynetworks, reject_invalid_helo_hostname, permit
|
||||||
smtpd_relay_restrictions = permit_mynetworks permit_sasl_authenticated defer_unauth_destination
|
smtpd_relay_restrictions = permit_mynetworks permit_sasl_authenticated defer_unauth_destination
|
||||||
smtpd_recipient_restrictions = permit_sasl_authenticated, permit_mynetworks, reject_unauth_destination, reject_unauth_pipelining, reject_invalid_helo_hostname, reject_non_fqdn_helo_hostname, reject_unknown_recipient_domain
|
smtpd_recipient_restrictions = permit_sasl_authenticated, permit_mynetworks, reject_unauth_destination, reject_invalid_helo_hostname, reject_non_fqdn_helo_hostname, reject_unknown_recipient_domain
|
||||||
smtpd_client_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination, reject_unauth_pipelining
|
smtpd_client_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination
|
||||||
smtpd_sender_restrictions = $dms_smtpd_sender_restrictions
|
smtpd_sender_restrictions = $dms_smtpd_sender_restrictions
|
||||||
smtpd_discard_ehlo_keywords = silent-discard, dsn
|
smtpd_discard_ehlo_keywords = silent-discard, dsn
|
||||||
|
smtpd_data_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_pipelining
|
||||||
disable_vrfy_command = yes
|
disable_vrfy_command = yes
|
||||||
|
|
||||||
# Security - Prevent SMTP Smuggling attack
|
# Security - Prevent SMTP Smuggling attack
|
||||||
|
|
|
@ -1,9 +1,12 @@
|
||||||
# documentation: https://rspamd.com/doc/configuration/metrics.html#actions
|
# documentation: https://rspamd.com/doc/configuration/metrics.html#actions
|
||||||
# and https://rspamd.com/doc/configuration/metrics.html
|
# and https://rspamd.com/doc/configuration/metrics.html
|
||||||
|
|
||||||
#greylist = 4;
|
# These values work in conjunction with the symbol scores in
|
||||||
#add_header = 6;
|
# `scores.d/*.conf`. When adjusting them, make sure to understand
|
||||||
#rewrite_subject = 7;
|
# and to be able to explain the impact on the whole system.
|
||||||
#reject = 15;
|
greylist = 4;
|
||||||
|
add_header = 6;
|
||||||
|
rewrite_subject = 7;
|
||||||
|
reject = 11;
|
||||||
|
|
||||||
subject = "***SPAM*** %s"
|
subject = "***SPAM*** %s"
|
||||||
|
|
|
@ -0,0 +1,108 @@
|
||||||
|
# Please refer to
|
||||||
|
# https://github.com/docker-mailserver/docker-mailserver/issues/3690
|
||||||
|
# for understanding this file and its scores' values.
|
||||||
|
|
||||||
|
symbols = {
|
||||||
|
# SPF
|
||||||
|
"R_SPF_ALLOW" {
|
||||||
|
weight = -1;
|
||||||
|
description = "SPF verification allows sending";
|
||||||
|
groups = ["spf"];
|
||||||
|
}
|
||||||
|
"R_SPF_NA" {
|
||||||
|
weight = 1.5;
|
||||||
|
description = "Missing SPF record";
|
||||||
|
one_shot = true;
|
||||||
|
groups = ["spf"];
|
||||||
|
}
|
||||||
|
"R_SPF_SOFTFAIL" {
|
||||||
|
weight = 2.5;
|
||||||
|
description = "SPF verification soft-failed";
|
||||||
|
groups = ["spf"];
|
||||||
|
}
|
||||||
|
"R_SPF_FAIL" {
|
||||||
|
weight = 4.5;
|
||||||
|
description = "SPF verification failed";
|
||||||
|
groups = ["spf"];
|
||||||
|
}
|
||||||
|
|
||||||
|
"R_SPF_NEUTRAL" { # == R_SPF_NA
|
||||||
|
weight = 1.5;
|
||||||
|
description = "SPF policy is neutral";
|
||||||
|
groups = ["spf"];
|
||||||
|
}
|
||||||
|
"R_SPF_DNSFAIL" { # == R_SPF_SOFTFAIL
|
||||||
|
weight = 2.5;
|
||||||
|
description = "SPF DNS failure";
|
||||||
|
groups = ["spf"];
|
||||||
|
}
|
||||||
|
"R_SPF_PERMFAIL" { # == R_SPF_FAIL
|
||||||
|
weight = 4.5;
|
||||||
|
description = "SPF record is malformed or persistent DNS error";
|
||||||
|
groups = ["spf"];
|
||||||
|
}
|
||||||
|
|
||||||
|
# DKIM
|
||||||
|
"R_DKIM_ALLOW" {
|
||||||
|
weight = -1;
|
||||||
|
description = "DKIM verification succeed";
|
||||||
|
one_shot = true;
|
||||||
|
groups = ["dkim"];
|
||||||
|
}
|
||||||
|
"R_DKIM_NA" {
|
||||||
|
weight = 0;
|
||||||
|
description = "Missing DKIM signature";
|
||||||
|
one_shot = true;
|
||||||
|
groups = ["dkim"];
|
||||||
|
}
|
||||||
|
"R_DKIM_TEMPFAIL" {
|
||||||
|
weight = 1.5;
|
||||||
|
description = "DKIM verification soft-failed";
|
||||||
|
groups = ["dkim"];
|
||||||
|
}
|
||||||
|
"R_DKIM_PERMFAIL" {
|
||||||
|
weight = 4.5;
|
||||||
|
description = "DKIM verification hard-failed (invalid)";
|
||||||
|
groups = ["dkim"];
|
||||||
|
}
|
||||||
|
|
||||||
|
"R_DKIM_REJECT" { # == R_DKIM_PERMFAIL
|
||||||
|
weight = 4.5;
|
||||||
|
description = "DKIM verification failed";
|
||||||
|
one_shot = true;
|
||||||
|
groups = ["dkim"];
|
||||||
|
}
|
||||||
|
|
||||||
|
# DMARC
|
||||||
|
"DMARC_NA" {
|
||||||
|
weight = 1;
|
||||||
|
description = "No DMARC record";
|
||||||
|
groups = ["dmarc"];
|
||||||
|
}
|
||||||
|
"DMARC_POLICY_QUARANTINE" {
|
||||||
|
weight = 1.5;
|
||||||
|
description = "DMARC quarantine policy";
|
||||||
|
groups = ["dmarc"];
|
||||||
|
}
|
||||||
|
"DMARC_POLICY_REJECT" {
|
||||||
|
weight = 2;
|
||||||
|
description = "DMARC reject policy";
|
||||||
|
groups = ["dmarc"];
|
||||||
|
}
|
||||||
|
|
||||||
|
"DMARC_POLICY_ALLOW" { # no equivalent
|
||||||
|
weight = -1;
|
||||||
|
description = "DMARC permit policy";
|
||||||
|
groups = ["dmarc"];
|
||||||
|
}
|
||||||
|
"DMARC_POLICY_ALLOW_WITH_FAILURES" { # no equivalent
|
||||||
|
weight = -0.5;
|
||||||
|
description = "DMARC permit policy with DKIM/SPF failure";
|
||||||
|
groups = ["dmarc"];
|
||||||
|
}
|
||||||
|
"DMARC_POLICY_SOFTFAIL" { # == DMARC_POLICY_QUARANTINE
|
||||||
|
weight = 1.5;
|
||||||
|
description = "DMARC soft-failed";
|
||||||
|
groups = ["dmarc"];
|
||||||
|
}
|
||||||
|
}
|
|
@ -192,7 +192,7 @@ function _install_getmail() {
|
||||||
|
|
||||||
function _install_utils() {
|
function _install_utils() {
|
||||||
_log 'debug' 'Installing utils sourced from Github'
|
_log 'debug' 'Installing utils sourced from Github'
|
||||||
curl -sL https://github.com/01mf02/jaq/releases/latest/download/jaq-v1.2.0-x86_64-unknown-linux-musl -o /usr/bin/jaq && chmod +x /usr/bin/jaq
|
curl -sL "https://github.com/01mf02/jaq/releases/latest/download/jaq-v1.2.0-$(uname -m)-unknown-linux-gnu" -o /usr/bin/jaq && chmod +x /usr/bin/jaq
|
||||||
}
|
}
|
||||||
|
|
||||||
function _remove_data_after_package_installations() {
|
function _remove_data_after_package_installations() {
|
||||||
|
|
|
@ -19,9 +19,6 @@ function _setup_postfix_early() {
|
||||||
postconf "inet_protocols = ${POSTFIX_INET_PROTOCOLS}"
|
postconf "inet_protocols = ${POSTFIX_INET_PROTOCOLS}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
__postfix__log 'trace' "Disabling SMTPUTF8 support"
|
|
||||||
postconf 'smtputf8_enable = no'
|
|
||||||
|
|
||||||
__postfix__log 'trace' "Configuring SASLauthd"
|
__postfix__log 'trace' "Configuring SASLauthd"
|
||||||
if [[ ${ENABLE_SASLAUTHD} -eq 1 ]] && [[ ! -f /etc/postfix/sasl/smtpd.conf ]]; then
|
if [[ ${ENABLE_SASLAUTHD} -eq 1 ]] && [[ ! -f /etc/postfix/sasl/smtpd.conf ]]; then
|
||||||
cat >/etc/postfix/sasl/smtpd.conf << EOF
|
cat >/etc/postfix/sasl/smtpd.conf << EOF
|
||||||
|
|
|
@ -111,7 +111,7 @@ function __setup__security__spamassassin() {
|
||||||
|
|
||||||
if [[ ${SPAMASSASSIN_SPAM_TO_INBOX} -eq 1 ]]; then
|
if [[ ${SPAMASSASSIN_SPAM_TO_INBOX} -eq 1 ]]; then
|
||||||
_log 'trace' 'Configuring Spamassassin/Amavis to send SPAM to inbox'
|
_log 'trace' 'Configuring Spamassassin/Amavis to send SPAM to inbox'
|
||||||
_log 'debug' 'SPAM_TO_INBOX=1 is set. SA_KILL will be ignored.'
|
_log 'debug' "'SPAMASSASSIN_SPAM_TO_INBOX=1' is set. The 'SA_KILL' ENV will be ignored."
|
||||||
|
|
||||||
sed -i "s|\$final_spam_destiny.*=.*$|\$final_spam_destiny = D_PASS;|g" /etc/amavis/conf.d/49-docker-mailserver
|
sed -i "s|\$final_spam_destiny.*=.*$|\$final_spam_destiny = D_PASS;|g" /etc/amavis/conf.d/49-docker-mailserver
|
||||||
sed -i "s|\$final_bad_header_destiny.*=.*$|\$final_bad_header_destiny = D_PASS;|g" /etc/amavis/conf.d/49-docker-mailserver
|
sed -i "s|\$final_bad_header_destiny.*=.*$|\$final_bad_header_destiny = D_PASS;|g" /etc/amavis/conf.d/49-docker-mailserver
|
||||||
|
@ -265,7 +265,7 @@ EOF
|
||||||
chown dovecot:root /usr/lib/dovecot/sieve-global/after/spam_to_junk.{sieve,svbin}
|
chown dovecot:root /usr/lib/dovecot/sieve-global/after/spam_to_junk.{sieve,svbin}
|
||||||
|
|
||||||
if [[ ${ENABLE_SPAMASSASSIN} -eq 1 ]] && [[ ${SPAMASSASSIN_SPAM_TO_INBOX} -eq 0 ]]; then
|
if [[ ${ENABLE_SPAMASSASSIN} -eq 1 ]] && [[ ${SPAMASSASSIN_SPAM_TO_INBOX} -eq 0 ]]; then
|
||||||
_log 'warning' "'SPAMASSASSIN_SPAM_TO_INBOX=0' but it is required to be 1 for 'MOVE_SPAM_TO_JUNK=1' to work"
|
_log 'warn' "'SPAMASSASSIN_SPAM_TO_INBOX=0' but it is required to be 1 for 'MOVE_SPAM_TO_JUNK=1' to work"
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
_log 'debug' 'Spam emails will not be moved to the Junk folder'
|
_log 'debug' 'Spam emails will not be moved to the Junk folder'
|
||||||
|
@ -290,7 +290,7 @@ EOF
|
||||||
chown dovecot:root /usr/lib/dovecot/sieve-global/after/spam_mark_as_read.{sieve,svbin}
|
chown dovecot:root /usr/lib/dovecot/sieve-global/after/spam_mark_as_read.{sieve,svbin}
|
||||||
|
|
||||||
if [[ ${ENABLE_SPAMASSASSIN} -eq 1 ]] && [[ ${SPAMASSASSIN_SPAM_TO_INBOX} -eq 0 ]]; then
|
if [[ ${ENABLE_SPAMASSASSIN} -eq 1 ]] && [[ ${SPAMASSASSIN_SPAM_TO_INBOX} -eq 0 ]]; then
|
||||||
_log 'warning' "'SPAMASSASSIN_SPAM_TO_INBOX=0' but it is required to be 1 for 'MARK_SPAM_AS_READ=1' to work"
|
_log 'warn' "'SPAMASSASSIN_SPAM_TO_INBOX=0' but it is required to be 1 for 'MARK_SPAM_AS_READ=1' to work"
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
_log 'debug' 'Spam emails will not be marked as read'
|
_log 'debug' 'Spam emails will not be marked as read'
|
||||||
|
|
|
@ -33,7 +33,7 @@ function setup_file() {
|
||||||
function teardown_file() { _default_teardown ; }
|
function teardown_file() { _default_teardown ; }
|
||||||
|
|
||||||
@test 'log files exist at /var/log/mail directory' {
|
@test 'log files exist at /var/log/mail directory' {
|
||||||
_run_in_container_bash "ls -1 /var/log/mail/ | grep -E 'clamav|freshclam|mail.log' | wc -l"
|
_run_in_container_bash "ls -1 /var/log/mail/ | grep -c -E 'clamav|freshclam|mail.log'"
|
||||||
assert_success
|
assert_success
|
||||||
assert_output 3
|
assert_output 3
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,7 +44,7 @@ function teardown_file() { _default_teardown ; }
|
||||||
# The other spam checks in `main.cf:smtpd_recipient_restrictions` would interfere with testing postgrey.
|
# The other spam checks in `main.cf:smtpd_recipient_restrictions` would interfere with testing postgrey.
|
||||||
_run_in_container sed -i \
|
_run_in_container sed -i \
|
||||||
-e 's/permit_sasl_authenticated.*policyd-spf,$//g' \
|
-e 's/permit_sasl_authenticated.*policyd-spf,$//g' \
|
||||||
-e 's/reject_unauth_pipelining.*reject_unknown_recipient_domain,$//g' \
|
-e 's/reject_invalid_helo_hostname.*reject_unknown_recipient_domain,$//g' \
|
||||||
-e 's/reject_rbl_client.*inet:127\.0\.0\.1:10023$//g' \
|
-e 's/reject_rbl_client.*inet:127\.0\.0\.1:10023$//g' \
|
||||||
-e 's/smtpd_recipient_restrictions =/smtpd_recipient_restrictions = check_policy_service inet:127.0.0.1:10023/g' \
|
-e 's/smtpd_recipient_restrictions =/smtpd_recipient_restrictions = check_policy_service inet:127.0.0.1:10023/g' \
|
||||||
/etc/postfix/main.cf
|
/etc/postfix/main.cf
|
||||||
|
|
|
@ -277,6 +277,10 @@ function _successful() {
|
||||||
--protocol ESMTP \
|
--protocol ESMTP \
|
||||||
--server mail.example.test \
|
--server mail.example.test \
|
||||||
--quit-after FIRST-EHLO
|
--quit-after FIRST-EHLO
|
||||||
|
|
||||||
|
# Ensure the output is actually related to what we want to refute against:
|
||||||
|
assert_output --partial 'EHLO mail.external.tld'
|
||||||
|
assert_output --partial '221 2.0.0 Bye'
|
||||||
refute_output --partial 'SMTPUTF8'
|
refute_output --partial 'SMTPUTF8'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -204,12 +204,12 @@ function teardown_file() { _default_teardown ; }
|
||||||
run ./setup.sh -c "${CONTAINER_NAME}" quota set quota_user2 51M
|
run ./setup.sh -c "${CONTAINER_NAME}" quota set quota_user2 51M
|
||||||
assert_failure
|
assert_failure
|
||||||
|
|
||||||
run /bin/sh -c "cat ${TEST_TMP_CONFIG}/dovecot-quotas.cf | grep -E '^quota_user@example.com\:12M\$' | wc -l | grep 1"
|
run /bin/sh -c "cat ${TEST_TMP_CONFIG}/dovecot-quotas.cf | grep -c -E '^quota_user@example.com\:12M\$' | grep 1"
|
||||||
assert_success
|
assert_success
|
||||||
|
|
||||||
run ./setup.sh -c "${CONTAINER_NAME}" quota set quota_user@example.com 26M
|
run ./setup.sh -c "${CONTAINER_NAME}" quota set quota_user@example.com 26M
|
||||||
assert_success
|
assert_success
|
||||||
run /bin/sh -c "cat ${TEST_TMP_CONFIG}/dovecot-quotas.cf | grep -E '^quota_user@example.com\:26M\$' | wc -l | grep 1"
|
run /bin/sh -c "cat ${TEST_TMP_CONFIG}/dovecot-quotas.cf | grep -c -E '^quota_user@example.com\:26M\$' | grep 1"
|
||||||
assert_success
|
assert_success
|
||||||
|
|
||||||
run grep "quota_user2@example.com" "${TEST_TMP_CONFIG}/dovecot-quotas.cf"
|
run grep "quota_user2@example.com" "${TEST_TMP_CONFIG}/dovecot-quotas.cf"
|
||||||
|
@ -220,12 +220,12 @@ function teardown_file() { _default_teardown ; }
|
||||||
@test "delquota" {
|
@test "delquota" {
|
||||||
run ./setup.sh -c "${CONTAINER_NAME}" quota set quota_user@example.com 12M
|
run ./setup.sh -c "${CONTAINER_NAME}" quota set quota_user@example.com 12M
|
||||||
assert_success
|
assert_success
|
||||||
run /bin/sh -c "cat ${TEST_TMP_CONFIG}/dovecot-quotas.cf | grep -E '^quota_user@example.com\:12M\$' | wc -l | grep 1"
|
run /bin/sh -c "cat ${TEST_TMP_CONFIG}/dovecot-quotas.cf | grep -c -E '^quota_user@example.com\:12M\$' | grep 1"
|
||||||
assert_success
|
assert_success
|
||||||
|
|
||||||
run ./setup.sh -c "${CONTAINER_NAME}" quota del unknown@domain.com
|
run ./setup.sh -c "${CONTAINER_NAME}" quota del unknown@domain.com
|
||||||
assert_failure
|
assert_failure
|
||||||
run /bin/sh -c "cat ${TEST_TMP_CONFIG}/dovecot-quotas.cf | grep -E '^quota_user@example.com\:12M\$' | wc -l | grep 1"
|
run /bin/sh -c "cat ${TEST_TMP_CONFIG}/dovecot-quotas.cf | grep -c -E '^quota_user@example.com\:12M\$' | grep 1"
|
||||||
assert_success
|
assert_success
|
||||||
|
|
||||||
run ./setup.sh -c "${CONTAINER_NAME}" quota del quota_user@example.com
|
run ./setup.sh -c "${CONTAINER_NAME}" quota del quota_user@example.com
|
||||||
|
@ -260,13 +260,13 @@ function teardown_file() { _default_teardown ; }
|
||||||
./setup.sh -c "${CONTAINER_NAME}" relay add-domain example3.org smtp.relay.com 587
|
./setup.sh -c "${CONTAINER_NAME}" relay add-domain example3.org smtp.relay.com 587
|
||||||
|
|
||||||
# check adding
|
# check adding
|
||||||
run /bin/sh -c "cat ${TEST_TMP_CONFIG}/postfix-relaymap.cf | grep -e '^@example1.org\s\+\[smtp.relay1.com\]:2525' | wc -l | grep 1"
|
run /bin/sh -c "cat ${TEST_TMP_CONFIG}/postfix-relaymap.cf | grep -c -e '^@example1.org\s\+\[smtp.relay1.com\]:2525' | grep 1"
|
||||||
assert_success
|
assert_success
|
||||||
# test default port
|
# test default port
|
||||||
run /bin/sh -c "cat ${TEST_TMP_CONFIG}/postfix-relaymap.cf | grep -e '^@example2.org\s\+\[smtp.relay2.com\]:25' | wc -l | grep 1"
|
run /bin/sh -c "cat ${TEST_TMP_CONFIG}/postfix-relaymap.cf | grep -c -e '^@example2.org\s\+\[smtp.relay2.com\]:25' | grep 1"
|
||||||
assert_success
|
assert_success
|
||||||
# test modifying
|
# test modifying
|
||||||
run /bin/sh -c "cat ${TEST_TMP_CONFIG}/postfix-relaymap.cf | grep -e '^@example3.org\s\+\[smtp.relay.com\]:587' | wc -l | grep 1"
|
run /bin/sh -c "cat ${TEST_TMP_CONFIG}/postfix-relaymap.cf | grep -c -e '^@example3.org\s\+\[smtp.relay.com\]:587' | grep 1"
|
||||||
assert_success
|
assert_success
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -276,16 +276,16 @@ function teardown_file() { _default_teardown ; }
|
||||||
./setup.sh -c "${CONTAINER_NAME}" relay add-auth example2.org smtp_user2 smtp_pass_new
|
./setup.sh -c "${CONTAINER_NAME}" relay add-auth example2.org smtp_user2 smtp_pass_new
|
||||||
|
|
||||||
# test adding
|
# test adding
|
||||||
run /bin/sh -c "cat ${TEST_TMP_CONFIG}/postfix-sasl-password.cf | grep -e '^@example.org\s\+smtp_user:smtp_pass' | wc -l | grep 1"
|
run /bin/sh -c "cat ${TEST_TMP_CONFIG}/postfix-sasl-password.cf | grep -c -e '^@example.org\s\+smtp_user:smtp_pass' | grep 1"
|
||||||
assert_success
|
assert_success
|
||||||
# test updating
|
# test updating
|
||||||
run /bin/sh -c "cat ${TEST_TMP_CONFIG}/postfix-sasl-password.cf | grep -e '^@example2.org\s\+smtp_user2:smtp_pass_new' | wc -l | grep 1"
|
run /bin/sh -c "cat ${TEST_TMP_CONFIG}/postfix-sasl-password.cf | grep -c -e '^@example2.org\s\+smtp_user2:smtp_pass_new' | grep 1"
|
||||||
assert_success
|
assert_success
|
||||||
}
|
}
|
||||||
|
|
||||||
@test "relay exclude-domain" {
|
@test "relay exclude-domain" {
|
||||||
./setup.sh -c "${CONTAINER_NAME}" relay exclude-domain example.org
|
./setup.sh -c "${CONTAINER_NAME}" relay exclude-domain example.org
|
||||||
|
|
||||||
run /bin/sh -c "cat ${TEST_TMP_CONFIG}/postfix-relaymap.cf | grep -e '^@example.org\s*$' | wc -l | grep 1"
|
run /bin/sh -c "cat ${TEST_TMP_CONFIG}/postfix-relaymap.cf | grep -c -e '^@example.org\s*$' | grep 1"
|
||||||
assert_success
|
assert_success
|
||||||
}
|
}
|
||||||
|
|
|
@ -264,7 +264,7 @@ EOF
|
||||||
#
|
#
|
||||||
|
|
||||||
@test "amavis: config overrides" {
|
@test "amavis: config overrides" {
|
||||||
_run_in_container_bash "grep 'Test Verification' /etc/amavis/conf.d/50-user | wc -l"
|
_run_in_container_bash "grep -c 'Test Verification' /etc/amavis/conf.d/50-user"
|
||||||
assert_success
|
assert_success
|
||||||
assert_output 1
|
assert_output 1
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue