-
|
Hi,
I looked at sieve doc elsewhere and the DMS sieve example looks fine. Also I tried to debug sieve filtering using Any idea of what can be wrong? EDIT and I test it sending a mail to |
Beta Was this translation helpful? Give feedback.
Replies: 3 comments 16 replies
-
|
This is an easy mistake when getting started with Sieve. You need to make sure you have the correct Sieve extensions loaded. In your case that would look like this: Perhaps the docs were not clear with those examples, but they were meant to be snippets to swap from the previous full sieve script example which does start with a ReferenceJust for anyone else landing here, I've provided a full example that you can run locally, just copy/paste this name: example
services:
dms:
image: ghcr.io/docker-mailserver/docker-mailserver:${DMS_RELEASE:-15.1.0}
hostname: mail.example.test
# These ENV below are just to simplify the reproduction and aren't relevant to the sieve functionality itself:
environment:
ENABLE_AMAVIS: 0
ENABLE_UPDATE_CHECK: 0
# Normally this would be `volumes` for you, but `configs` is useful for examples,
# as it allows embedding the files into a single `compose.yaml` example that you can copy/paste to run locally:
configs:
- source: dms-accounts
target: /tmp/docker-mailserver/postfix-accounts.cf
# Sieve script is associated to a specific account/mailbox:
- source: dms-sieve
target: /tmp/docker-mailserver/[email protected]
# This is a workaround for running this `compose.yaml` example locally without proper DNS setup.
# It's only needed for the `swaks` command to successfully deliver mail on port 25:
networks:
default:
aliases:
- example.test
# The Docker Compose `configs` feature inlines file content into `compose.yaml` (convenient for reproductions)
# NOTE: `$` will be inferred as an ENV on the host to replace with a value if found,
# `$$` is required as an escape to opt-out of that feature when an actual `$` is expected in the file content.
configs:
# Created via `setup email add [email protected] secret`:
# - Username: `[email protected]`
# - Password: `secret`
dms-accounts:
content: |
[email protected]|{SHA512-CRYPT}$$6$$sbgFRCmQ.KWS5ryb$$EsWrlYosiadgdUOxCBHY0DQ3qFbeudDhNMqHs6jZt.8gmxUwiLVy738knqkHD4zj4amkb296HFqQ3yDq4UXt8.
dms-sieve:
content: |
require ["envelope", "subaddress", "fileinto"];
# Is the envelope subaddress (`envelope :detail`) of the recipient ("to") exactly `test`? (case-insensitive):
if envelope :detail "to" "test" {
# Store the mail into your `test` mailbox (it will be created if it does not exist yet).
# The mail will exist at: /var/mail/example.test/john.doe/.INBOX.test/new
fileinto "INBOX.test";
}$ docker compose up -d --force-recreate
# Send a test mail to the mail address with the subaddress `test`:
$ docker compose exec dms swaks --silent --server localhost --from [email protected] --to [email protected]
# Check that it was delivered into the expected `test` inbox folder:
$ docker compose exec dms ls /var/mail/example.test/john.doe/.INBOX.test/new
'1758764721.M6145P775.mail.example.test,S=893,W=914'TroubleshootingIn this case your sieve extension probably failed to compiled. If it was successful you'd find it will have a $ docker compose exec dms ls -a /var/mail/example.test/john.doe/home
. .. .dovecot.sieve .dovecot.svbinWhen compilation fails, the $ docker compose exec dms cat /var/mail/example.test/john.doe/home/.dovecot.sieve.log
sieve: info: started log at 2025-09-25 01:57:14 +0000.
.dovecot: line 4: error: unknown test 'envelope' (only reported once at first occurrence).
.dovecot: line 7: error: unknown command 'fileinto' (only reported once at first occurrence).
.dovecot: error: validation failed.Those two have extensions of the equivalent name, while |
Beta Was this translation helpful? Give feedback.
-
|
I've identified another way that will work, but I don't know if it's ideal. This was through references:
Instead of using the name: example
services:
dms:
image: ghcr.io/docker-mailserver/docker-mailserver:${DMS_RELEASE:-15.1.0}
hostname: mail.example.test
# These ENV below are just to simplify the reproduction and aren't relevant to the sieve functionality itself:
environment:
ENABLE_AMAVIS: 0
ENABLE_UPDATE_CHECK: 0
# Normally this would be `volumes` for you, but `configs` is useful for examples,
# as it allows embedding the files into a single `compose.yaml` example that you can copy/paste to run locally:
configs:
- source: dms-accounts
target: /tmp/docker-mailserver/postfix-accounts.cf
- source: dms-aliases
target: /tmp/docker-mailserver/postfix-virtual.cf
# Sieve script is associated to a specific account/mailbox:
- source: dms-sieve
target: /tmp/docker-mailserver/[email protected]
- source: dms-sieve
target: /tmp/docker-mailserver/[email protected]
- source: user-patches
target: /tmp/docker-mailserver/user-patches.sh
- source: dovecot-extra
target: /tmp/docker-mailserver/dovecot.cf
# This is a workaround for running this `compose.yaml` example locally without proper DNS setup.
# It's only needed for the `swaks` command to successfully deliver mail on port 25:
networks:
default:
aliases:
- example.test
# The Docker Compose `configs` feature inlines file content into `compose.yaml` (convenient for reproductions)
# NOTE: `$` will be inferred as an ENV on the host to replace with a value if found,
# `$$` is required as an escape to opt-out of that feature when an actual `$` is expected in the file content.
configs:
# Created via `setup email add [email protected] secret`:
# - Username: `[email protected]`
# - Password: `secret`
dms-accounts:
content: |
[email protected]|{SHA512-CRYPT}$$6$$sbgFRCmQ.KWS5ryb$$EsWrlYosiadgdUOxCBHY0DQ3qFbeudDhNMqHs6jZt.8gmxUwiLVy738knqkHD4zj4amkb296HFqQ3yDq4UXt8.
[email protected]|{SHA512-CRYPT}$$6$$sbgFRCmQ.KWS5ryb$$EsWrlYosiadgdUOxCBHY0DQ3qFbeudDhNMqHs6jZt.8gmxUwiLVy738knqkHD4zj4amkb296HFqQ3yDq4UXt8.
dms-aliases:
content: |
[email protected] [email protected]
[email protected] [email protected]
@example.test [email protected]
dms-sieve:
content: |
require ["envelope", "subaddress", "fileinto"];
# Is the envelope subaddress (`envelope :detail`) of the recipient ("to") exactly `ext-tag`? (case-insensitive):
if envelope :detail "to" "ext-tag" {
# Store the mail into your `ext-tag` mailbox (it will be created if it does not exist yet).
# The mail will exist at: /var/mail/example.test/john.doe/.INBOX.ext-tag/new
fileinto "INBOX.ext-tag";
}
# Configure Postfix to append the `X-Original-To` header:
# See "Command Attribute Syntax" section: https://www.postfix.org/smtp.8.html
user-patches:
content: |
postconf lmtp_destination_recipient_limit=1
postconf -F 'lmtp/unix/command=lmtp flags=O'
# Have Dovecot set the ORCPT from this header, when the RCPT value is not present:
# https://doc.dovecot.org/2.3/configuration_manual/protocols/lmtp_server/#envelope-addresses
# https://doc.dovecot.org/2.3/settings/core/#core_setting-lda_original_recipient_header
dovecot-extra:
content: |
lda_original_recipient_header = X-Original-ToWith that docker compose up -d --force-recreate
# Send to catch-all alias that will resolve to store at `[email protected]` mailbox:
docker compose exec dms swaks --silent --server localhost --from [email protected] --to [email protected]
# Send to an alias that will resolve to store at the `[email protected]` mailbox:
docker compose exec dms swaks --silent --server localhost --from [email protected] --to [email protected]There is a slight difference in these mails, the subaddress is still missing for the wildcard $ docker compose exec dms bash -c 'cat /var/mail/example.test/john.doe/.INBOX.ext-tag/new/*'
Return-Path: <[email protected]>
Delivered-To: [email protected]
Received: from mail.example.test
by mail.example.test with LMTP
id NRsxHTqM3GjdAwAAUi6ngw
(envelope-from <[email protected]>)
for <[email protected]>; Wed, 01 Oct 2025 02:04:42 +0000
X-Original-To: [email protected]
X-Comment: SPF check N/A for local connections - client-ip=::1; helo=mail.example.test; [email protected]; receiver=example.test
Received: from mail.example.test (localhost [IPv6:::1])
by mail.example.test (Postfix) with ESMTP id 59CCA240591
for <[email protected]>; Wed, 1 Oct 2025 02:04:42 +0000 (UTC)
Date: Wed, 01 Oct 2025 02:04:36 +0000
To: [email protected]
From: [email protected]
Subject: test Wed, 01 Oct 2025 02:04:36 +0000
Message-Id: <[email protected]>
X-Mailer: swaks v20240103.0 jetmore.org/john/code/swaks/
This is a test mailing$ docker compose exec dms bash -c 'cat /var/mail/example.test/jane.doe/.INBOX.ext-tag/new/*'
Return-Path: <[email protected]>
Delivered-To: [email protected]
Received: from mail.example.test
by mail.example.test with LMTP
id IM/xMk2M3GjdAwAAUi6ngw
(envelope-from <[email protected]>)
for <[email protected]>; Wed, 01 Oct 2025 02:05:01 +0000
X-Original-To: [email protected]
X-Comment: SPF check N/A for local connections - client-ip=::1; helo=mail.example.test; [email protected]; receiver=example.test
Received: from mail.example.test (localhost [IPv6:::1])
by mail.example.test (Postfix) with ESMTP id A8FA2240591
for <[email protected]>; Wed, 1 Oct 2025 02:05:01 +0000 (UTC)
Date: Wed, 01 Oct 2025 02:05:01 +0000
To: [email protected]
From: [email protected]
Subject: test Wed, 01 Oct 2025 02:05:01 +0000
Message-Id: <[email protected]>
X-Mailer: swaks v20240103.0 jetmore.org/john/code/swaks/
This is a test mailingWhen Sieve is running, the I did also come across a similar/related setting NOTE: As per one of the DMS references cited, you could avoid setting |
Beta Was this translation helpful? Give feedback.
-
|
This is the (mostly) working solution I found. Using (no problem for me with the second line you mention) and a sieve rule similar to the one in the docs :
I can provide more details about my configuration to understand why yours doesn't work, but mine is pretty standard... nothing fancy in |
Beta Was this translation helpful? Give feedback.



This is the (mostly) working solution I found.
The idea is having a
useraccount which works as normal but also as a catch-all for the domain. There is also atestaccount.Using
(no problem for me with the second line you mention)
and a sieve rule similar to the one in the docs :
user+tag@ends in user'sINBOX.tagmailboxtest+tag@ends in test'sINBOX.tagmailboxwhatever@ends in user'sINBOXmailboxbut
whatever+tag@is also stored in user'sINBOX. Which seems coherent with the problem I had before.It …