{pkgs, lib, config, system, ...}:
let inherit (builtins) toString toFile;
inherit (lib) types;
- inherit (pkgs.lib) unlines unlinesAttrs unlinesValues;
+ inherit (pkgs.lib) unlines unlinesAttrs unlinesValues unwords;
+ inherit (config) networking;
inherit (config.services) dovecot2 postfix x509 openldap;
when = x: y: if x == null then "" else y;
extSep = postfix.recipientDelimiter;
|| "0"<=c && c<="9"
|| c=="-"
then c else "_");
- domainGroup = escapeGroup "${config.networking.baseName}";
+ domainGroup = escapeGroup "${networking.domainBase}";
etc_dovecot = [
- { target = "dovecot/${config.networking.domain}/dovecot-ldap.conf";
+ { target = "dovecot/${networking.domain}/dovecot-ldap.conf";
source = pkgs.writeText "dovecot-ldap.conf" ''
${lib.optionalString dovecot2.debug ''
debug_level = 1
# mailQuota=quota_rule=*:bytes=%$
# doveadm user query
- iterate_attrs = =user=%{ldap:uid}@${config.networking.domain}
+ iterate_attrs = =user=%{ldap:uid}@${networking.domain}
iterate_filter = (&(objectClass=posixAccount)(mailEnabled=TRUE))
'';
}
all
'';
};
+
+ sieve-rspamd-filter =
+ pkgs.stdenv.mkDerivation {
+ name = "sieve-rspamd-filter";
+ nativeBuildInputs = [ pkgs.makeWrapper ];
+ phases = [ "installPhase" ];
+ installPhase = ''
+ mkdir -p $out/bin
+ cat > $out/bin/learn-spam.sh <<EOF
+ #!/bin/sh
+ exec ${pkgs.rspamd}/bin/rspamc -h /run/rspamd.sock learn_spam
+ EOF
+ cat > $out/bin/learn-ham.sh <<EOF
+ #!/bin/sh
+ exec ${pkgs.rspamd}/bin/rspamc -h /run/rspamd.sock learn_ham
+ EOF
+ chmod +x $out/bin/*.sh
+ '';
+ };
in
{
imports = [
installSieve = ''
rm -rf "${sieveDir}"
+ install -D -d -m 0755 -o root -g root \
+ "${sieveDir}/bin"
'' + unlinesAttrs (dir: sieves: ''
install -D -d -m 0755 -o root -g root \
${sieveDir} ${sieveDir}/${dir}.d
install -D -d -m 1770 \
-o ${dovecot2.mailUser} \
-g ${domainGroup} \
- ${mailDir}/${config.networking.domain} \
- ${stateDir}/control/${config.networking.domain} \
- ${stateDir}/index/${config.networking.domain}
+ ${mailDir}/${networking.domain} \
+ ${stateDir}/control/${networking.domain} \
+ ${stateDir}/index/${networking.domain}
+
# NOTE: do not set the sticky bit (+t)
# on acl/<domain>/, to let dovecot
# rename acl.db.lock (own by new user)
install -D -d -m 0770 \
-o ${dovecot2.mailUser} \
-g ${domainGroup} \
- ${stateDir}/acl/${config.networking.domain}
+ ${stateDir}/acl/${networking.domain}
+
+ # NOTE: domainAliases point to the very same mailboxes as domain's.
+ for domainAlias in ${unwords networking.domainAliases}
+ do
+ ln -fns ${networking.domain} ${mailDir}/$domainAlias
+ ln -fns ${networking.domain} ${stateDir}/control/$domainAlias
+ ln -fns ${networking.domain} ${stateDir}/index/$domainAlias
+ ln -fns ${networking.domain} ${stateDir}/acl/$domainAlias
+ done
'';
};
};
addflag "Junk";
}
'';
+ /*
+ require ["fileinto","mailbox"];
+
+ if header :contains "X-Spam" "Yes" {
+ fileinto :create "INBOX.Junk";
+ stop;
+ }
+ */
extension = ''
require
[ "envelope"
stop;
}
'';
+ report-spam = ''
+ require ["vnd.dovecot.pipe", "copy", "imapsieve", "environment", "variables"];
+
+ if environment :matches "imap.user" "*" {
+ set "username" "''${1}";
+ }
+
+ pipe :copy "learn-spam.sh" [ "''${username}" ];
+ '';
+ report-ham = ''
+ require ["vnd.dovecot.pipe", "copy", "imapsieve", "environment", "variables"];
+
+ if environment :matches "imap.mailbox" "*" {
+ set "mailbox" "''${1}";
+ }
+
+ if string "''${mailbox}" "Trash" {
+ stop;
+ }
+
+ if environment :matches "imap.user" "*" {
+ set "username" "''${1}";
+ }
+
+ pipe :copy "learn-ham.sh" [ "''${username}" ];
+ '';
};
};
configFile = toString (pkgs.writeText "dovecot.conf" ''
passdb {
driver = ldap
- args = /etc/dovecot/${config.networking.domain}/dovecot-ldap.conf
+ args = /etc/dovecot/${networking.domain}/dovecot-ldap.conf
default_fields = userdb_mail_access_groups=${domainGroup}
override_fields =
}
userdb {
# NOTE: this userdb is only used by lda.
driver = ldap
- args = /etc/dovecot/${config.networking.domain}/dovecot-ldap.conf
+ args = /etc/dovecot/${networking.domain}/dovecot-ldap.conf
default_fields = mail_access_groups=${domainGroup}
override_fields =
skip = found
#}
mail_home = ${mailDir}/%d/%n
# NOTE: if needed, may be overrided by userdb_mail
- mail_location = maildir:${mailDir}/%d/%n/Maildir:LAYOUT=fs:INDEX=${stateDir}/index/%d/%n:CONTROL=${stateDir}/control/%d/%n
+ mail_location = maildir:${mailDir}/%d/%n/Maildir:LAYOUT=fs:INDEX=${stateDir}/index/%d/%n:INDEXPVT=${stateDir}/index/%d/%n:CONTROL=${stateDir}/control/%d/%n
# NOTE: if needed, may be overrided by userdb_mail
# NOTE: INDEX and CONTROL are on a partition without quota, as explain in the doc.
# SEE: http://wiki2.dovecot.org/Quota/FS
#maildir_copy_with_hardlinks = yes
namespace inbox {
# NOTE: here because protocol sieve {namespace inbox{}} does not seem to work.
+ type = private
inbox = yes
location =
list = yes
separator = ${dirSep}
}
namespace {
- #list = children
- list = yes
- location = maildir:${mailDir}/%d/%n/Maildir:LAYOUT=fs:INDEX=${stateDir}/index/%d/%n/Shared/%n:CONTROL=${stateDir}/control/%d/%n/Shared/%n
- # FIXME: %d not working
- prefix = Partages+%%n+
- separator = ${dirSep}
+ type = shared
+ #list = children
+ list = yes
+ # NOTE: always listed in the LIST command.
+ location = maildir:${mailDir}/%%d/%%n/Maildir:LAYOUT=fs:INDEX=${stateDir}/index/%%d/%%n/Shared:INDEXPVT=${stateDir}/index/%d/%n/Shared/%%n:CONTROL=${stateDir}/control/%d/%n/Shared
+ # NOTE: how to access the other users' mailboxes.
+ # NOTE: %var expands to the logged in user's variable, while
+ # %%var expands to the other users' variables.
+ # NOTE: INDEX and CONTROL are shared, INDEXPVT is not.
+ prefix = Partages+%%n+
+ separator = ${dirSep}
subscriptions = yes
- type = shared
}
mail_plugins = $mail_plugins acl quota virtual
#mail_uid = ${dovecot2.mailUser}
sieve_spamtest_status_header = X-Spam-Score
sieve_spamtest_status_type = strlen
sieve_user_log = /var/log/dovecot/%d/sieve.%n.log
+
+ sieve_plugins = sieve_imapsieve sieve_extprograms
+ sieve_pipe_bin_dir = ${sieve-rspamd-filter}/bin
+ sieve_global_extensions = +vnd.dovecot.pipe +vnd.dovecot.environment
+ # From elsewhere to Spam folder
+ imapsieve_mailbox1_name = Spam
+ imapsieve_mailbox1_causes = COPY
+ imapsieve_mailbox1_before = file:${sieveDir}/global.d/report-spam.sieve
+
+ # From Spam folder to elsewhere
+ imapsieve_mailbox2_name = *
+ imapsieve_mailbox2_from = Spam
+ imapsieve_mailbox2_causes = COPY
+ imapsieve_mailbox2_before = file:${sieveDir}/global.d/report-ham.sieve
}
+ # If you have Dovecot v2.2.8+ you may get a significant performance improvement with fetch-headers:
+ imapc_features = $imapc_features fetch-headers
+ # Read multiple mails in parallel, improves performance
+ mail_prefetch_count = 20
service quota-warning {
executable = script ${
pkgs.writeScript "quota-warning" ''
USER=$2
cat << EOF | ${pkgs.dovecot}/libexec/dovecot/dovecot-lda -d $USER -o
"plugin/quota=maildir:User quota:noenforcing"
- From: postmaster@${config.networking.domain}
+ From: postmaster@${networking.domain}
Subject: [WARNING] your mailbox is now $PERCENT% full.
Please remove some mails to make room for new ones.
}
protocol imap {
#mail_max_userip_connections = 10
- mail_plugins = $mail_plugins imap_acl imap_quota # antispam
+ mail_plugins = $mail_plugins imap_acl imap_quota imap_sieve # antispam
namespace inbox {
inbox = yes
location =
}
mailbox Junk {
special_use = \Junk
+ auto = subscribe
+ #autoexpunge = 30d
}
mailbox Sent {
special_use = \Sent
+ auto = subscribe
}
mailbox "Sent Messages" {
special_use = \Sent
+ auto = subscribe
}
mailbox Trash {
special_use = \Trash
+ auto = subscribe
+ #autoexpunge = 30d
}
prefix =
separator = ${dirSep}
}
protocol lda {
auth_socket_path = /var/run/dovecot/auth-userdb
- hostname = ${config.networking.domain}
+ hostname = ${networking.domain}
info_log_path =
log_path =
mail_plugins = $mail_plugins sieve
prefix =
separator = ${dirSep}
}
- postmaster_address = postmaster${extSep}dovecot${extSep}lda@${config.networking.domain}
+ postmaster_address = postmaster${extSep}dovecot${extSep}lda@${networking.domain}
syslog_facility = mail
}
protocol lmtp {
prefix =
separator = ${dirSep}
}
- postmaster_address = postmaster${extSep}dovecot${extSep}lmtp@${config.networking.domain}
+ postmaster_address = postmaster${extSep}dovecot${extSep}lmtp@${networking.domain}
}
protocol pop3 {
#mail_max_userip_connections = 10