2024-01-29 12:21:58 +01:00
{
config ,
lib ,
pkgs ,
. . .
} :
2011-10-27 19:43:20 +00:00
let
2024-01-29 12:21:58 +01:00
inherit ( lib )
attrValues
concatMapStringsSep
concatStrings
concatStringsSep
flatten
imap1
literalExpression
mapAttrsToList
2023-12-17 17:09:10 +01:00
mkEnableOption
mkIf
mkOption
mkRemovedOptionModule
optional
optionalAttrs
2024-01-14 21:07:42 +01:00
optionalString
singleton
types
mkRenamedOptionModule
nameValuePair
2024-01-23 13:49:02 +01:00
mapAttrs'
listToAttrs
filter
;
inherit ( lib . strings ) match ;
2023-12-17 17:09:10 +01:00
2011-10-27 19:43:20 +00:00
cfg = config . services . dovecot2 ;
2016-04-22 17:21:17 +02:00
dovecotPkg = pkgs . dovecot ;
2011-10-27 19:43:20 +00:00
2015-12-09 10:27:44 +01:00
baseDir = " / r u n / d o v e c o t 2 " ;
stateDir = " / v a r / l i b / d o v e c o t " ;
2011-10-27 19:43:20 +00:00
2024-01-29 12:22:12 +01:00
sieveScriptSettings = mapAttrs' (
to : _ : nameValuePair " s i e v e _ ${ to } " " ${ stateDir } / s i e v e / ${ to } "
) cfg . sieve . scripts ;
2024-01-14 21:07:42 +01:00
imapSieveMailboxSettings = listToAttrs (
flatten (
imap1 (
idx : el :
singleton {
name = " i m a p s i e v e _ m a i l b o x ${ toString idx } _ n a m e " ;
value = el . name ;
}
++ optional ( el . from != null ) {
name = " i m a p s i e v e _ m a i l b o x ${ toString idx } _ f r o m " ;
value = el . from ;
}
++ optional ( el . causes != [ ] ) {
name = " i m a p s i e v e _ m a i l b o x ${ toString idx } _ c a u s e s " ;
value = concatStringsSep " , " el . causes ;
}
++ optional ( el . before != null ) {
name = " i m a p s i e v e _ m a i l b o x ${ toString idx } _ b e f o r e " ;
value = " f i l e : ${ stateDir } / i m a p s i e v e / b e f o r e / ${ baseNameOf el . before } " ;
}
++ optional ( el . after != null ) {
name = " i m a p s i e v e _ m a i l b o x ${ toString idx } _ a f t e r " ;
value = " f i l e : ${ stateDir } / i m a p s i e v e / a f t e r / ${ baseNameOf el . after } " ;
}
) cfg . imapsieve . mailbox
2024-12-10 20:29:24 +01:00
)
2024-01-14 21:07:42 +01:00
) ;
2024-01-23 13:49:02 +01:00
mkExtraConfigCollisionWarning = term : ''
You referred to $ { term } in ` services . dovecot2 . extraConfig ` .
Due to gradual transition to structured configuration for plugin configuration , it is possible
this will cause your plugin configuration to be ignored .
Consider setting ` services . dovecot2 . pluginSettings . ${ term } ` instead .
'' ;
# Those settings are automatically set based on other parts
# of this module.
automaticallySetPluginSettings =
[
" s i e v e _ p l u g i n s "
" s i e v e _ e x t e n s i o n s "
" s i e v e _ g l o b a l _ e x t e n s i o n s "
" s i e v e _ p i p e _ b i n _ d i r "
]
++ ( builtins . attrNames sieveScriptSettings )
++ ( builtins . attrNames imapSieveMailboxSettings ) ;
# The idea is to match everything that looks like `$term =`
# but not `# $term something something`
# or `# $term = some value` because those are comments.
2024-12-23 21:58:07 +01:00
configContainsSetting = lines : term : ( match " [ [ : b l a n k : ] ] * ${ term } [ [ : b l a n k : ] ] * = . * " lines ) != null ;
2024-01-23 13:49:02 +01:00
warnAboutExtraConfigCollisions = map mkExtraConfigCollisionWarning (
filter ( configContainsSetting cfg . extraConfig ) automaticallySetPluginSettings
) ;
2024-01-14 21:07:42 +01:00
sievePipeBinScriptDirectory = pkgs . linkFarm " s i e v e - p i p e - b i n s " (
map ( el : {
name = builtins . unsafeDiscardStringContext ( baseNameOf el ) ;
path = el ;
} ) cfg . sieve . pipeBins
) ;
2015-12-09 10:27:44 +01:00
dovecotConf = concatStrings [
2011-10-27 19:43:20 +00:00
''
2015-12-09 10:27:44 +01:00
base_dir = $ { baseDir }
2016-01-10 06:54:07 +03:00
protocols = $ { concatStringsSep " " cfg . protocols }
2017-01-29 04:11:01 -06:00
sendmail_path = /run/wrappers/bin/sendmail
2019-12-31 12:00:00 +00:00
# defining mail_plugins must be done before the first protocol {} filter because of https://doc.dovecot.org/configuration_manual/config_file/config_file_syntax/#variable-expansion
mail_plugins = $ mail_plugins $ { concatStringsSep " " cfg . mailPlugins . globally . enable }
2011-10-27 19:43:20 +00:00
''
2015-12-09 10:27:44 +01:00
2020-01-28 12:00:00 +00:00
( concatStringsSep " \n " (
mapAttrsToList ( protocol : plugins : ''
protocol $ { protocol } {
mail_plugins = $ mail_plugins $ { concatStringsSep " " plugins . enable }
}
'' ) c f g . m a i l P l u g i n s . p e r P r o t o c o l
) )
(
if cfg . sslServerCert = = null then
''
ssl = no
disable_plaintext_auth = no
''
else
''
ssl_cert = < $ { cfg . sslServerCert }
ssl_key = < $ { cfg . sslServerKey }
$ { optionalString ( cfg . sslCACert != null ) ( " s s l _ c a = < " + cfg . sslCACert ) }
2022-01-19 22:39:57 +01:00
$ { optionalString cfg . enableDHE '' s s l _ d h = < ${ config . security . dhparams . params . dovecot2 . path } '' }
2020-01-28 12:00:00 +00:00
disable_plaintext_auth = yes
''
)
2011-10-27 19:43:20 +00:00
2015-12-09 10:27:44 +01:00
''
2011-10-27 19:43:20 +00:00
default_internal_user = $ { cfg . user }
2018-03-28 19:16:41 +02:00
default_internal_group = $ { cfg . group }
2016-01-10 07:07:26 +03:00
$ { optionalString ( cfg . mailUser != null ) " m a i l _ u i d = ${ cfg . mailUser } " }
$ { optionalString ( cfg . mailGroup != null ) " m a i l _ g i d = ${ cfg . mailGroup } " }
2011-10-27 19:43:20 +00:00
2012-06-10 15:07:25 +00:00
mail_location = $ { cfg . mailLocation }
2011-10-27 19:43:20 +00:00
maildir_copy_with_hardlinks = yes
2015-12-09 10:27:44 +01:00
pop3_uidl_format = % 0 8 Xv % 0 8 Xu
2011-10-27 19:43:20 +00:00
auth_mechanisms = plain login
2015-12-09 10:27:44 +01:00
2011-10-27 19:43:20 +00:00
service auth {
user = root
}
2015-12-09 10:27:44 +01:00
''
2020-01-28 12:00:00 +00:00
( optionalString cfg . enablePAM ''
userdb {
driver = passwd
}
2016-01-10 07:05:12 +03:00
2020-01-28 12:00:00 +00:00
passdb {
driver = pam
args = $ { optionalString cfg . showPAMFailure " f a i l u r e _ s h o w _ m s g = y e s " } dovecot2
2017-08-15 12:14:29 +02:00
}
2020-01-28 12:00:00 +00:00
'' )
2017-08-15 12:14:29 +02:00
2020-08-18 01:57:31 +02:00
( optionalString ( cfg . mailboxes != { } ) ''
2020-07-15 12:00:00 +00:00
namespace inbox {
inbox = yes
$ { concatStringsSep " \n " ( map mailboxConfig ( attrValues cfg . mailboxes ) ) }
2020-01-28 12:00:00 +00:00
}
'' )
( optionalString cfg . enableQuota ''
service quota-status {
executable = $ { dovecotPkg } /libexec/dovecot/quota-status - p postfix
inet_listener {
port = $ { cfg . quotaPort }
2017-08-15 12:14:29 +02:00
}
2020-01-28 12:00:00 +00:00
client_limit = 1
2024-12-10 20:29:24 +01:00
}
2017-08-15 12:14:29 +02:00
2020-01-28 12:00:00 +00:00
plugin {
quota_rule = * : storage = $ { cfg . quotaGlobalPerUser }
2021-10-16 09:52:18 +08:00
quota = count:User quota # per virtual mail user quota
2020-01-28 12:00:00 +00:00
quota_status_success = DUNNO
quota_status_nouser = DUNNO
quota_status_overquota = " 5 5 2 5 . 2 . 2 M a i l b o x i s f u l l "
quota_grace = 10 % %
2021-10-16 09:52:18 +08:00
quota_vsizes = yes
2020-01-28 12:00:00 +00:00
}
'' )
2017-08-15 12:14:29 +02:00
2024-01-14 21:07:42 +01:00
# General plugin settings:
# - sieve is mostly generated here, refer to `pluginSettings` to follow
# the control flow.
2023-12-17 17:09:10 +01:00
''
plugin {
2024-01-14 21:42:40 +01:00
$ { concatStringsSep " \n " ( mapAttrsToList ( key : value : " ${ key } = ${ value } " ) cfg . pluginSettings ) }
2023-12-17 17:09:10 +01:00
}
''
2015-12-09 10:27:44 +01:00
cfg . extraConfig
] ;
2011-10-27 19:43:20 +00:00
2016-04-26 15:10:42 +03:00
modulesDir = pkgs . symlinkJoin {
name = " d o v e c o t - m o d u l e s " ;
paths = map ( pkg : " ${ pkg } / l i b / d o v e c o t " ) (
[ dovecotPkg ] ++ map ( module : module . override { dovecot = dovecotPkg ; } ) cfg . modules
) ;
} ;
2011-10-27 19:43:20 +00:00
2017-08-15 12:14:29 +02:00
mailboxConfig =
mailbox :
''
2018-02-05 17:06:49 +01:00
mailbox " ${ mailbox . name } " {
2017-08-15 12:14:29 +02:00
auto = $ { toString mailbox . auto }
2020-06-03 23:54:36 +02:00
''
+ optionalString ( mailbox . autoexpunge != null ) ''
autoexpunge = $ { mailbox . autoexpunge }
2017-08-15 12:14:29 +02:00
''
+ optionalString ( mailbox . specialUse != null ) ''
2020-01-28 12:00:00 +00:00
special_use = \ $ { toString mailbox . specialUse }
2017-08-15 12:14:29 +02:00
''
+ " } " ;
2024-12-10 20:29:24 +01:00
2020-08-18 01:57:31 +02:00
mailboxes =
{ name , . . . }:
{
2017-08-15 12:14:29 +02:00
options = {
name = mkOption {
2020-08-18 01:57:31 +02:00
type = types . strMatching '' [ ^ " ] + '' ;
2017-08-15 12:14:29 +02:00
example = " S p a m " ;
2020-08-18 01:57:31 +02:00
default = name ;
readOnly = true ;
2017-08-15 12:14:29 +02:00
description = " T h e n a m e o f t h e m a i l b o x . " ;
} ;
auto = mkOption {
type = types . enum [
" n o "
" c r e a t e "
" s u b s c r i b e "
] ;
default = " n o " ;
example = " s u b s c r i b e " ;
description = " W h e t h e r t o a u t o m a t i c a l l y c r e a t e o r c r e a t e a n d s u b s c r i b e t o t h e m a i l b o x o r n o t . " ;
} ;
specialUse = mkOption {
type = types . nullOr (
types . enum [
" A l l "
" A r c h i v e "
" D r a f t s "
" F l a g g e d "
" J u n k "
" S e n t "
" T r a s h "
]
) ;
default = null ;
example = " J u n k " ;
description = " N u l l i f n o s p e c i a l u s e f l a g i s s e t . O t h e r t h a n t h a t e v e r y u s e f l a g m e n t i o n e d i n t h e R F C i s v a l i d . " ;
} ;
2020-06-03 23:54:36 +02:00
autoexpunge = mkOption {
type = types . nullOr types . str ;
default = null ;
example = " 6 0 d " ;
description = ''
To automatically remove all email from the mailbox which is older than the
specified time .
'' ;
2024-12-10 20:29:24 +01:00
} ;
2020-06-03 23:54:36 +02:00
} ;
2017-08-15 12:14:29 +02:00
} ;
2015-12-09 10:27:44 +01:00
in
2011-10-27 19:43:20 +00:00
{
2019-12-10 02:51:19 +01:00
imports = [
( mkRemovedOptionModule [ " s e r v i c e s " " d o v e c o t 2 " " p a c k a g e " ] " " )
2024-01-14 21:07:42 +01:00
( mkRenamedOptionModule
[ " s e r v i c e s " " d o v e c o t 2 " " s i e v e S c r i p t s " ]
[ " s e r v i c e s " " d o v e c o t 2 " " s i e v e " " s c r i p t s " ]
)
2019-12-10 02:51:19 +01:00
] ;
2011-10-27 19:43:20 +00:00
2015-12-09 10:27:44 +01:00
options . services . dovecot2 = {
2022-01-20 00:35:12 +01:00
enable = mkEnableOption " t h e d o v e c o t 2 . x P O P 3 / I M A P s e r v e r " ;
2011-10-27 19:43:20 +00:00
2023-02-01 06:12:57 +01:00
enablePop3 = mkEnableOption " s t a r t i n g t h e P O P 3 l i s t e n e r ( w h e n D o v e c o t i s e n a b l e d ) " ;
2011-10-27 19:43:20 +00:00
2023-02-01 06:12:57 +01:00
enableImap = mkEnableOption " s t a r t i n g t h e I M A P l i s t e n e r ( w h e n D o v e c o t i s e n a b l e d ) " // {
default = true ;
} ;
2011-10-27 19:43:20 +00:00
2023-02-01 06:12:57 +01:00
enableLmtp = mkEnableOption " s t a r t i n g t h e L M T P l i s t e n e r ( w h e n D o v e c o t i s e n a b l e d ) " ;
2012-09-30 00:53:50 +02:00
2016-01-10 06:54:07 +03:00
protocols = mkOption {
type = types . listOf types . str ;
2020-01-28 12:00:00 +00:00
default = [ ] ;
2016-01-10 06:54:07 +03:00
description = " A d d i t i o n a l l i s t e n e r s t o s t a r t w h e n D o v e c o t i s e n a b l e d . " ;
} ;
2015-12-09 10:27:44 +01:00
user = mkOption {
type = types . str ;
default = " d o v e c o t 2 " ;
description = " D o v e c o t u s e r n a m e . " ;
} ;
2015-07-03 00:26:49 +03:00
2015-12-09 10:27:44 +01:00
group = mkOption {
type = types . str ;
default = " d o v e c o t 2 " ;
description = " D o v e c o t g r o u p n a m e . " ;
} ;
2011-10-27 19:43:20 +00:00
2015-12-09 10:27:44 +01:00
extraConfig = mkOption {
2016-10-23 19:33:41 +02:00
type = types . lines ;
2015-12-09 10:27:44 +01:00
default = " " ;
example = " m a i l _ d e b u g = y e s " ;
description = " A d d i t i o n a l e n t r i e s t o p u t v e r b a t i m i n t o D o v e c o t ' s c o n f i g f i l e . " ;
} ;
2011-10-27 19:43:20 +00:00
2019-12-31 12:00:00 +00:00
mailPlugins =
2020-01-28 12:00:00 +00:00
let
plugins =
hint :
types . submodule {
options = {
enable = mkOption {
type = types . listOf types . str ;
default = [ ] ;
description = " m a i l p l u g i n s t o e n a b l e a s a l i s t o f s t r i n g s t o a p p e n d t o t h e ${ hint } ` $ m a i l _ p l u g i n s ` c o n f i g u r a t i o n v a r i a b l e " ;
2024-12-10 20:29:24 +01:00
} ;
2020-01-28 12:00:00 +00:00
} ;
2019-12-31 12:00:00 +00:00
} ;
2020-01-28 12:00:00 +00:00
in
mkOption {
type =
with types ;
submodule {
options = {
globally = mkOption {
2020-01-28 12:00:00 +00:00
description = " A d d i t i o n a l e n t r i e s t o a d d t o t h e m a i l _ p l u g i n s v a r i a b l e f o r a l l p r o t o c o l s " ;
2020-01-28 12:00:00 +00:00
type = plugins " t o p - l e v e l " ;
example = {
enable = [ " v i r t u a l " ] ;
} ;
default = {
enable = [ ] ;
} ;
} ;
perProtocol = mkOption {
2020-01-28 12:00:00 +00:00
description = " A d d i t i o n a l e n t r i e s t o a d d t o t h e m a i l _ p l u g i n s v a r i a b l e , p e r p r o t o c o l " ;
2020-01-28 12:00:00 +00:00
type = attrsOf ( plugins " c o r r e s p o n d i n g p e r - p r o t o c o l " ) ;
default = { } ;
example = {
imap = [ " i m a p _ a c l " ] ;
} ;
} ;
} ;
2019-12-31 12:00:00 +00:00
} ;
2020-01-28 12:00:00 +00:00
description = " A d d i t i o n a l e n t r i e s t o a d d t o t h e m a i l _ p l u g i n s v a r i a b l e , g l o b a l l y a n d p e r p r o t o c o l " ;
example = {
globally . enable = [ " a c l " ] ;
perProtocol . imap . enable = [ " i m a p _ a c l " ] ;
2019-12-31 12:00:00 +00:00
} ;
2023-10-18 22:59:26 +02:00
default = {
2023-12-17 17:09:10 +01:00
globally . enable = [ ] ;
2020-01-28 12:00:00 +00:00
perProtocol = { } ;
2024-12-10 20:29:24 +01:00
} ;
} ;
2019-12-31 12:00:00 +00:00
2015-12-09 10:27:44 +01:00
configFile = mkOption {
2019-10-04 09:57:06 +02:00
type = types . nullOr types . path ;
2015-12-09 10:27:44 +01:00
default = null ;
description = " C o n f i g f i l e u s e d f o r t h e w h o l e d o v e c o t c o n f i g u r a t i o n . " ;
apply = v : if v != null then v else pkgs . writeText " d o v e c o t . c o n f " dovecotConf ;
} ;
2012-09-21 16:04:46 +02:00
2015-12-09 10:27:44 +01:00
mailLocation = mkOption {
type = types . str ;
default = " m a i l d i r : / v a r / s p o o l / m a i l / % u " ; # Same as inbox, as postfix
example = " m a i l d i r : ~ / m a i l : I N B O X = / v a r / s p o o l / m a i l / % u " ;
description = ''
Location that dovecot will use for mail folders . Dovecot mail_location option .
'' ;
} ;
2015-01-19 10:45:20 +01:00
2016-01-10 07:07:26 +03:00
mailUser = mkOption {
type = types . nullOr types . str ;
default = null ;
description = " D e f a u l t u s e r t o s t o r e m a i l f o r v i r t u a l u s e r s . " ;
} ;
mailGroup = mkOption {
type = types . nullOr types . str ;
default = null ;
description = " D e f a u l t g r o u p t o s t o r e m a i l f o r v i r t u a l u s e r s . " ;
} ;
2022-01-20 00:35:12 +01:00
createMailUser =
mkEnableOption ''
automatically creating the user
given in { option } ` services . dovecot . user ` and the group
2024-08-02 23:19:41 +08:00
given in { option } ` services . dovecot . group ` ''
// {
default = true ;
} ;
2017-08-15 12:14:29 +02:00
2015-12-09 10:27:44 +01:00
modules = mkOption {
type = types . listOf types . package ;
default = [ ] ;
2021-10-03 18:06:03 +02:00
example = literalExpression " [ p k g s . d o v e c o t _ p i g e o n h o l e ] " ;
2015-12-09 10:27:44 +01:00
description = ''
Symlinks the contents of lib/dovecot of every given package into
2016-01-10 07:00:34 +03:00
/etc/dovecot/modules. This will make the given modules available
2016-04-22 17:21:17 +02:00
if a dovecot package with the module_dir patch applied is being used .
2015-12-09 10:27:44 +01:00
'' ;
} ;
2012-06-10 15:07:25 +00:00
2015-12-09 10:27:44 +01:00
sslCACert = mkOption {
type = types . nullOr types . str ;
default = null ;
description = " P a t h t o t h e s e r v e r ' s C A c e r t i f i c a t e k e y . " ;
} ;
2011-10-27 19:43:20 +00:00
2015-12-09 10:27:44 +01:00
sslServerCert = mkOption {
type = types . nullOr types . str ;
default = null ;
description = " P a t h t o t h e s e r v e r ' s p u b l i c k e y . " ;
} ;
2011-10-27 19:43:20 +00:00
2015-12-09 10:27:44 +01:00
sslServerKey = mkOption {
type = types . nullOr types . str ;
default = null ;
description = " P a t h t o t h e s e r v e r ' s p r i v a t e k e y . " ;
} ;
2011-10-27 19:43:20 +00:00
2023-02-01 06:12:57 +01:00
enablePAM = mkEnableOption " c r e a t i n g a o w n D o v e c o t P A M s e r v i c e a n d c o n f i g u r e P A M u s e r l o g i n s " // {
default = true ;
} ;
2011-10-27 19:43:20 +00:00
2023-10-18 22:59:26 +02:00
enableDHE = mkEnableOption " s s l _ d h a n d g e n e r a t i o n o f p r i m e s f o r t h e k e y e x c h a n g e " // {
default = true ;
} ;
2022-01-19 22:39:57 +01:00
2023-02-01 06:12:57 +01:00
showPAMFailure = mkEnableOption " s h o w i n g t h e P A M f a i l u r e m e s s a g e o n a u t h e n t i c a t i o n e r r o r ( u s e f u l f o r O T P W ) " ;
2017-08-15 12:14:29 +02:00
mailboxes = mkOption {
2020-08-18 01:57:31 +02:00
type =
with types ;
coercedTo ( listOf unspecified ) (
list :
listToAttrs (
map ( entry : {
name = entry . name ;
value = removeAttrs entry [ " n a m e " ] ;
} ) list
)
) ( attrsOf ( submodule mailboxes ) ) ;
2020-06-04 16:10:32 +02:00
default = { } ;
2021-10-03 18:06:03 +02:00
example = literalExpression ''
2020-06-04 16:10:32 +02:00
{
Spam = { specialUse = " J u n k " ; auto = " c r e a t e " ; } ;
}
'' ;
2017-08-15 12:14:29 +02:00
description = " C o n f i g u r e m a i l b o x e s a n d a u t o c r e a t e o r s u b s c r i b e t h e m . " ;
} ;
2023-02-01 06:12:57 +01:00
enableQuota = mkEnableOption " t h e d o v e c o t q u o t a s e r v i c e " ;
2017-08-15 12:14:29 +02:00
quotaPort = mkOption {
type = types . str ;
default = " 1 2 3 4 0 " ;
description = ''
The Port the dovecot quota service binds to .
If using postfix , add check_policy_service inet:localhost:12340 to your smtpd_recipient_restrictions in your postfix config .
'' ;
} ;
quotaGlobalPerUser = mkOption {
type = types . str ;
default = " 1 0 0 G " ;
example = " 1 0 G " ;
description = " Q u o t a l i m i t f o r t h e u s e r i n b y t e s . S u p p o r t s s u f f i x e s b , k , M , G , T a n d % . " ;
} ;
2024-01-14 21:07:42 +01:00
pluginSettings = mkOption {
# types.str does not coerce from packages, like `sievePipeBinScriptDirectory`.
type = types . attrsOf (
types . oneOf [
types . str
types . package
]
) ;
default = { } ;
example = literalExpression ''
{
sieve = " f i l e : ~ / s i e v e ; a c t i v e = ~ / . d o v e c o t . s i e v e " ;
}
'' ;
description = ''
Plugin settings for dovecot in general , e . g . ` sieve ` , ` sieve_default ` , etc .
Some of the other knobs of this module will influence by default the plugin settings , but you
can still override any plugin settings .
If you override a plugin setting , its value is cleared and you have to copy over the defaults .
'' ;
} ;
2023-12-17 17:09:10 +01:00
imapsieve . mailbox = mkOption {
default = [ ] ;
description = " C o n f i g u r e S i e v e f i l t e r i n g r u l e s o n I M A P a c t i o n s " ;
type = types . listOf (
types . submodule (
{ config , . . . }:
{
options = {
name = mkOption {
description = ''
This setting configures the name of a mailbox for which administrator scripts are configured .
The settings defined hereafter with matching sequence numbers apply to the mailbox named by this setting .
This setting supports wildcards with a syntax compatible with the IMAP LIST command , meaning that this setting can apply to multiple or even all ( " * " ) mailboxes .
'' ;
example = " J u n k " ;
type = types . str ;
} ;
from = mkOption {
2024-01-14 21:42:40 +01:00
default = null ;
2023-12-17 17:09:10 +01:00
description = ''
Only execute the administrator Sieve scripts for the mailbox configured with services . dovecot2 . imapsieve . mailbox . <name> . name when the message originates from the indicated mailbox .
This setting supports wildcards with a syntax compatible with the IMAP LIST command , meaning that this setting can apply to multiple or even all ( " * " ) mailboxes .
'' ;
2024-01-14 21:42:40 +01:00
example = " * " ;
type = types . nullOr types . str ;
2023-12-17 17:09:10 +01:00
} ;
causes = mkOption {
default = [ ] ;
description = ''
Only execute the administrator Sieve scripts for the mailbox configured with services . dovecot2 . imapsieve . mailbox . <name> . name when one of the listed IMAPSIEVE causes apply .
2024-12-10 20:29:24 +01:00
2023-12-17 17:09:10 +01:00
This has no effect on the user script , which is always executed no matter the cause .
2024-12-10 20:29:24 +01:00
'' ;
2023-12-17 17:09:10 +01:00
example = [
2024-12-10 20:29:24 +01:00
" C O P Y "
2023-12-17 17:09:10 +01:00
" A P P E N D "
2024-12-10 20:29:24 +01:00
] ;
2023-12-17 17:09:10 +01:00
type = types . listOf (
2024-12-10 20:29:24 +01:00
types . enum [
" A P P E N D "
" C O P Y "
" F L A G "
]
) ;
} ;
2023-12-17 17:09:10 +01:00
before = mkOption {
default = null ;
description = ''
When an IMAP event of interest occurs , this sieve script is executed before any user script respectively .
This setting each specify the location of a single sieve script . The semantics of this setting is similar to sieve_before : the specified scripts form a sequence together with the user script in which the next script is only executed when an ( implicit ) keep action is executed .
2024-12-10 20:29:24 +01:00
'' ;
2023-12-17 17:09:10 +01:00
example = literalExpression " . / r e p o r t - s p a m . s i e v e " ;
type = types . nullOr types . path ;
2024-12-10 20:29:24 +01:00
} ;
2023-12-17 17:09:10 +01:00
after = mkOption {
default = null ;
description = ''
2024-01-14 21:07:42 +01:00
When an IMAP event of interest occurs , this sieve script is executed after any user script respectively .
2024-12-10 20:29:24 +01:00
2023-12-17 17:09:10 +01:00
This setting each specify the location of a single sieve script . The semantics of this setting is similar to sieve_after : the specified scripts form a sequence together with the user script in which the next script is only executed when an ( implicit ) keep action is executed .
'' ;
example = literalExpression " . / r e p o r t - s p a m . s i e v e " ;
type = types . nullOr types . path ;
} ;
} ;
}
2024-12-10 20:29:24 +01:00
)
2023-12-17 17:09:10 +01:00
) ;
} ;
sieve = {
plugins = mkOption {
default = [ ] ;
example = [ " s i e v e _ e x t p r o g r a m s " ] ;
description = " S i e v e p l u g i n s t o l o a d " ;
type = types . listOf types . str ;
} ;
extensions = mkOption {
default = [ ] ;
description = " S i e v e e x t e n s i o n s f o r u s e i n u s e r s c r i p t s " ;
example = [
" n o t i f y "
" i m a p f l a g s "
" v n d . d o v e c o t . f i l t e r "
] ;
type = types . listOf types . str ;
} ;
globalExtensions = mkOption {
default = [ ] ;
example = [ " v n d . d o v e c o t . e n v i r o n m e n t " ] ;
description = " S i e v e e x t e n s i o n s f o r u s e i n g l o b a l s c r i p t s " ;
type = types . listOf types . str ;
} ;
2024-01-14 21:07:42 +01:00
scripts = mkOption {
type = types . attrsOf types . path ;
default = { } ;
description = " S i e v e s c r i p t s t o b e e x e c u t e d . K e y i s a s e q u e n c e , e . g . ' b e f o r e 2 ' , ' a f t e r ' e t c . " ;
} ;
2023-12-17 17:09:10 +01:00
pipeBins = mkOption {
default = [ ] ;
example = literalExpression ''
map lib . getExe [
( pkgs . writeShellScriptBin " l e a r n - h a m . s h " " e x e c ' ' ${ pkgs . rspamd } / b i n / r s p a m c l e a r n _ h a m " )
( pkgs . writeShellScriptBin " l e a r n - s p a m . s h " " e x e c ' ' ${ pkgs . rspamd } / b i n / r s p a m c l e a r n _ s p a m " )
]
'' ;
description = " P r o g r a m s a v a i l a b l e f o r u s e b y t h e v n d . d o v e c o t . p i p e e x t e n s i o n " ;
type = types . listOf types . path ;
} ;
} ;
2011-10-27 19:43:20 +00:00
} ;
2015-12-09 10:27:44 +01:00
config = mkIf cfg . enable {
security . pam . services . dovecot2 = mkIf cfg . enablePAM { } ;
2011-10-27 19:43:20 +00:00
2022-01-19 22:39:57 +01:00
security . dhparams = mkIf ( cfg . sslServerCert != null && cfg . enableDHE ) {
2018-04-25 21:18:26 +00:00
enable = true ;
2018-05-10 08:29:29 +02:00
params . dovecot2 = { } ;
2018-04-25 21:18:26 +00:00
} ;
2023-12-17 17:09:10 +01:00
services . dovecot2 = {
protocols =
optional cfg . enableImap " i m a p " ++ optional cfg . enablePop3 " p o p 3 " ++ optional cfg . enableLmtp " l m t p " ;
mailPlugins = mkIf cfg . enableQuota {
globally . enable = [ " q u o t a " ] ;
perProtocol . imap . enable = [ " i m a p _ q u o t a " ] ;
} ;
sieve . plugins =
optional ( cfg . imapsieve . mailbox != [ ] ) " s i e v e _ i m a p s i e v e "
++ optional ( cfg . sieve . pipeBins != [ ] ) " s i e v e _ e x t p r o g r a m s " ;
sieve . globalExtensions = optional ( cfg . sieve . pipeBins != [ ] ) " v n d . d o v e c o t . p i p e " ;
2024-01-14 21:07:42 +01:00
pluginSettings = lib . mapAttrs ( n : lib . mkDefault ) (
{
sieve_plugins = concatStringsSep " " cfg . sieve . plugins ;
sieve_extensions = concatStringsSep " " ( map ( el : " + ${ el } " ) cfg . sieve . extensions ) ;
sieve_global_extensions = concatStringsSep " " ( map ( el : " + ${ el } " ) cfg . sieve . globalExtensions ) ;
sieve_pipe_bin_dir = sievePipeBinScriptDirectory ;
}
// sieveScriptSettings
// imapSieveMailboxSettings
) ;
2019-12-31 12:00:00 +00:00
} ;
2019-09-14 19:51:29 +02:00
users . users =
{
dovenull = {
2020-01-28 12:00:00 +00:00
uid = config . ids . uids . dovenull2 ;
2019-09-14 19:51:29 +02:00
description = " D o v e c o t u s e r f o r u n t r u s t e d l o g i n s " ;
group = " d o v e n u l l " ;
} ;
}
// optionalAttrs ( cfg . user = = " d o v e c o t 2 " ) {
dovecot2 = {
2020-01-28 12:00:00 +00:00
uid = config . ids . uids . dovecot2 ;
description = " D o v e c o t u s e r " ;
group = cfg . group ;
} ;
2019-09-14 19:51:29 +02:00
}
// optionalAttrs ( cfg . createMailUser && cfg . mailUser != null ) {
$ { cfg . mailUser } = {
2021-04-16 00:42:43 +02:00
description = " V i r t u a l M a i l U s e r " ;
isSystemUser = true ;
} // optionalAttrs ( cfg . mailGroup != null ) { group = cfg . mailGroup ; } ;
2019-09-14 19:51:29 +02:00
} ;
users . groups =
{
dovenull . gid = config . ids . gids . dovenull2 ;
}
// optionalAttrs ( cfg . group = = " d o v e c o t 2 " ) {
dovecot2 . gid = config . ids . gids . dovecot2 ;
}
// optionalAttrs ( cfg . createMailUser && cfg . mailGroup != null ) {
2020-01-28 12:00:00 +00:00
$ { cfg . mailGroup } = { } ;
2019-09-14 19:51:29 +02:00
} ;
2015-01-19 10:45:20 +01:00
2016-01-10 07:00:34 +03:00
environment . etc . " d o v e c o t / m o d u l e s " . source = modulesDir ;
2016-01-10 07:02:24 +03:00
environment . etc . " d o v e c o t / d o v e c o t . c o n f " . source = cfg . configFile ;
2016-01-10 07:00:34 +03:00
2015-12-09 10:27:44 +01:00
systemd . services . dovecot2 = {
description = " D o v e c o t I M A P / P O P 3 s e r v e r " ;
2019-08-24 16:52:17 +02:00
after = [ " n e t w o r k . t a r g e t " ] ;
2015-12-09 10:27:44 +01:00
wantedBy = [ " m u l t i - u s e r . t a r g e t " ] ;
2020-05-08 12:00:00 +00:00
restartTriggers = [
cfg . configFile
modulesDir
] ;
2015-12-09 10:27:44 +01:00
2020-09-09 00:31:27 -07:00
startLimitIntervalSec = 60 ; # 1 min
2015-12-09 10:27:44 +01:00
serviceConfig = {
2021-08-20 12:12:52 +02:00
Type = " n o t i f y " ;
2016-01-10 07:02:24 +03:00
ExecStart = " ${ dovecotPkg } / s b i n / d o v e c o t - F " ;
ExecReload = " ${ dovecotPkg } / s b i n / d o v e a d m r e l o a d " ;
2015-12-09 10:27:44 +01:00
Restart = " o n - f a i l u r e " ;
RestartSec = " 1 s " ;
2016-01-09 04:15:25 +03:00
RuntimeDirectory = [ " d o v e c o t 2 " ] ;
2011-10-27 19:43:20 +00:00
} ;
2016-01-10 07:05:12 +03:00
2017-01-13 14:19:29 -07:00
# When copying sieve scripts preserve the original time stamp
# (should be 0) so that the compiled sieve script is newer than
# the source file and Dovecot won't try to compile it.
2016-01-10 07:05:12 +03:00
preStart =
''
2023-12-17 17:09:10 +01:00
rm - rf $ { stateDir } /sieve $ { stateDir } /imapsieve
2024-01-14 21:07:42 +01:00
''
+ optionalString ( cfg . sieve . scripts != { } ) ''
2016-01-10 07:05:12 +03:00
mkdir - p $ { stateDir } /sieve
2020-01-28 12:00:00 +00:00
$ { concatStringsSep " \n " (
mapAttrsToList ( to : from : ''
if [ - d ' $ { from } ' ] ; then
mkdir ' $ { stateDir } /sieve / $ { to } '
cp - p " ${ from } / " * . sieve ' $ { stateDir } /sieve / $ { to } '
else
cp - p ' $ { from } ' ' $ { stateDir } /sieve / $ { to } '
fi
$ { pkgs . dovecot_pigeonhole } /bin/sievec ' $ { stateDir } /sieve / $ { to } '
2024-01-14 21:07:42 +01:00
'' ) c f g . s i e v e . s c r i p t s
2020-01-28 12:00:00 +00:00
) }
2016-01-10 07:07:26 +03:00
chown - R ' $ { cfg . mailUser }: $ { cfg . mailGroup } ' ' $ { stateDir } /sieve '
2023-12-17 17:09:10 +01:00
''
+ optionalString ( cfg . imapsieve . mailbox != [ ] ) ''
mkdir - p $ { stateDir } /imapsieve / { before , after }
2024-12-10 20:29:24 +01:00
2023-12-17 17:09:10 +01:00
$ { concatMapStringsSep " \n " (
el :
optionalString ( el . before != null ) ''
cp - p $ { el . before } $ { stateDir } /imapsieve/before / $ { baseNameOf el . before }
$ { pkgs . dovecot_pigeonhole } /bin/sievec ' $ { stateDir } /imapsieve/before / $ { baseNameOf el . before } '
''
+ optionalString ( el . after != null ) ''
cp - p $ { el . after } $ { stateDir } /imapsieve/after / $ { baseNameOf el . after }
$ { pkgs . dovecot_pigeonhole } /bin/sievec ' $ { stateDir } /imapsieve/after / $ { baseNameOf el . after } '
''
) cfg . imapsieve . mailbox }
2024-12-10 20:29:24 +01:00
2023-12-17 17:09:10 +01:00
$ { optionalString (
cfg . mailUser != null && cfg . mailGroup != null
) " c h o w n - R ' ${ cfg . mailUser } : ${ cfg . mailGroup } ' ' ${ stateDir } / i m a p s i e v e ' " }
2016-01-10 07:05:12 +03:00
'' ;
2015-12-09 10:27:44 +01:00
} ;
2011-10-27 19:43:20 +00:00
2015-12-09 10:27:44 +01:00
environment . systemPackages = [ dovecotPkg ] ;
2011-10-27 22:04:08 +00:00
2024-01-23 13:49:02 +01:00
warnings = warnAboutExtraConfigCollisions ;
2020-08-18 01:57:31 +02:00
2015-12-09 10:27:44 +01:00
assertions = [
2020-01-28 12:00:00 +00:00
{
assertion =
( cfg . sslServerCert = = null ) = = ( cfg . sslServerKey = = null )
&& ( cfg . sslCACert != null -> ! ( cfg . sslServerCert = = null || cfg . sslServerKey = = null ) ) ;
2015-12-09 10:27:44 +01:00
message = " d o v e c o t n e e d s b o t h s s l S e r v e r C e r t a n d s s l S e r v e r K e y d e f i n e d f o r w o r k i n g c r y p t o " ;
}
2020-01-28 12:00:00 +00:00
{
assertion = cfg . showPAMFailure -> cfg . enablePAM ;
2015-12-09 10:27:44 +01:00
message = " d o v e c o t i s c o n f i g u r e d w i t h s h o w P A M F a i l u r e w h i l e e n a b l e P A M i s d i s a b l e d " ;
}
2020-01-28 12:00:00 +00:00
{
2024-01-14 21:07:42 +01:00
assertion = cfg . sieve . scripts != { } -> ( cfg . mailUser != null && cfg . mailGroup != null ) ;
message = " d o v e c o t r e q u i r e s m a i l U s e r a n d m a i l G r o u p t o b e s e t w h e n ` s i e v e . s c r i p t s ` i s s e t " ;
2016-09-07 01:39:18 +00:00
}
2015-12-09 10:27:44 +01:00
] ;
2012-09-30 00:53:50 +02:00
2011-10-27 19:43:20 +00:00
} ;
2023-12-17 17:09:20 +01:00
meta . maintainers = [ lib . maintainers . dblsaiko ] ;
2011-10-27 19:43:20 +00:00
}