Merge branch 'master' into oauth2
This commit is contained in:
commit
acfc44d991
|
@ -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
|
||||||
|
|
17
CHANGELOG.md
17
CHANGELOG.md
|
@ -15,10 +15,27 @@ All notable changes to this project will be documented in this file. The format
|
||||||
|
|
||||||
### Updates
|
### Updates
|
||||||
|
|
||||||
|
- **Tests**:
|
||||||
|
- Refactored mail sending ([#3747](https://github.com/docker-mailserver/docker-mailserver/pull/3747)):
|
||||||
|
- This change is a follow-up to [#3732](https://github.com/docker-mailserver/docker-mailserver/pull/3732) from DMS v13.2.
|
||||||
|
- `swaks` version is now the latest from Github releases instead of the Debian package.
|
||||||
|
- `_nc_wrapper`, `_send_mail` and related helpers expect the `.txt` filepath extension again.
|
||||||
|
- `sending.bash` helper methods were refactored to better integrate `swaks` and accommodate different usage contexts.
|
||||||
|
- `test/files/emails/existing/` files were removed similar to previous removal of SMTP auth files as they became redundant with `swaks`.
|
||||||
- **Internal:**
|
- **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))
|
- 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)):
|
- **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)
|
- 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)
|
## [v13.2.0](https://github.com/docker-mailserver/docker-mailserver/releases/tag/v13.2.0)
|
||||||
|
|
||||||
|
|
2108
CONTRIBUTORS.md
2108
CONTRIBUTORS.md
File diff suppressed because it is too large
Load Diff
|
@ -326,7 +326,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
|
||||||
|
|
|
@ -324,28 +324,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
|
||||||
|
@ -523,63 +527,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>'
|
||||||
|
|
||||||
|
|
|
@ -368,9 +368,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
|
||||||
|
@ -379,23 +376,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 -------------------------
|
||||||
|
|
|
@ -80,7 +80,7 @@ function _install_packages() {
|
||||||
# `bind9-dnsutils` provides the `dig` command
|
# `bind9-dnsutils` provides the `dig` command
|
||||||
# `iputils-ping` provides the `ping` command
|
# `iputils-ping` provides the `ping` command
|
||||||
DEBUG_PACKAGES=(
|
DEBUG_PACKAGES=(
|
||||||
bind9-dnsutils iputils-ping less nano swaks
|
bind9-dnsutils iputils-ping less nano
|
||||||
)
|
)
|
||||||
|
|
||||||
apt-get "${QUIET}" --no-install-recommends install \
|
apt-get "${QUIET}" --no-install-recommends install \
|
||||||
|
@ -192,7 +192,15 @@ 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
|
_log 'trace' 'Installing 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
|
||||||
|
|
||||||
|
_log 'trace' 'Installing swaks'
|
||||||
|
local SWAKS_VERSION='20240103.0'
|
||||||
|
local SWAKS_RELEASE="swaks-${SWAKS_VERSION}"
|
||||||
|
curl -sSfL "https://github.com/jetmore/swaks/releases/download/v${SWAKS_VERSION}/${SWAKS_RELEASE}.tar.gz" | tar -xz
|
||||||
|
mv "${SWAKS_RELEASE}/swaks" /usr/local/bin
|
||||||
|
rm -r "${SWAKS_RELEASE}"
|
||||||
}
|
}
|
||||||
|
|
||||||
function _remove_data_after_package_installations() {
|
function _remove_data_after_package_installations() {
|
||||||
|
|
|
@ -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'
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
From: Docker Mail Server <dockermailserver@external.tld>
|
|
||||||
To: Existing Local User <added@localhost.localdomain>
|
|
||||||
Date: Sat, 22 May 2010 07:43:25 -0400
|
|
||||||
Subject: Test Message existing-added.txt
|
|
||||||
This is a test mail.
|
|
|
@ -1,5 +0,0 @@
|
||||||
From: Docker Mail Server <dockermailserver@external.tld>
|
|
||||||
To: Existing Local User <alias1@localhost.localdomain>
|
|
||||||
Date: Sat, 22 May 2010 07:43:25 -0400
|
|
||||||
Subject: Test Message existing-alias-external.txt
|
|
||||||
This is a test mail.
|
|
|
@ -1,5 +0,0 @@
|
||||||
From: Docker Mail Server <dockermailserver@external.tld>
|
|
||||||
To: Existing Local Alias <alias2@localhost.localdomain>
|
|
||||||
Date: Sat, 22 May 2010 07:43:25 -0400
|
|
||||||
Subject: Test Message existing-alias-local.txt
|
|
||||||
This is a test mail.
|
|
|
@ -1,5 +0,0 @@
|
||||||
From: Docker Mail Server <dockermailserver@external.tld>
|
|
||||||
To: Existing Local Alias With Delimiter <alias1+test@localhost.localdomain>
|
|
||||||
Date: Sat, 22 May 2010 07:43:25 -0400
|
|
||||||
Subject: Test Message existing-alias-recipient-delimiter.txt
|
|
||||||
This is a test mail.
|
|
|
@ -1,5 +0,0 @@
|
||||||
From: Docker Mail Server <dockermailserver@external.tld>
|
|
||||||
To: Existing Local User <wildcard@localdomain2.com>
|
|
||||||
Date: Sat, 22 May 2010 07:43:25 -0400
|
|
||||||
Subject: Test Message existing-catchall-local.txt
|
|
||||||
This is a test mail.
|
|
|
@ -1,5 +0,0 @@
|
||||||
From: Docker Mail Server <dockermailserver@external.tld>
|
|
||||||
To: Existing Local User <bounce-always@localhost.localdomain>
|
|
||||||
Date: Sat, 22 May 2010 07:43:25 -0400
|
|
||||||
Subject: Test Message existing-regexp-alias-external.txt
|
|
||||||
This is a test mail.
|
|
|
@ -1,5 +0,0 @@
|
||||||
From: Docker Mail Server <dockermailserver@external.tld>
|
|
||||||
To: Existing Local User <test123@localhost.localdomain>
|
|
||||||
Date: Sat, 22 May 2010 07:43:25 -0400
|
|
||||||
Subject: Test Message existing-regexp-alias-local.txt
|
|
||||||
This is a test mail.
|
|
|
@ -1,6 +0,0 @@
|
||||||
From: Docker Mail Server <dockermailserver@external.tld>
|
|
||||||
To: Existing Local User <user1@localhost.localdomain>
|
|
||||||
Cc: Existing Local Alias <alias2@localhost.localdomain>
|
|
||||||
Date: Sat, 22 May 2010 07:43:25 -0400
|
|
||||||
Subject: Test Message existing-user-and-cc-local-alias.txt
|
|
||||||
This is a test mail.
|
|
|
@ -1,5 +0,0 @@
|
||||||
From: Docker Mail Server <dockermailserver@external.tld>
|
|
||||||
To: Existing Local User <user1@localhost.localdomain>
|
|
||||||
Date: Sat, 22 May 2010 07:43:25 -0400
|
|
||||||
Subject: Test Message existing-user1.txt
|
|
||||||
This is a test mail.
|
|
|
@ -1,5 +0,0 @@
|
||||||
From: Docker Mail Server <dockermailserver@external.tld>
|
|
||||||
To: Existing Local User <user1@localhost.localdomain>
|
|
||||||
Date: Sat, 22 May 2010 07:43:25 -0400
|
|
||||||
Subject: Test Message non-existing-user.txt
|
|
||||||
This is a test mail.
|
|
|
@ -1,5 +0,0 @@
|
||||||
From: Docker Mail Server <pass@example.test>
|
|
||||||
To: Existing Local User <user1@localhost.localdomain>
|
|
||||||
Date: Sat, 22 May 2010 07:43:25 -0400
|
|
||||||
Subject: Test Message rspamd/pass.txt
|
|
||||||
This mail should pass and Rspamd should not mark it.
|
|
|
@ -1,5 +0,0 @@
|
||||||
From: Docker Mail Server <spam-header@example.test>
|
|
||||||
To: Existing Local User <user1@localhost.localdomain>
|
|
||||||
Date: Sat, 21 Jan 2023 11:11:11 +0000
|
|
||||||
Subject: Test Message rspamd-spam-header.txt
|
|
||||||
YJS*C4JDBQADN1.NSBN3*2IDNEN*GTUBE-STANDARD-ANTI-UBE-TEST-EMAIL*C.34X
|
|
|
@ -1,5 +0,0 @@
|
||||||
From: Docker Mail Server <spam@example.test>
|
|
||||||
To: Existing Local User <user1@localhost.localdomain>
|
|
||||||
Date: Sat, 21 Jan 2023 11:11:11 +0000
|
|
||||||
Subject: Test Message rspamd-spam.txt
|
|
||||||
XJS*C4JDBQADN1.NSBN3*2IDNEN*GTUBE-STANDARD-ANTI-UBE-TEST-EMAIL*C.34X
|
|
|
@ -1,5 +0,0 @@
|
||||||
From: Docker Mail Server <virus@example.test>
|
|
||||||
To: Existing Local User <user1@localhost.localdomain>
|
|
||||||
Date: Sat, 21 Jan 2023 11:11:11 +0000
|
|
||||||
Subject: Test Message rspamd-virus.txt
|
|
||||||
X5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*
|
|
|
@ -466,7 +466,7 @@ function _print_mail_log_for_id() {
|
||||||
local MAIL_ID=${1:?Mail ID must be provided}
|
local MAIL_ID=${1:?Mail ID must be provided}
|
||||||
local CONTAINER_NAME=$(__handle_container_name "${2:-}")
|
local CONTAINER_NAME=$(__handle_container_name "${2:-}")
|
||||||
|
|
||||||
_run_in_container grep -F "${MAIL_ID}" /var/log/mail.log
|
_run_in_container grep -E "${MAIL_ID}" /var/log/mail.log
|
||||||
}
|
}
|
||||||
|
|
||||||
# A simple wrapper for netcat (`nc`). This is useful when sending
|
# A simple wrapper for netcat (`nc`). This is useful when sending
|
||||||
|
@ -480,7 +480,7 @@ function _nc_wrapper() {
|
||||||
|
|
||||||
[[ -v CONTAINER_NAME ]] || return 1
|
[[ -v CONTAINER_NAME ]] || return 1
|
||||||
|
|
||||||
_run_in_container_bash "nc ${NC_PARAMETERS} < /tmp/docker-mailserver-test/${FILE}.txt"
|
_run_in_container_bash "nc ${NC_PARAMETERS} < /tmp/docker-mailserver-test/${FILE}"
|
||||||
}
|
}
|
||||||
|
|
||||||
# ? << Miscellaneous helper functions
|
# ? << Miscellaneous helper functions
|
||||||
|
|
|
@ -7,68 +7,118 @@
|
||||||
# ! ATTENTION: This file is loaded by `common.sh` - do not load it yourself!
|
# ! ATTENTION: This file is loaded by `common.sh` - do not load it yourself!
|
||||||
# ! ATTENTION: This file requires helper functions from `common.sh`!
|
# ! ATTENTION: This file requires helper functions from `common.sh`!
|
||||||
|
|
||||||
# Sends a mail from localhost (127.0.0.1) to a container. To send
|
# Sends an e-mail from the container named by the environment variable `CONTAINER_NAME`
|
||||||
# a custom email, create a file at `test/files/<TEST FILE>`,
|
# to the same or another container.
|
||||||
# and provide `<TEST FILE>` as an argument to this function.
|
|
||||||
#
|
#
|
||||||
# Parameters include all options that one can supply to `swaks`
|
# To send a custom email, you can
|
||||||
# itself. The `--data` parameter expects a relative path from `emails/`
|
#
|
||||||
# where the contents will be implicitly provided to `swaks` via STDIN.
|
# 1. create a file at `test/files/<TEST FILE>` and provide `<TEST FILE>` via `--data` as an argument to this function;
|
||||||
|
# 2. use this function without the `--data` argument, in which case we provide a default;
|
||||||
|
# 3. provide data inline (`--data <INLINE DATA>`).
|
||||||
|
#
|
||||||
|
# The very first parameter **may** be `--expect-rejection` - use it of you expect the mail transaction to not finish
|
||||||
|
# successfully. All other (following) parameters include all options that one can supply to `swaks` itself.
|
||||||
|
# As mentioned before, the `--data` parameter expects a value of either:
|
||||||
|
#
|
||||||
|
# - A relative path from `test/files/emails/`
|
||||||
|
# - An "inline" data string (e.g., `Date: 1 Jan 2024\nSubject: This is a test`)
|
||||||
|
#
|
||||||
|
# ## Output
|
||||||
|
#
|
||||||
|
# This functions prints the output of the transaction that `swaks` prints.
|
||||||
#
|
#
|
||||||
# ## Attention
|
# ## Attention
|
||||||
#
|
#
|
||||||
# This function assumes `CONTAINER_NAME` to be properly set (to the container
|
# This function assumes `CONTAINER_NAME` to be properly set (to the container
|
||||||
# name the command should be executed in)!
|
# name the command should be executed in)!
|
||||||
#
|
#
|
||||||
# This function will just send the email in an "asynchronous" fashion, i.e. it will
|
# This function will send the email in an "asynchronous" fashion,
|
||||||
# send the email but it will not make sure the mail queue is empty after the mail
|
# it will return without waiting for the Postfix mail queue to be emptied.
|
||||||
# has been sent.
|
|
||||||
function _send_email() {
|
function _send_email() {
|
||||||
[[ -v CONTAINER_NAME ]] || return 1
|
local RETURN_VALUE=0
|
||||||
|
local COMMAND_STRING
|
||||||
|
|
||||||
# Parameter defaults common to our testing needs:
|
function __parse_arguments() {
|
||||||
local EHLO='mail.external.tld'
|
[[ -v CONTAINER_NAME ]] || return 1
|
||||||
local FROM='user@external.tld'
|
|
||||||
local TO='user1@localhost.localdomain'
|
|
||||||
local SERVER='0.0.0.0'
|
|
||||||
local PORT=25
|
|
||||||
# Extra options for `swaks` that aren't covered by the default options above:
|
|
||||||
local ADDITIONAL_SWAKS_OPTIONS=()
|
|
||||||
# Specifically for handling `--data` option below:
|
|
||||||
local FINAL_SWAKS_OPTIONS=()
|
|
||||||
|
|
||||||
while [[ ${#} -gt 0 ]]; do
|
# Parameter defaults common to our testing needs:
|
||||||
case "${1}" in
|
local EHLO='mail.external.tld'
|
||||||
( '--ehlo' ) EHLO=${2:?--ehlo given but no argument} ; shift 2 ;;
|
local FROM='user@external.tld'
|
||||||
( '--from' ) FROM=${2:?--from given but no argument} ; shift 2 ;;
|
local TO='user1@localhost.localdomain'
|
||||||
( '--to' ) TO=${2:?--to given but no argument} ; shift 2 ;;
|
local SERVER='0.0.0.0'
|
||||||
( '--server' ) SERVER=${2:?--server given but no argument} ; shift 2 ;;
|
local PORT=25
|
||||||
( '--port' ) PORT=${2:?--port given but no argument} ; shift 2 ;;
|
# Extra options for `swaks` that aren't covered by the default options above:
|
||||||
( '--data' )
|
local ADDITIONAL_SWAKS_OPTIONS=()
|
||||||
local TEMPLATE_FILE="/tmp/docker-mailserver-test/emails/${2:?--data given but no argument provided}.txt"
|
local DATA_WAS_SUPPLIED=0
|
||||||
FINAL_SWAKS_OPTIONS+=('--data')
|
|
||||||
FINAL_SWAKS_OPTIONS+=('-')
|
|
||||||
FINAL_SWAKS_OPTIONS+=('<')
|
|
||||||
FINAL_SWAKS_OPTIONS+=("${TEMPLATE_FILE}")
|
|
||||||
shift 2
|
|
||||||
;;
|
|
||||||
( * ) ADDITIONAL_SWAKS_OPTIONS+=("${1}") ; shift 1 ;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
|
|
||||||
_run_in_container_bash "swaks --server ${SERVER} --port ${PORT} --ehlo ${EHLO} --from ${FROM} --to ${TO} ${ADDITIONAL_SWAKS_OPTIONS[*]} ${FINAL_SWAKS_OPTIONS[*]}"
|
while [[ ${#} -gt 0 ]]; do
|
||||||
|
case "${1}" in
|
||||||
|
( '--ehlo' ) EHLO=${2:?--ehlo given but no argument} ; shift 2 ;;
|
||||||
|
( '--from' ) FROM=${2:?--from given but no argument} ; shift 2 ;;
|
||||||
|
( '--to' ) TO=${2:?--to given but no argument} ; shift 2 ;;
|
||||||
|
( '--server' ) SERVER=${2:?--server given but no argument} ; shift 2 ;;
|
||||||
|
( '--port' ) PORT=${2:?--port given but no argument} ; shift 2 ;;
|
||||||
|
( '--data' )
|
||||||
|
ADDITIONAL_SWAKS_OPTIONS+=('--data')
|
||||||
|
local FILE_PATH="/tmp/docker-mailserver-test/emails/${2:?--data given but no argument provided}"
|
||||||
|
if _exec_in_container_bash "[[ -e ${FILE_PATH} ]]"; then
|
||||||
|
ADDITIONAL_SWAKS_OPTIONS+=("@${FILE_PATH}")
|
||||||
|
else
|
||||||
|
ADDITIONAL_SWAKS_OPTIONS+=("'${2}'")
|
||||||
|
fi
|
||||||
|
shift 2
|
||||||
|
DATA_WAS_SUPPLIED=1
|
||||||
|
;;
|
||||||
|
( * ) ADDITIONAL_SWAKS_OPTIONS+=("'${1}'") ; shift 1 ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
if [[ ${DATA_WAS_SUPPLIED} -eq 0 ]]; then
|
||||||
|
# Fallback template (without the implicit `Message-Id` + `X-Mailer` headers from swaks):
|
||||||
|
# NOTE: It is better to let Postfix generate and append the `Message-Id` header itself,
|
||||||
|
# as it will contain the Queue ID for tracking in logs (which is also returned in swaks output).
|
||||||
|
ADDITIONAL_SWAKS_OPTIONS+=('--data')
|
||||||
|
ADDITIONAL_SWAKS_OPTIONS+=("'Date: %DATE%\nTo: %TO_ADDRESS%\nFrom: %FROM_ADDRESS%\nSubject: test %DATE%\n%NEW_HEADERS%\n%BODY%\n'")
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "swaks --server '${SERVER}' --port '${PORT}' --ehlo '${EHLO}' --from '${FROM}' --to '${TO}' ${ADDITIONAL_SWAKS_OPTIONS[*]}"
|
||||||
|
}
|
||||||
|
|
||||||
|
if [[ ${1:-} == --expect-rejection ]]; then
|
||||||
|
shift 1
|
||||||
|
COMMAND_STRING=$(__parse_arguments "${@}")
|
||||||
|
_run_in_container_bash "${COMMAND_STRING}"
|
||||||
|
RETURN_VALUE=${?}
|
||||||
|
else
|
||||||
|
COMMAND_STRING=$(__parse_arguments "${@}")
|
||||||
|
_run_in_container_bash "${COMMAND_STRING}"
|
||||||
|
assert_success
|
||||||
|
fi
|
||||||
|
|
||||||
|
# shellcheck disable=SC2154
|
||||||
|
echo "${output}"
|
||||||
|
return "${RETURN_VALUE}"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Like `_send_email` with two major differences:
|
# Like `_send_email` with two major differences:
|
||||||
#
|
#
|
||||||
# 1. this function waits for the mail to be processed; there is no asynchronicity
|
# 1. this function waits for the mail to be processed; there is no asynchronicity
|
||||||
# because filtering the logs in a synchronous way is easier and safer!
|
# because filtering the logs in a synchronous way is easier and safer;
|
||||||
# 2. this function prints an ID one can later filter by to check logs
|
# 2. this function takes the name of a variable and inserts IDs one can later
|
||||||
|
# filter by to check logs.
|
||||||
#
|
#
|
||||||
# No. 2 is especially useful in case you send more than one email in a single
|
# No. 2 is especially useful in case you send more than one email in a single
|
||||||
# test file and need to assert certain log entries for each mail individually.
|
# test file and need to assert certain log entries for each mail individually.
|
||||||
#
|
#
|
||||||
# This function takes the same arguments as `_send_mail`.
|
# The first argument has to be the name of the variable that the e-mail ID is stored in.
|
||||||
|
# The second argument **can** be the flag `--expect-rejection`.
|
||||||
|
#
|
||||||
|
# - If this flag is supplied, the function does not check whether the whole mail delivery
|
||||||
|
# transaction was successful. Additionally the queue ID will be retrieved differently.
|
||||||
|
# - CAUTION: It must still be possible to `grep` for the Message-ID that Postfix
|
||||||
|
# generated in the mail log; otherwise this function fails.
|
||||||
|
#
|
||||||
|
# The rest of the arguments are the same as `_send_email`.
|
||||||
#
|
#
|
||||||
# ## Attention
|
# ## Attention
|
||||||
#
|
#
|
||||||
|
@ -82,20 +132,35 @@ function _send_email() {
|
||||||
# chosen. Sending more than one mail at any given point in time with this function
|
# chosen. Sending more than one mail at any given point in time with this function
|
||||||
# is UNDEFINED BEHAVIOR!
|
# is UNDEFINED BEHAVIOR!
|
||||||
function _send_email_and_get_id() {
|
function _send_email_and_get_id() {
|
||||||
[[ -v CONTAINER_NAME ]] || return 1
|
# Export the variable denoted by ${1} so everyone has access
|
||||||
|
export "${1:?Mail ID must be set for _send_email_and_get_id}"
|
||||||
|
# Get a "reference" to the content of the variable denoted by ${1} so we can manipulate the content
|
||||||
|
local -n ID_ENV_VAR_REF=${1:?}
|
||||||
|
# Prepare the message ID header here because we will shift away ${1} later
|
||||||
|
local MID="<${1}@dms-tests>"
|
||||||
|
# Get rid of ${1} so only the arguments for swaks remain
|
||||||
|
shift 1
|
||||||
|
|
||||||
_wait_for_empty_mail_queue_in_container
|
local QUEUE_ID
|
||||||
_send_email "${@}"
|
|
||||||
_wait_for_empty_mail_queue_in_container
|
|
||||||
|
|
||||||
local MAIL_ID
|
|
||||||
# The unique ID Postfix (and other services) use may be different in length
|
# The unique ID Postfix (and other services) use may be different in length
|
||||||
# on different systems (e.g. amd64 (11) vs aarch64 (10)). Hence, we use a
|
# on different systems (e.g. amd64 (11) vs aarch64 (10)). Hence, we use a
|
||||||
# range to safely capture it.
|
# range to safely capture it.
|
||||||
MAIL_ID=$(_exec_in_container tac /var/log/mail.log \
|
local QUEUE_ID_REGEX='[A-Z0-9]{9,12}'
|
||||||
| grep -E -m 1 'postfix/smtpd.*: [A-Z0-9]+: client=localhost' \
|
|
||||||
| grep -E -o '[A-Z0-9]{9,12}' || true)
|
|
||||||
|
|
||||||
assert_not_equal "${MAIL_ID}" ''
|
_wait_for_empty_mail_queue_in_container
|
||||||
echo "${MAIL_ID}"
|
local OUTPUT=$(_send_email "${@}" --header "Message-Id: ${MID}")
|
||||||
|
_wait_for_empty_mail_queue_in_container
|
||||||
|
|
||||||
|
# We store Postfix's queue ID first
|
||||||
|
ID_ENV_VAR_REF=$(_exec_in_container tac /var/log/mail.log \
|
||||||
|
| grep -E "postfix/cleanup.*: ${QUEUE_ID_REGEX}:.*message-id=${MID}" \
|
||||||
|
| grep -E --only-matching --max-count 1 "${QUEUE_ID_REGEX}" || :)
|
||||||
|
# But we also requre potential Dovecot sieve output, which requires the mesage ID,
|
||||||
|
# so we need to provide the message ID too.
|
||||||
|
ID_ENV_VAR_REF+="|${MID}"
|
||||||
|
|
||||||
|
# Last but not least, we perform plausibility checks on the IDs.
|
||||||
|
assert_not_equal "${ID_ENV_VAR_REF}" ''
|
||||||
|
run echo "${ID_ENV_VAR_REF}"
|
||||||
|
assert_line --regexp "^${QUEUE_ID_REGEX}\|${MID}$"
|
||||||
}
|
}
|
||||||
|
|
|
@ -225,12 +225,9 @@ function teardown_file() { _default_teardown ; }
|
||||||
sleep 10
|
sleep 10
|
||||||
|
|
||||||
# send some big emails
|
# send some big emails
|
||||||
_send_email --to 'quotauser@otherdomain.tld' --data 'quota-exceeded'
|
_send_email --to 'quotauser@otherdomain.tld' --data 'quota-exceeded.txt'
|
||||||
assert_success
|
_send_email --to 'quotauser@otherdomain.tld' --data 'quota-exceeded.txt'
|
||||||
_send_email --to 'quotauser@otherdomain.tld' --data 'quota-exceeded'
|
_send_email --to 'quotauser@otherdomain.tld' --data 'quota-exceeded.txt'
|
||||||
assert_success
|
|
||||||
_send_email --to 'quotauser@otherdomain.tld' --data 'quota-exceeded'
|
|
||||||
assert_success
|
|
||||||
# check for quota warn message existence
|
# check for quota warn message existence
|
||||||
run _repeat_until_success_or_timeout 20 _exec_in_container grep -R 'Subject: quota warning' /var/mail/otherdomain.tld/quotauser/new/
|
run _repeat_until_success_or_timeout 20 _exec_in_container grep -R 'Subject: quota warning' /var/mail/otherdomain.tld/quotauser/new/
|
||||||
assert_success
|
assert_success
|
||||||
|
|
|
@ -26,11 +26,9 @@ function setup_file() {
|
||||||
_wait_for_smtp_port_in_container
|
_wait_for_smtp_port_in_container
|
||||||
|
|
||||||
# Single mail sent from 'spam@spam.com' that is handled by User (relocate) and Global (copy) sieves for user1:
|
# Single mail sent from 'spam@spam.com' that is handled by User (relocate) and Global (copy) sieves for user1:
|
||||||
_send_email --data 'sieve/spam-folder'
|
_send_email --data 'sieve/spam-folder.txt'
|
||||||
assert_success
|
|
||||||
# Mail for user2 triggers the sieve-pipe:
|
# Mail for user2 triggers the sieve-pipe:
|
||||||
_send_email --to 'user2@otherdomain.tld' --data 'sieve/pipe'
|
_send_email --to 'user2@otherdomain.tld' --data 'sieve/pipe.txt'
|
||||||
assert_success
|
|
||||||
|
|
||||||
_wait_for_empty_mail_queue_in_container
|
_wait_for_empty_mail_queue_in_container
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,8 +26,7 @@ function teardown() { _default_teardown ; }
|
||||||
_common_container_setup 'CUSTOM_SETUP_ARGUMENTS'
|
_common_container_setup 'CUSTOM_SETUP_ARGUMENTS'
|
||||||
_wait_for_smtp_port_in_container
|
_wait_for_smtp_port_in_container
|
||||||
|
|
||||||
_send_email --data 'existing/user1'
|
_send_email
|
||||||
assert_success
|
|
||||||
_wait_for_empty_mail_queue_in_container
|
_wait_for_empty_mail_queue_in_container
|
||||||
|
|
||||||
# Mail received should be stored as `u.1` (one file per message)
|
# Mail received should be stored as `u.1` (one file per message)
|
||||||
|
@ -48,8 +47,7 @@ function teardown() { _default_teardown ; }
|
||||||
_common_container_setup 'CUSTOM_SETUP_ARGUMENTS'
|
_common_container_setup 'CUSTOM_SETUP_ARGUMENTS'
|
||||||
_wait_for_smtp_port_in_container
|
_wait_for_smtp_port_in_container
|
||||||
|
|
||||||
_send_email --data 'existing/user1'
|
_send_email
|
||||||
assert_success
|
|
||||||
_wait_for_empty_mail_queue_in_container
|
_wait_for_empty_mail_queue_in_container
|
||||||
|
|
||||||
# Mail received should be stored in `m.1` (1 or more messages)
|
# Mail received should be stored in `m.1` (1 or more messages)
|
||||||
|
|
|
@ -14,8 +14,7 @@ function setup_file() {
|
||||||
function teardown_file() { _default_teardown ; }
|
function teardown_file() { _default_teardown ; }
|
||||||
|
|
||||||
@test 'normal delivery works' {
|
@test 'normal delivery works' {
|
||||||
_send_email --data 'existing/user1'
|
_send_email
|
||||||
assert_success
|
|
||||||
_count_files_in_directory_in_container /var/mail/localhost.localdomain/user1/new 1
|
_count_files_in_directory_in_container /var/mail/localhost.localdomain/user1/new 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,7 +26,7 @@ function teardown_file() { _default_teardown ; }
|
||||||
}
|
}
|
||||||
|
|
||||||
@test "(IMAP) special-use folders should be created when necessary" {
|
@test "(IMAP) special-use folders should be created when necessary" {
|
||||||
_nc_wrapper 'nc/imap_special_use_folders' '-w 8 0.0.0.0 143'
|
_nc_wrapper 'nc/imap_special_use_folders.txt' '-w 8 0.0.0.0 143'
|
||||||
assert_output --partial 'Drafts'
|
assert_output --partial 'Drafts'
|
||||||
assert_output --partial 'Junk'
|
assert_output --partial 'Junk'
|
||||||
assert_output --partial 'Trash'
|
assert_output --partial 'Trash'
|
||||||
|
|
|
@ -25,15 +25,14 @@ function setup_file() {
|
||||||
|
|
||||||
_wait_for_service postfix
|
_wait_for_service postfix
|
||||||
_wait_for_smtp_port_in_container
|
_wait_for_smtp_port_in_container
|
||||||
_send_email --from 'virus@external.tld' --data 'amavis/virus'
|
_send_email --from 'virus@external.tld' --data 'amavis/virus.txt'
|
||||||
assert_success
|
|
||||||
_wait_for_empty_mail_queue_in_container
|
_wait_for_empty_mail_queue_in_container
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,8 +18,7 @@ function setup_file() {
|
||||||
_common_container_setup 'CUSTOM_SETUP_ARGUMENTS'
|
_common_container_setup 'CUSTOM_SETUP_ARGUMENTS'
|
||||||
_wait_for_smtp_port_in_container
|
_wait_for_smtp_port_in_container
|
||||||
|
|
||||||
_send_email --data 'existing/user1'
|
_send_email
|
||||||
assert_success
|
|
||||||
_wait_for_empty_mail_queue_in_container
|
_wait_for_empty_mail_queue_in_container
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -74,7 +74,7 @@ function teardown_file() {
|
||||||
CONTAINER1_IP=$(_get_container_ip "${CONTAINER1_NAME}")
|
CONTAINER1_IP=$(_get_container_ip "${CONTAINER1_NAME}")
|
||||||
# Trigger a ban by failing to login twice:
|
# Trigger a ban by failing to login twice:
|
||||||
for _ in {1..2}; do
|
for _ in {1..2}; do
|
||||||
CONTAINER_NAME=${CONTAINER2_NAME} _send_email \
|
CONTAINER_NAME=${CONTAINER2_NAME} _send_email --expect-rejection \
|
||||||
--server "${CONTAINER1_IP}" \
|
--server "${CONTAINER1_IP}" \
|
||||||
--port 465 \
|
--port 465 \
|
||||||
--auth PLAIN \
|
--auth PLAIN \
|
||||||
|
|
|
@ -51,7 +51,7 @@ function teardown_file() { _default_teardown ; }
|
||||||
_reload_postfix
|
_reload_postfix
|
||||||
|
|
||||||
# Send test mail (it should fail to deliver):
|
# Send test mail (it should fail to deliver):
|
||||||
_send_email --from 'user@external.tld' --port 25 --data 'postgrey'
|
_send_email --expect-rejection --from 'user@external.tld' --port 25 --data 'postgrey.txt'
|
||||||
assert_failure
|
assert_failure
|
||||||
assert_output --partial 'Recipient address rejected: Delayed by Postgrey'
|
assert_output --partial 'Recipient address rejected: Delayed by Postgrey'
|
||||||
|
|
||||||
|
@ -67,8 +67,7 @@ function teardown_file() { _default_teardown ; }
|
||||||
# Wait until `$POSTGREY_DELAY` seconds pass before trying again:
|
# Wait until `$POSTGREY_DELAY` seconds pass before trying again:
|
||||||
sleep 3
|
sleep 3
|
||||||
# Retry delivering test mail (it should be trusted this time):
|
# Retry delivering test mail (it should be trusted this time):
|
||||||
_send_email --from 'user@external.tld' --port 25 --data 'postgrey'
|
_send_email --from 'user@external.tld' --port 25 --data 'postgrey.txt'
|
||||||
assert_success
|
|
||||||
|
|
||||||
# Confirm postgrey permitted delivery (triplet is now trusted):
|
# Confirm postgrey permitted delivery (triplet is now trusted):
|
||||||
_should_have_log_entry \
|
_should_have_log_entry \
|
||||||
|
@ -87,7 +86,7 @@ function teardown_file() { _default_teardown ; }
|
||||||
# - It'd also cause the earlier greylist test to fail.
|
# - It'd also cause the earlier greylist test to fail.
|
||||||
# - TODO: Actually confirm whitelist feature works correctly as these test cases are using a workaround:
|
# - TODO: Actually confirm whitelist feature works correctly as these test cases are using a workaround:
|
||||||
@test "should whitelist sender 'user@whitelist.tld'" {
|
@test "should whitelist sender 'user@whitelist.tld'" {
|
||||||
_nc_wrapper 'nc/postgrey_whitelist' '-w 0 0.0.0.0 10023'
|
_nc_wrapper 'nc/postgrey_whitelist.txt' '-w 0 0.0.0.0 10023'
|
||||||
|
|
||||||
_should_have_log_entry \
|
_should_have_log_entry \
|
||||||
'action=pass' \
|
'action=pass' \
|
||||||
|
@ -96,7 +95,7 @@ function teardown_file() { _default_teardown ; }
|
||||||
}
|
}
|
||||||
|
|
||||||
@test "should whitelist recipient 'user2@otherdomain.tld'" {
|
@test "should whitelist recipient 'user2@otherdomain.tld'" {
|
||||||
_nc_wrapper 'nc/postgrey_whitelist_recipients' '-w 0 0.0.0.0 10023'
|
_nc_wrapper 'nc/postgrey_whitelist_recipients.txt' '-w 0 0.0.0.0 10023'
|
||||||
|
|
||||||
_should_have_log_entry \
|
_should_have_log_entry \
|
||||||
'action=pass' \
|
'action=pass' \
|
||||||
|
|
|
@ -44,7 +44,7 @@ function teardown_file() {
|
||||||
# Use `nc` to send all SMTP commands at once instead (emulate a misbehaving client that should be rejected)
|
# Use `nc` to send all SMTP commands at once instead (emulate a misbehaving client that should be rejected)
|
||||||
# NOTE: Postscreen only runs on port 25, avoid implicit ports in test methods
|
# NOTE: Postscreen only runs on port 25, avoid implicit ports in test methods
|
||||||
@test 'should fail send when talking out of turn' {
|
@test 'should fail send when talking out of turn' {
|
||||||
CONTAINER_NAME=${CONTAINER2_NAME} _nc_wrapper 'emails/nc_raw/postscreen' "${CONTAINER1_IP} 25"
|
CONTAINER_NAME=${CONTAINER2_NAME} _nc_wrapper 'emails/nc_raw/postscreen.txt' "${CONTAINER1_IP} 25"
|
||||||
# Expected postscreen log entry:
|
# Expected postscreen log entry:
|
||||||
assert_output --partial 'Protocol error'
|
assert_output --partial 'Protocol error'
|
||||||
|
|
||||||
|
@ -56,14 +56,10 @@ function teardown_file() {
|
||||||
@test "should successfully pass postscreen and get postfix greeting message (respecting postscreen_greet_wait time)" {
|
@test "should successfully pass postscreen and get postfix greeting message (respecting postscreen_greet_wait time)" {
|
||||||
# Configure `send_email()` to send from the mail client container (CONTAINER2_NAME) via ENV override,
|
# Configure `send_email()` to send from the mail client container (CONTAINER2_NAME) via ENV override,
|
||||||
# mail is sent to the DMS server container (CONTAINER1_NAME) via `--server` parameter:
|
# mail is sent to the DMS server container (CONTAINER1_NAME) via `--server` parameter:
|
||||||
CONTAINER_NAME=${CONTAINER2_NAME} _send_email --server "${CONTAINER1_IP}" --port 25 --data 'postscreen'
|
# TODO: Use _send_email_and_get_id when proper resolution of domain names is possible:
|
||||||
# NOTE: Cannot assert_success due to sender address not being resolvable.
|
CONTAINER_NAME=${CONTAINER2_NAME} _send_email --expect-rejection --server "${CONTAINER1_IP}" --port 25 --data 'postscreen.txt'
|
||||||
# TODO: Uncomment when proper resolution of domain names is possible:
|
# CONTAINER_NAME=${CONTAINER2_NAME} _send_email_and_get_id MAIL_ID_POSTSCREEN --server "${CONTAINER1_IP}" --data 'postscreen.txt'
|
||||||
# assert_success
|
# _print_mail_log_for_id "${MAIL_ID_POSTSCREEN}"
|
||||||
|
|
||||||
# TODO: Prefer this approach when `_send_email_and_get_id()` can support separate client and server containers:
|
|
||||||
# local MAIL_ID=$(_send_email_and_get_id --port 25 --data 'postscreen')
|
|
||||||
# _print_mail_log_for_id "${MAIL_ID}"
|
|
||||||
# assert_output --partial "stored mail into mailbox 'INBOX'"
|
# assert_output --partial "stored mail into mailbox 'INBOX'"
|
||||||
|
|
||||||
_run_in_container cat /var/log/mail.log
|
_run_in_container cat /var/log/mail.log
|
||||||
|
|
|
@ -43,16 +43,24 @@ function setup_file() {
|
||||||
_wait_for_service postfix
|
_wait_for_service postfix
|
||||||
_wait_for_smtp_port_in_container
|
_wait_for_smtp_port_in_container
|
||||||
|
|
||||||
# We will send 3 emails: the first one should pass just fine; the second one should
|
# ref: https://rspamd.com/doc/gtube_patterns.html
|
||||||
# be rejected due to spam; the third one should be rejected due to a virus.
|
local GTUBE_SUFFIX='*C4JDBQADN1.NSBN3*2IDNEN*GTUBE-STANDARD-ANTI-UBE-TEST-EMAIL*C.34X'
|
||||||
export MAIL_ID1=$(_send_email_and_get_id --from 'rspamd-pass@example.test' --data 'rspamd/pass')
|
|
||||||
export MAIL_ID2=$(_send_email_and_get_id --from 'rspamd-spam@example.test' --data 'rspamd/spam')
|
|
||||||
export MAIL_ID3=$(_send_email_and_get_id --from 'rspamd-virus@example.test' --data 'rspamd/virus')
|
|
||||||
export MAIL_ID4=$(_send_email_and_get_id --from 'rspamd-spam-header@example.test' --data 'rspamd/spam-header')
|
|
||||||
|
|
||||||
for ID in MAIL_ID{1,2,3,4}; do
|
# We will send 4 emails:
|
||||||
[[ -n ${!ID} ]] || { echo "${ID} is empty - aborting!" ; return 1 ; }
|
# 1. The first one should pass just fine
|
||||||
done
|
_send_email_and_get_id MAIL_ID_PASS
|
||||||
|
# 2. The second one should be rejected (GTUBE pattern)
|
||||||
|
_send_email_and_get_id MAIL_ID_REJECT --expect-rejection --body "XJS${GTUBE_SUFFIX}"
|
||||||
|
# 3. The third one should be rejected due to a virus (ClamAV EICAR pattern)
|
||||||
|
# shellcheck disable=SC2016
|
||||||
|
_send_email_and_get_id MAIL_ID_VIRUS --expect-rejection \
|
||||||
|
--body 'X5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*'
|
||||||
|
# 4. The fourth one will receive an added header (GTUBE pattern)
|
||||||
|
_send_email_and_get_id MAIL_ID_HEADER --body "YJS${GTUBE_SUFFIX}"
|
||||||
|
|
||||||
|
_run_in_container cat /var/log/mail.log
|
||||||
|
assert_success
|
||||||
|
refute_output --partial 'inet:localhost:11332: Connection refused'
|
||||||
}
|
}
|
||||||
|
|
||||||
function teardown_file() { _default_teardown ; }
|
function teardown_file() { _default_teardown ; }
|
||||||
|
@ -104,7 +112,7 @@ function teardown_file() { _default_teardown ; }
|
||||||
@test 'normal mail passes fine' {
|
@test 'normal mail passes fine' {
|
||||||
_service_log_should_contain_string 'rspamd' 'F \(no action\)'
|
_service_log_should_contain_string 'rspamd' 'F \(no action\)'
|
||||||
|
|
||||||
_print_mail_log_for_id "${MAIL_ID1}"
|
_print_mail_log_for_id "${MAIL_ID_PASS}"
|
||||||
assert_output --partial "stored mail into mailbox 'INBOX'"
|
assert_output --partial "stored mail into mailbox 'INBOX'"
|
||||||
|
|
||||||
_count_files_in_directory_in_container /var/mail/localhost.localdomain/user1/new/ 1
|
_count_files_in_directory_in_container /var/mail/localhost.localdomain/user1/new/ 1
|
||||||
|
@ -114,7 +122,7 @@ function teardown_file() { _default_teardown ; }
|
||||||
_service_log_should_contain_string 'rspamd' 'S \(reject\)'
|
_service_log_should_contain_string 'rspamd' 'S \(reject\)'
|
||||||
_service_log_should_contain_string 'rspamd' 'reject "Gtube pattern"'
|
_service_log_should_contain_string 'rspamd' 'reject "Gtube pattern"'
|
||||||
|
|
||||||
_print_mail_log_for_id "${MAIL_ID2}"
|
_print_mail_log_for_id "${MAIL_ID_REJECT}"
|
||||||
assert_output --partial 'milter-reject'
|
assert_output --partial 'milter-reject'
|
||||||
assert_output --partial '5.7.1 Gtube pattern'
|
assert_output --partial '5.7.1 Gtube pattern'
|
||||||
|
|
||||||
|
@ -125,7 +133,7 @@ function teardown_file() { _default_teardown ; }
|
||||||
_service_log_should_contain_string 'rspamd' 'T \(reject\)'
|
_service_log_should_contain_string 'rspamd' 'T \(reject\)'
|
||||||
_service_log_should_contain_string 'rspamd' 'reject "ClamAV FOUND VIRUS "Eicar-Signature"'
|
_service_log_should_contain_string 'rspamd' 'reject "ClamAV FOUND VIRUS "Eicar-Signature"'
|
||||||
|
|
||||||
_print_mail_log_for_id "${MAIL_ID3}"
|
_print_mail_log_for_id "${MAIL_ID_VIRUS}"
|
||||||
assert_output --partial 'milter-reject'
|
assert_output --partial 'milter-reject'
|
||||||
assert_output --partial '5.7.1 ClamAV FOUND VIRUS "Eicar-Signature"'
|
assert_output --partial '5.7.1 ClamAV FOUND VIRUS "Eicar-Signature"'
|
||||||
refute_output --partial "stored mail into mailbox 'INBOX'"
|
refute_output --partial "stored mail into mailbox 'INBOX'"
|
||||||
|
@ -214,7 +222,7 @@ function teardown_file() { _default_teardown ; }
|
||||||
_service_log_should_contain_string 'rspamd' 'S \(add header\)'
|
_service_log_should_contain_string 'rspamd' 'S \(add header\)'
|
||||||
_service_log_should_contain_string 'rspamd' 'add header "Gtube pattern"'
|
_service_log_should_contain_string 'rspamd' 'add header "Gtube pattern"'
|
||||||
|
|
||||||
_print_mail_log_for_id "${MAIL_ID4}"
|
_print_mail_log_for_id "${MAIL_ID_HEADER}"
|
||||||
assert_output --partial "fileinto action: stored mail into mailbox 'Junk'"
|
assert_output --partial "fileinto action: stored mail into mailbox 'Junk'"
|
||||||
|
|
||||||
_count_files_in_directory_in_container /var/mail/localhost.localdomain/user1/new/ 1
|
_count_files_in_directory_in_container /var/mail/localhost.localdomain/user1/new/ 1
|
||||||
|
@ -256,7 +264,7 @@ function teardown_file() { _default_teardown ; }
|
||||||
|
|
||||||
# Move an email to the "Junk" folder from "INBOX"; the first email we
|
# Move an email to the "Junk" folder from "INBOX"; the first email we
|
||||||
# sent should pass fine, hence we can now move it.
|
# sent should pass fine, hence we can now move it.
|
||||||
_nc_wrapper 'nc/rspamd_imap_move_to_junk' '0.0.0.0 143'
|
_nc_wrapper 'nc/rspamd_imap_move_to_junk.txt' '0.0.0.0 143'
|
||||||
sleep 1 # wait for the transaction to finish
|
sleep 1 # wait for the transaction to finish
|
||||||
|
|
||||||
_run_in_container cat /var/log/mail/mail.log
|
_run_in_container cat /var/log/mail/mail.log
|
||||||
|
@ -270,7 +278,7 @@ function teardown_file() { _default_teardown ; }
|
||||||
# Move an email to the "INBOX" folder from "Junk"; there should be two mails
|
# Move an email to the "INBOX" folder from "Junk"; there should be two mails
|
||||||
# in the "Junk" folder, since the second email we sent during setup should
|
# in the "Junk" folder, since the second email we sent during setup should
|
||||||
# have landed in the Junk folder already.
|
# have landed in the Junk folder already.
|
||||||
_nc_wrapper 'nc/rspamd_imap_move_to_inbox' '0.0.0.0 143'
|
_nc_wrapper 'nc/rspamd_imap_move_to_inbox.txt' '0.0.0.0 143'
|
||||||
sleep 1 # wait for the transaction to finish
|
sleep 1 # wait for the transaction to finish
|
||||||
|
|
||||||
_run_in_container cat /var/log/mail/mail.log
|
_run_in_container cat /var/log/mail/mail.log
|
||||||
|
|
|
@ -95,7 +95,7 @@ function teardown() { _default_teardown ; }
|
||||||
function _should_send_spam_message() {
|
function _should_send_spam_message() {
|
||||||
_wait_for_smtp_port_in_container
|
_wait_for_smtp_port_in_container
|
||||||
_wait_for_tcp_port_in_container 10024 # port 10024 is for Amavis
|
_wait_for_tcp_port_in_container 10024 # port 10024 is for Amavis
|
||||||
_send_email --from 'spam@external.tld' --data 'amavis/spam'
|
_send_email --from 'spam@external.tld' --data 'amavis/spam.txt'
|
||||||
}
|
}
|
||||||
|
|
||||||
function _should_be_received_by_amavis() {
|
function _should_be_received_by_amavis() {
|
||||||
|
|
|
@ -207,7 +207,7 @@ function _should_have_correct_mail_headers() {
|
||||||
# (eg: OVERRIDE_HOSTNAME or `--hostname mail --domainname example.test`)
|
# (eg: OVERRIDE_HOSTNAME or `--hostname mail --domainname example.test`)
|
||||||
local EXPECTED_HOSTNAME=${3:-${EXPECTED_FQDN}}
|
local EXPECTED_HOSTNAME=${3:-${EXPECTED_FQDN}}
|
||||||
|
|
||||||
_send_email --from 'user@external.tld' --data 'existing/user1'
|
_send_email --from 'user@external.tld'
|
||||||
_wait_for_empty_mail_queue_in_container
|
_wait_for_empty_mail_queue_in_container
|
||||||
_count_files_in_directory_in_container '/var/mail/localhost.localdomain/user1/new/' '1'
|
_count_files_in_directory_in_container '/var/mail/localhost.localdomain/user1/new/' '1'
|
||||||
|
|
||||||
|
|
|
@ -49,9 +49,9 @@ function teardown_file() {
|
||||||
|
|
||||||
# TODO replace with _send_email as soon as it supports DSN
|
# TODO replace with _send_email as soon as it supports DSN
|
||||||
# TODO ref: https://github.com/jetmore/swaks/issues/41
|
# TODO ref: https://github.com/jetmore/swaks/issues/41
|
||||||
_nc_wrapper 'emails/nc_raw/dsn/unauthenticated'
|
_nc_wrapper 'emails/nc_raw/dsn/unauthenticated.txt'
|
||||||
_nc_wrapper 'emails/nc_raw/dsn/authenticated' '0.0.0.0 465'
|
_nc_wrapper 'emails/nc_raw/dsn/authenticated.txt' '0.0.0.0 465'
|
||||||
_nc_wrapper 'emails/nc_raw/dsn/authenticated' '0.0.0.0 587'
|
_nc_wrapper 'emails/nc_raw/dsn/authenticated.txt' '0.0.0.0 587'
|
||||||
_wait_for_empty_mail_queue_in_container
|
_wait_for_empty_mail_queue_in_container
|
||||||
|
|
||||||
_run_in_container grep "${LOG_DSN}" /var/log/mail/mail.log
|
_run_in_container grep "${LOG_DSN}" /var/log/mail/mail.log
|
||||||
|
@ -62,7 +62,7 @@ function teardown_file() {
|
||||||
@test "should only send a DSN when requested from ports 465/587" {
|
@test "should only send a DSN when requested from ports 465/587" {
|
||||||
export CONTAINER_NAME=${CONTAINER2_NAME}
|
export CONTAINER_NAME=${CONTAINER2_NAME}
|
||||||
|
|
||||||
_nc_wrapper 'emails/nc_raw/dsn/unauthenticated'
|
_nc_wrapper 'emails/nc_raw/dsn/unauthenticated.txt'
|
||||||
_wait_for_empty_mail_queue_in_container
|
_wait_for_empty_mail_queue_in_container
|
||||||
|
|
||||||
# DSN requests can now only be made on ports 465 and 587,
|
# DSN requests can now only be made on ports 465 and 587,
|
||||||
|
@ -74,8 +74,8 @@ function teardown_file() {
|
||||||
assert_failure
|
assert_failure
|
||||||
|
|
||||||
# These ports are excluded via master.cf.
|
# These ports are excluded via master.cf.
|
||||||
_nc_wrapper 'emails/nc_raw/dsn/authenticated' '0.0.0.0 465'
|
_nc_wrapper 'emails/nc_raw/dsn/authenticated.txt' '0.0.0.0 465'
|
||||||
_nc_wrapper 'emails/nc_raw/dsn/authenticated' '0.0.0.0 587'
|
_nc_wrapper 'emails/nc_raw/dsn/authenticated.txt' '0.0.0.0 587'
|
||||||
_wait_for_empty_mail_queue_in_container
|
_wait_for_empty_mail_queue_in_container
|
||||||
|
|
||||||
_run_in_container grep "${LOG_DSN}" /var/log/mail/mail.log
|
_run_in_container grep "${LOG_DSN}" /var/log/mail/mail.log
|
||||||
|
@ -85,9 +85,9 @@ function teardown_file() {
|
||||||
@test "should never send a DSN" {
|
@test "should never send a DSN" {
|
||||||
export CONTAINER_NAME=${CONTAINER3_NAME}
|
export CONTAINER_NAME=${CONTAINER3_NAME}
|
||||||
|
|
||||||
_nc_wrapper 'emails/nc_raw/dsn/unauthenticated'
|
_nc_wrapper 'emails/nc_raw/dsn/unauthenticated.txt'
|
||||||
_nc_wrapper 'emails/nc_raw/dsn/authenticated' '0.0.0.0 465'
|
_nc_wrapper 'emails/nc_raw/dsn/authenticated.txt' '0.0.0.0 465'
|
||||||
_nc_wrapper 'emails/nc_raw/dsn/authenticated' '0.0.0.0 587'
|
_nc_wrapper 'emails/nc_raw/dsn/authenticated.txt' '0.0.0.0 587'
|
||||||
_wait_for_empty_mail_queue_in_container
|
_wait_for_empty_mail_queue_in_container
|
||||||
|
|
||||||
# DSN requests are rejected regardless of origin.
|
# DSN requests are rejected regardless of origin.
|
||||||
|
|
|
@ -38,7 +38,7 @@ function teardown_file() { _default_teardown ; }
|
||||||
|
|
||||||
@test "delivers mail to existing account" {
|
@test "delivers mail to existing account" {
|
||||||
_wait_for_smtp_port_in_container
|
_wait_for_smtp_port_in_container
|
||||||
_send_email --data 'existing/user1' # send a test email
|
_send_email
|
||||||
|
|
||||||
# Verify delivery was successful, log line should look similar to:
|
# Verify delivery was successful, log line should look similar to:
|
||||||
# postfix/lmtp[1274]: 0EA424ABE7D9: to=<user1@localhost.localdomain>, relay=127.0.0.1[127.0.0.1]:24, delay=0.13, delays=0.07/0.01/0.01/0.05, dsn=2.0.0, status=sent (250 2.0.0 <user1@localhost.localdomain> ixPpB+Zvv2P7BAAAUi6ngw Saved)
|
# postfix/lmtp[1274]: 0EA424ABE7D9: to=<user1@localhost.localdomain>, relay=127.0.0.1[127.0.0.1]:24, delay=0.13, delays=0.07/0.01/0.01/0.05, dsn=2.0.0, status=sent (250 2.0.0 <user1@localhost.localdomain> ixPpB+Zvv2P7BAAAUi6ngw Saved)
|
||||||
|
|
|
@ -26,11 +26,10 @@ function teardown_file() { _default_teardown ; }
|
||||||
# this test covers https://github.com/docker-mailserver/docker-mailserver/issues/681
|
# this test covers https://github.com/docker-mailserver/docker-mailserver/issues/681
|
||||||
@test "(Postfix) remove privacy details of the sender" {
|
@test "(Postfix) remove privacy details of the sender" {
|
||||||
_send_email \
|
_send_email \
|
||||||
--port 587 -tls --auth LOGIN \
|
--port 587 -tls --auth PLAIN \
|
||||||
--auth-user user1@localhost.localdomain \
|
--auth-user user1@localhost.localdomain \
|
||||||
--auth-password mypassword \
|
--auth-password mypassword \
|
||||||
--data 'privacy'
|
--data 'privacy.txt'
|
||||||
assert_success
|
|
||||||
|
|
||||||
_run_until_success_or_timeout 120 _exec_in_container_bash '[[ -d /var/mail/localhost.localdomain/user1/new ]]'
|
_run_until_success_or_timeout 120 _exec_in_container_bash '[[ -d /var/mail/localhost.localdomain/user1/new ]]'
|
||||||
assert_success
|
assert_success
|
||||||
|
|
|
@ -63,46 +63,43 @@ function setup_file() {
|
||||||
|
|
||||||
# TODO: Move to clamav tests (For use when ClamAV is enabled):
|
# TODO: Move to clamav tests (For use when ClamAV is enabled):
|
||||||
# _repeat_in_container_until_success_or_timeout 60 "${CONTAINER_NAME}" test -e /var/run/clamav/clamd.ctl
|
# _repeat_in_container_until_success_or_timeout 60 "${CONTAINER_NAME}" test -e /var/run/clamav/clamd.ctl
|
||||||
# _send_email --from 'virus@external.tld' --data 'amavis/virus'
|
# _send_email --from 'virus@external.tld' --data 'amavis/virus.txt'
|
||||||
|
|
||||||
# Required for 'delivers mail to existing alias':
|
# Required for 'delivers mail to existing alias':
|
||||||
_send_email --to alias1@localhost.localdomain --data 'existing/alias-external'
|
_send_email --to alias1@localhost.localdomain --header "Subject: Test Message existing-alias-external"
|
||||||
# Required for 'delivers mail to existing alias with recipient delimiter':
|
# Required for 'delivers mail to existing alias with recipient delimiter':
|
||||||
_send_email --to alias1~test@localhost.localdomain --data 'existing/alias-recipient-delimiter'
|
_send_email --to alias1~test@localhost.localdomain --header 'Subject: Test Message existing-alias-recipient-delimiter'
|
||||||
# Required for 'delivers mail to existing catchall':
|
# Required for 'delivers mail to existing catchall':
|
||||||
_send_email --to wildcard@localdomain2.com --data 'existing/catchall-local'
|
_send_email --to wildcard@localdomain2.com --header 'Subject: Test Message existing-catchall-local'
|
||||||
# Required for 'delivers mail to regexp alias':
|
# Required for 'delivers mail to regexp alias':
|
||||||
_send_email --to test123@localhost.localdomain --data 'existing/regexp-alias-local'
|
_send_email --to test123@localhost.localdomain --header 'Subject: Test Message existing-regexp-alias-local'
|
||||||
|
|
||||||
# Required for 'rejects mail to unknown user':
|
# Required for 'rejects mail to unknown user':
|
||||||
_send_email --to nouser@localhost.localdomain --data 'non-existing-user'
|
_send_email --expect-rejection --to nouser@localhost.localdomain
|
||||||
|
assert_failure
|
||||||
# Required for 'redirects mail to external aliases':
|
# Required for 'redirects mail to external aliases':
|
||||||
_send_email --to bounce-always@localhost.localdomain --data 'existing/regexp-alias-external'
|
_send_email --to bounce-always@localhost.localdomain
|
||||||
_send_email --to alias2@localhost.localdomain --data 'existing/alias-local'
|
_send_email --to alias2@localhost.localdomain
|
||||||
# Required for 'rejects spam':
|
# Required for 'rejects spam':
|
||||||
_send_email --from 'spam@external.tld' --data 'amavis/spam'
|
_send_email --from 'spam@external.tld' --data 'amavis/spam.txt'
|
||||||
|
|
||||||
# Required for 'delivers mail to existing account':
|
# Required for 'delivers mail to existing account':
|
||||||
_send_email --data 'existing/user1'
|
_send_email --header 'Subject: Test Message existing-user1'
|
||||||
assert_success
|
|
||||||
_send_email --to user2@otherdomain.tld
|
_send_email --to user2@otherdomain.tld
|
||||||
assert_success
|
|
||||||
_send_email --to user3@localhost.localdomain
|
_send_email --to user3@localhost.localdomain
|
||||||
assert_success
|
_send_email --to added@localhost.localdomain --header 'Subject: Test Message existing-added'
|
||||||
_send_email --to added@localhost.localdomain --data 'existing/added'
|
_send_email \
|
||||||
assert_success
|
--to user1@localhost.localdomain \
|
||||||
_send_email --to user1@localhost.localdomain --data 'existing/user-and-cc-local-alias'
|
--header 'Subject: Test Message existing-user-and-cc-local-alias' \
|
||||||
assert_success
|
--cc 'alias2@localhost.localdomain'
|
||||||
_send_email --data 'sieve/spam-folder'
|
_send_email --data 'sieve/spam-folder.txt'
|
||||||
assert_success
|
_send_email --to user2@otherdomain.tld --data 'sieve/pipe.txt'
|
||||||
_send_email --to user2@otherdomain.tld --data 'sieve/pipe'
|
|
||||||
assert_success
|
|
||||||
_run_in_container_bash 'sendmail root < /tmp/docker-mailserver-test/emails/sendmail/root-email.txt'
|
_run_in_container_bash 'sendmail root < /tmp/docker-mailserver-test/emails/sendmail/root-email.txt'
|
||||||
assert_success
|
assert_success
|
||||||
}
|
}
|
||||||
|
|
||||||
function _unsuccessful() {
|
function _unsuccessful() {
|
||||||
_send_email --port 465 --auth "${1}" --auth-user "${2}" --auth-password wrongpassword
|
_send_email --expect-rejection --port 465 --auth "${1}" --auth-user "${2}" --auth-password wrongpassword --quit-after AUTH
|
||||||
assert_failure
|
assert_failure
|
||||||
assert_output --partial 'authentication failed'
|
assert_output --partial 'authentication failed'
|
||||||
assert_output --partial 'No authentication type succeeded'
|
assert_output --partial 'No authentication type succeeded'
|
||||||
|
@ -110,7 +107,6 @@ function _unsuccessful() {
|
||||||
|
|
||||||
function _successful() {
|
function _successful() {
|
||||||
_send_email --port 465 --auth "${1}" --auth-user "${2}" --auth-password mypassword --quit-after AUTH
|
_send_email --port 465 --auth "${1}" --auth-user "${2}" --auth-password mypassword --quit-after AUTH
|
||||||
assert_success
|
|
||||||
assert_output --partial 'Authentication successful'
|
assert_output --partial 'Authentication successful'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,12 +24,12 @@ function teardown_file() { _default_teardown ; }
|
||||||
}
|
}
|
||||||
|
|
||||||
@test 'authentication works' {
|
@test 'authentication works' {
|
||||||
_nc_wrapper 'auth/pop3-auth' '-w 1 0.0.0.0 110'
|
_nc_wrapper 'auth/pop3-auth.txt' '-w 1 0.0.0.0 110'
|
||||||
assert_success
|
assert_success
|
||||||
}
|
}
|
||||||
|
|
||||||
@test 'added user authentication works' {
|
@test 'added user authentication works' {
|
||||||
_nc_wrapper 'auth/added-pop3-auth' '-w 1 0.0.0.0 110'
|
_nc_wrapper 'auth/added-pop3-auth.txt' '-w 1 0.0.0.0 110'
|
||||||
assert_success
|
assert_success
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@ function setup_file() {
|
||||||
function teardown_file() { _default_teardown ; }
|
function teardown_file() { _default_teardown ; }
|
||||||
|
|
||||||
@test '(Dovecot) LDAP RIMAP connection and authentication works' {
|
@test '(Dovecot) LDAP RIMAP connection and authentication works' {
|
||||||
_nc_wrapper 'auth/imap-auth' '-w 1 0.0.0.0 143'
|
_nc_wrapper 'auth/imap-auth.txt' '-w 1 0.0.0.0 143'
|
||||||
assert_success
|
assert_success
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,8 +31,8 @@ function teardown_file() { _default_teardown ; }
|
||||||
}
|
}
|
||||||
|
|
||||||
@test '(SASLauthd) RIMAP SMTP authentication works' {
|
@test '(SASLauthd) RIMAP SMTP authentication works' {
|
||||||
_send_email \
|
_send_email --expect-rejection \
|
||||||
--auth LOGIN \
|
--auth PLAIN \
|
||||||
--auth-user user1@localhost.localdomain \
|
--auth-user user1@localhost.localdomain \
|
||||||
--auth-password mypassword \
|
--auth-password mypassword \
|
||||||
--quit-after AUTH
|
--quit-after AUTH
|
||||||
|
@ -41,20 +41,18 @@ function teardown_file() { _default_teardown ; }
|
||||||
|
|
||||||
_send_email \
|
_send_email \
|
||||||
--port 465 \
|
--port 465 \
|
||||||
--auth LOGIN \
|
--auth PLAIN \
|
||||||
--auth-user user1@localhost.localdomain \
|
--auth-user user1@localhost.localdomain \
|
||||||
--auth-password mypassword \
|
--auth-password mypassword \
|
||||||
--quit-after AUTH
|
--quit-after AUTH
|
||||||
assert_success
|
|
||||||
assert_output --partial 'Authentication successful'
|
assert_output --partial 'Authentication successful'
|
||||||
|
|
||||||
_send_email \
|
_send_email \
|
||||||
--port 587 \
|
--port 587 \
|
||||||
--auth LOGIN \
|
--auth PLAIN \
|
||||||
--auth-user user1@localhost.localdomain \
|
--auth-user user1@localhost.localdomain \
|
||||||
--auth-password mypassword \
|
--auth-password mypassword \
|
||||||
--quit-after AUTH
|
--quit-after AUTH
|
||||||
assert_success
|
|
||||||
assert_output --partial 'Authentication successful'
|
assert_output --partial 'Authentication successful'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -248,7 +248,7 @@ function teardown() {
|
||||||
|
|
||||||
# dovecot
|
# dovecot
|
||||||
@test "dovecot: ldap imap connection and authentication works" {
|
@test "dovecot: ldap imap connection and authentication works" {
|
||||||
_nc_wrapper 'auth/imap-ldap-auth' '-w 1 0.0.0.0 143'
|
_nc_wrapper 'auth/imap-ldap-auth.txt' '-w 1 0.0.0.0 143'
|
||||||
assert_success
|
assert_success
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -326,25 +326,26 @@ function teardown() {
|
||||||
@test "spoofing (with LDAP): rejects sender forging" {
|
@test "spoofing (with LDAP): rejects sender forging" {
|
||||||
_wait_for_smtp_port_in_container_to_respond dms-test_ldap
|
_wait_for_smtp_port_in_container_to_respond dms-test_ldap
|
||||||
|
|
||||||
_send_email \
|
_send_email --expect-rejection \
|
||||||
--port 465 -tlsc --auth LOGIN \
|
--port 465 -tlsc --auth PLAIN \
|
||||||
--auth-user some.user@localhost.localdomain \
|
--auth-user some.user@localhost.localdomain \
|
||||||
--auth-password secret \
|
--auth-password secret \
|
||||||
--ehlo mail \
|
--ehlo mail \
|
||||||
--from ldap@localhost.localdomain \
|
--from ldap@localhost.localdomain \
|
||||||
--data 'auth/ldap-smtp-auth-spoofed'
|
--data 'auth/ldap-smtp-auth-spoofed.txt'
|
||||||
|
assert_failure
|
||||||
assert_output --partial 'Sender address rejected: not owned by user'
|
assert_output --partial 'Sender address rejected: not owned by user'
|
||||||
}
|
}
|
||||||
|
|
||||||
@test "spoofing (with LDAP): accepts sending as alias" {
|
@test "spoofing (with LDAP): accepts sending as alias" {
|
||||||
_send_email \
|
_send_email \
|
||||||
--port 465 -tlsc --auth LOGIN \
|
--port 465 -tlsc --auth PLAIN \
|
||||||
--auth-user some.user@localhost.localdomain \
|
--auth-user some.user@localhost.localdomain \
|
||||||
--auth-password secret \
|
--auth-password secret \
|
||||||
--ehlo mail \
|
--ehlo mail \
|
||||||
--from postmaster@localhost.localdomain \
|
--from postmaster@localhost.localdomain \
|
||||||
--to some.user@localhost.localdomain \
|
--to some.user@localhost.localdomain \
|
||||||
--data 'auth/ldap-smtp-auth-spoofed-alias'
|
--data 'auth/ldap-smtp-auth-spoofed-alias.txt'
|
||||||
assert_output --partial 'End data with'
|
assert_output --partial 'End data with'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -353,20 +354,21 @@ function teardown() {
|
||||||
# Template used has invalid AUTH: https://github.com/docker-mailserver/docker-mailserver/pull/3006#discussion_r1073321432
|
# Template used has invalid AUTH: https://github.com/docker-mailserver/docker-mailserver/pull/3006#discussion_r1073321432
|
||||||
skip 'TODO: This test seems to have been broken from the start (?)'
|
skip 'TODO: This test seems to have been broken from the start (?)'
|
||||||
|
|
||||||
_send_email \
|
_send_email --expect-rejection \
|
||||||
--port 465 -tlsc --auth LOGIN \
|
--port 465 -tlsc --auth PLAIN \
|
||||||
--auth-user some.user.email@localhost.localdomain \
|
--auth-user some.user.email@localhost.localdomain \
|
||||||
--auth-password secret \
|
--auth-password secret \
|
||||||
--ehlo mail \
|
--ehlo mail \
|
||||||
--from randomspoofedaddress@localhost.localdomain \
|
--from randomspoofedaddress@localhost.localdomain \
|
||||||
--to some.user@localhost.localdomain \
|
--to some.user@localhost.localdomain \
|
||||||
--data 'auth/ldap-smtp-auth-spoofed-sender-with-filter-exception'
|
--data 'auth/ldap-smtp-auth-spoofed-sender-with-filter-exception.txt'
|
||||||
|
assert_failure
|
||||||
assert_output --partial 'Sender address rejected: not owned by user'
|
assert_output --partial 'Sender address rejected: not owned by user'
|
||||||
}
|
}
|
||||||
|
|
||||||
@test "saslauthd: ldap smtp authentication" {
|
@test "saslauthd: ldap smtp authentication" {
|
||||||
_send_email \
|
_send_email --expect-rejection \
|
||||||
--auth LOGIN \
|
--auth PLAIN \
|
||||||
--auth-user some.user@localhost.localdomain \
|
--auth-user some.user@localhost.localdomain \
|
||||||
--auth-password wrongpassword \
|
--auth-password wrongpassword \
|
||||||
--quit-after AUTH
|
--quit-after AUTH
|
||||||
|
@ -379,12 +381,11 @@ function teardown() {
|
||||||
--auth-user some.user@localhost.localdomain \
|
--auth-user some.user@localhost.localdomain \
|
||||||
--auth-password secret \
|
--auth-password secret \
|
||||||
--quit-after AUTH
|
--quit-after AUTH
|
||||||
assert_success
|
|
||||||
assert_output --partial 'Authentication successful'
|
assert_output --partial 'Authentication successful'
|
||||||
|
|
||||||
_send_email \
|
_send_email \
|
||||||
--port 587 -tls \
|
--port 587 -tls \
|
||||||
--auth LOGIN \
|
--auth PLAIN \
|
||||||
--auth-user some.user@localhost.localdomain \
|
--auth-user some.user@localhost.localdomain \
|
||||||
--auth-password secret \
|
--auth-password secret \
|
||||||
--quit-after AUTH
|
--quit-after AUTH
|
||||||
|
|
|
@ -80,12 +80,12 @@ function teardown_file() { _default_teardown ; }
|
||||||
}
|
}
|
||||||
|
|
||||||
@test "imap: authentication works" {
|
@test "imap: authentication works" {
|
||||||
_nc_wrapper 'auth/imap-auth' '-w 1 0.0.0.0 143'
|
_nc_wrapper 'auth/imap-auth.txt' '-w 1 0.0.0.0 143'
|
||||||
assert_success
|
assert_success
|
||||||
}
|
}
|
||||||
|
|
||||||
@test "imap: added user authentication works" {
|
@test "imap: added user authentication works" {
|
||||||
_nc_wrapper 'auth/added-imap-auth' '-w 1 0.0.0.0 143'
|
_nc_wrapper 'auth/added-imap-auth.txt' '-w 1 0.0.0.0 143'
|
||||||
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
|
||||||
}
|
}
|
||||||
|
@ -293,13 +293,13 @@ EOF
|
||||||
|
|
||||||
# An authenticated user cannot use an envelope sender (MAIL FROM)
|
# An authenticated user cannot use an envelope sender (MAIL FROM)
|
||||||
# address they do not own according to `main.cf:smtpd_sender_login_maps` lookup
|
# address they do not own according to `main.cf:smtpd_sender_login_maps` lookup
|
||||||
_send_email \
|
_send_email --expect-rejection \
|
||||||
--port 465 -tlsc --auth LOGIN \
|
--port 465 -tlsc --auth PLAIN \
|
||||||
--auth-user added@localhost.localdomain \
|
--auth-user added@localhost.localdomain \
|
||||||
--auth-password mypassword \
|
--auth-password mypassword \
|
||||||
--ehlo mail \
|
--ehlo mail \
|
||||||
--from user2@localhost.localdomain \
|
--from user2@localhost.localdomain \
|
||||||
--data 'auth/added-smtp-auth-spoofed'
|
--data 'auth/added-smtp-auth-spoofed.txt'
|
||||||
assert_output --partial 'Sender address rejected: not owned by user'
|
assert_output --partial 'Sender address rejected: not owned by user'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -310,12 +310,12 @@ EOF
|
||||||
# to each table. Address is authorized when a result that maps to
|
# to each table. Address is authorized when a result that maps to
|
||||||
# the DMS account is returned.
|
# the DMS account is returned.
|
||||||
_send_email \
|
_send_email \
|
||||||
--port 465 -tlsc --auth LOGIN \
|
--port 465 -tlsc --auth PLAIN \
|
||||||
--auth-user user1@localhost.localdomain \
|
--auth-user user1@localhost.localdomain \
|
||||||
--auth-password mypassword \
|
--auth-password mypassword \
|
||||||
--ehlo mail \
|
--ehlo mail \
|
||||||
--from alias1@localhost.localdomain \
|
--from alias1@localhost.localdomain \
|
||||||
--data 'auth/added-smtp-auth-spoofed-alias'
|
--data 'auth/added-smtp-auth-spoofed-alias.txt'
|
||||||
assert_success
|
assert_success
|
||||||
assert_output --partial 'End data with'
|
assert_output --partial 'End data with'
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@ function setup_file() {
|
||||||
function teardown_file() { _default_teardown ; }
|
function teardown_file() { _default_teardown ; }
|
||||||
|
|
||||||
@test 'should successfully deliver mail' {
|
@test 'should successfully deliver mail' {
|
||||||
_send_email --data 'existing/user1'
|
_send_email --header 'Subject: Test Message existing-user1'
|
||||||
_wait_for_empty_mail_queue_in_container
|
_wait_for_empty_mail_queue_in_container
|
||||||
|
|
||||||
# Should be successfully sent (received) by Postfix:
|
# Should be successfully sent (received) by Postfix:
|
||||||
|
@ -31,7 +31,7 @@ function teardown_file() { _default_teardown ; }
|
||||||
|
|
||||||
# Verify successful delivery via Dovecot to `/var/mail` account by searching for the subject:
|
# Verify successful delivery via Dovecot to `/var/mail` account by searching for the subject:
|
||||||
_repeat_in_container_until_success_or_timeout 20 "${CONTAINER_NAME}" grep -R \
|
_repeat_in_container_until_success_or_timeout 20 "${CONTAINER_NAME}" grep -R \
|
||||||
'Subject: Test Message existing-user1.txt' \
|
'Subject: Test Message existing-user1' \
|
||||||
'/var/mail/localhost.localdomain/user1/new/'
|
'/var/mail/localhost.localdomain/user1/new/'
|
||||||
assert_success
|
assert_success
|
||||||
_should_output_number_of_lines 1
|
_should_output_number_of_lines 1
|
||||||
|
|
Loading…
Reference in New Issue