aboutsummaryrefslogblamecommitdiff
path: root/modules/private/mail/dovecot.nix
blob: 047d7d0b688549eb27e773e65c3c4b9cd2954341 (plain) (tree)


























































                                                                                                



















































































































































                                                                                                                       












                                                            
                                               

























                                                                        
{ lib, pkgs, config, myconfig,  ... }:
let
  sieve_bin = pkgs.runCommand "sieve_bin" {
    buildInputs = [ pkgs.makeWrapper ];
  } ''
    cp -a ${./sieve_bin} $out
    chmod -R u+w $out
    patchShebangs $out
    for i in $out/*; do
      wrapProgram "$i" --prefix PATH : ${lib.makeBinPath [ pkgs.coreutils ]}
    done
    '';
in
{
  config.secrets.keys = [
    {
      dest = "dovecot/ldap";
      user = config.services.dovecot2.user;
      group = config.services.dovecot2.group;
      permissions = "0400";
      text = ''
        hosts = ${myconfig.env.mail.dovecot.ldap.host}
        tls = yes

        dn = ${myconfig.env.mail.dovecot.ldap.dn}
        dnpass = ${myconfig.env.mail.dovecot.ldap.password}

        auth_bind = yes

        ldap_version = 3

        base = ${myconfig.env.mail.dovecot.ldap.base}
        scope = subtree

        user_filter = ${myconfig.env.mail.dovecot.ldap.filter}
        pass_filter = ${myconfig.env.mail.dovecot.ldap.filter}

        user_attrs = ${myconfig.env.mail.dovecot.ldap.user_attrs}
        pass_attrs = ${myconfig.env.mail.dovecot.ldap.pass_attrs}
        '';
    }
  ];

  config.users.users.vhost = {
    group = "vhost";
    uid = config.ids.uids.vhost;
  };
  config.users.groups.vhost.gid = config.ids.gids.vhost;

  # https://blog.zeninc.net/index.php?post/2018/04/01/Un-annuaire-pour-les-gouverner-tous.......
  config.services.dovecot2 = {
    enable = true;
    enablePAM = false;
    enablePop3 = true;
    enableImap = true;
    enableLmtp = true;
    protocols = [ "sieve" ];
    modules = [
      pkgs.dovecot_pigeonhole
      pkgs.dovecot_fts-xapian
    ];
    mailUser = "vhost";
    mailGroup = "vhost";
    createMailUser = false;
    mailboxes = [
      { name = "Trash";  auto = "subscribe"; specialUse = "Trash"; }
      { name = "Junk";   auto = "subscribe"; specialUse = "Junk"; }
      { name = "Sent";   auto = "subscribe"; specialUse = "Sent"; }
      { name = "Drafts"; auto = "subscribe"; specialUse = "Drafts"; }
    ];
    mailLocation = "mbox:~/Mail:INBOX=~/Mail/Inbox:INDEX=~/.imap";
    sslServerCert = "/var/lib/acme/mail/fullchain.pem";
    sslServerKey = "/var/lib/acme/mail/key.pem";
    sslCACert = "/var/lib/acme/mail/fullchain.pem";
    extraConfig = builtins.concatStringsSep "\n" [
      ''
        postmaster_address = postmaster@immae.eu
        mail_attribute_dict = file:%h/dovecot-attributes
        imap_idle_notify_interval = 20 mins
        namespace inbox {
          type = private
          separator = /
          inbox = yes
          list = yes
        }
      ''

      # Full text search
      ''
        # needs to be bigger than any mailbox size
        default_vsz_limit = 2GB
        mail_plugins = $mail_plugins fts fts_xapian
        plugin {
          plugin = fts fts_xapian
          fts = xapian
          fts_xapian = partial=2 full=20
          fts_autoindex = yes
          fts_autoindex_exclude = \Junk
          fts_autoindex_exclude2 = \Trash
          fts_autoindex_exclude3 = Virtual/*
        }
      ''

      # Antispam
      # https://docs.iredmail.org/dovecot.imapsieve.html
      ''
      # imap_sieve plugin added below

      plugin {
          sieve_plugins = sieve_imapsieve sieve_extprograms
          imapsieve_url = sieve://127.0.0.1:4190

          # From elsewhere to Junk folder
          imapsieve_mailbox1_name = Junk
          imapsieve_mailbox1_causes = COPY APPEND
          imapsieve_mailbox1_before = file:${./sieve_scripts}/report_spam.sieve;bindir=/var/lib/vhost/.imapsieve_bin

          # From Junk folder to elsewhere
          imapsieve_mailbox2_name = *
          imapsieve_mailbox2_from = Junk
          imapsieve_mailbox2_causes = COPY
          imapsieve_mailbox2_before = file:${./sieve_scripts}/report_ham.sieve;bindir=/var/lib/vhost/.imapsieve_bin

          sieve_pipe_bin_dir = ${sieve_bin}

          sieve_global_extensions = +vnd.dovecot.pipe +vnd.dovecot.environment
      }
      ''
      # Services to listen
      ''
      service imap-login {
        inet_listener imap {
        }
        inet_listener imaps {
        }
      }
      service pop3-login {
        inet_listener pop3 {
        }
        inet_listener pop3s {
        }
      }
      service imap {
      }
      service pop3 {
      }
      service auth {
        unix_listener auth-userdb {
        }
        unix_listener ${config.services.postfix.config.queue_directory}/private/auth {
          mode = 0666
        }
      }
      service auth-worker {
      }
      service dict {
        unix_listener dict {
        }
      }
      service stats {
        unix_listener stats-reader {
          user = vhost
          group = vhost
          mode = 0660
        }
        unix_listener stats-writer {
          user = vhost
          group = vhost
          mode = 0660
        }
      }
      ''

      # Authentification
      ''
      first_valid_uid = ${toString config.ids.uids.vhost}
      disable_plaintext_auth = yes
      passdb {
        driver = ldap
        args = ${config.secrets.fullPaths."dovecot/ldap"}
      }
      userdb {
        driver = static
        args = user=%u uid=vhost gid=vhost home=/var/lib/vhost/%d/%n/ mail=mbox:~/Mail:INBOX=~/Mail/Inbox:INDEX=~/.imap
      }
      ''

      # Zlib
      ''
      mail_plugins = $mail_plugins zlib
      plugin {
        zlib_save_level = 6
        zlib_save = gz
      }
      ''

      # Sieve
      ''
      plugin {
        sieve = file:~/sieve;bindir=~/.sieve-bin;active=~/.dovecot.sieve
      }
      service managesieve-login {
      }
      service managesieve {
      }
      ''

      # Virtual mailboxes
      ''
      mail_plugins = $mail_plugins virtual
      namespace Virtual {
        prefix = Virtual/
        location = virtual:~/Virtual
      }
      ''

      # Protocol specific configuration
      # Needs to come last if there are mail_plugins entries
      ''
      protocol imap {
        mail_plugins = $mail_plugins imap_sieve
      }
      protocol lda {
        mail_plugins = $mail_plugins sieve
      }
      ''
    ];
  };
  config.networking.firewall.allowedTCPPorts = [ 110 143 993 995 4190 ];
  config.system.activationScripts.dovecot = {
    deps = [ "users" ];
    text  =''
      install -m 0755 -o vhost -g vhost -d /var/lib/vhost
      '';
  };

  config.security.acme.certs."mail" = {
    postRun = ''
      systemctl restart dovecot2.service
    '';
    extraDomains = {
      "imap.immae.eu" = null;
      "pop3.immae.eu" = null;
    };
  };
}