{ config, pkgs, ... }:
let
  hostname = "mail.${config.networking.domain}";
  dovecot-ldap-args = pkgs.writeText "ldap-args" ''
    uris = ldap://localhost
    dn = uid=search, ou=users, dc=ifsr, dc=de
    auth_bind = yes
    !include ${config.sops.secrets."dovecot_ldap_search".path}

    ldap_version = 3
    scope = subtree
    base = dc=ifsr, dc=de
    user_filter = (&(objectClass=posixAccount)(uid=%n))
    pass_filter = (&(objectClass=posixAccount)(uid=%n))
  '';
in
{
  networking.firewall.allowedTCPPorts = [
    143 # IMAP
    993 # IMAPS
    4190 # Managesieve
  ];
  sops.secrets."dovecot_ldap_search".owner = config.services.dovecot2.user;
  environment.etc = {
    "dovecot/sieve-pipe/sa-learn-spam.sh" = {
      text = ''
        #!/bin/sh
        ${pkgs.rspamd}/bin/rspamc learn_spam
      '';
      mode = "0555";
    };
    "dovecot/sieve-pipe/sa-learn-ham.sh" = {
      text = ''
        #!/bin/sh
        ${pkgs.rspamd}/bin/rspamc learn_ham
      '';
      mode = "0555";
    };
    "dovecot/sieve/report-spam.sieve" = {
      source = ./report-spam.sieve;
      user = "dovecot2";
      group = "dovecot2";
      mode = "0544";
    };
    "dovecot/sieve/report-ham.sieve" = {
      source = ./report-ham.sieve;
      user = "dovecot2";
      group = "dovecot2";
      mode = "0544";
    };
  };

  services.dovecot2 = {
    enable = true;
    enableImap = true;
    enableQuota = true;
    quotaGlobalPerUser = "10G";
    enableLmtp = true;
    enablePAM = false;
    mailLocation = "maildir:~/Maildir";
    sslServerCert = "/var/lib/acme/${hostname}/fullchain.pem";
    sslServerKey = "/var/lib/acme/${hostname}/key.pem";
    protocols = [ "imap" "sieve" ];
    mailPlugins = {
      globally.enable = [ "listescape" ];
      perProtocol = {
        imap = {
          enable = [ "imap_sieve" "imap_filter_sieve" ];
        };
        lmtp = {
          enable = [ "sieve" ];
        };
      };
    };
    mailboxes = {
      Spam = {
        auto = "subscribe";
        specialUse = "Junk";
        autoexpunge = "60d";
      };
      Sent = {
        auto = "subscribe";
        specialUse = "Sent";
      };
      Drafts = {
        auto = "subscribe";
        specialUse = "Drafts";
      };
      Trash = {
        auto = "subscribe";
        specialUse = "Trash";
      };
      Archive = {
        auto = "no";
        specialUse = "Archive";
      };
    };
    modules = [
      pkgs.dovecot_pigeonhole
    ];
    # set to satisfy the sieveScripts check, will be overridden by userdb lookups anyways
    mailUser = "vmail";
    mailGroup = "vmail";
    sieveScripts = {
      before = pkgs.writeText "spam.sieve" ''
        require "fileinto";

        if anyof(
        header :contains "x-spam-flag" "yes",
        header :contains "X-Spam-Status" "Yes"){
                fileinto "Spam";
        }
      '';
    };
    extraConfig = ''
      auth_username_format = %Ln
      passdb {
        driver = ldap
        args = ${dovecot-ldap-args}
      }
      userdb {
        driver = ldap
        args = ${dovecot-ldap-args}
      }
      service auth {
        unix_listener /var/lib/postfix/auth {
          group = postfix
          mode = 0660
          user = postfix
        }
      }
      service managesieve-login {
        inet_listener sieve {
          port = 4190
        }
        service_count = 1
      }

      namespace inbox {
        separator = /
        inbox = yes
      }

      service lmtp {
        unix_listener dovecot-lmtp {
          group = postfix
          mode = 0600
          user = postfix
        }
        client_limit = 1
      }


      plugin {
        sieve_plugins = sieve_imapsieve sieve_extprograms
        sieve_global_extensions = +vnd.dovecot.pipe
        sieve_pipe_bin_dir = /etc/dovecot/sieve-pipe

        # Spam: From elsewhere to Spam folder or flag changed in Spam folder
        imapsieve_mailbox1_name = Spam
        imapsieve_mailbox1_causes = COPY APPEND FLAG
        imapsieve_mailbox1_before = file:/etc/dovecot/sieve/report-spam.sieve

        # Ham: From Spam folder to elsewhere
        imapsieve_mailbox2_name = *
        imapsieve_mailbox2_from = Spam
        imapsieve_mailbox2_causes = COPY
        imapsieve_mailbox2_before = file:/etc/dovecot/sieve/report-ham.sieve

        # https://doc.dovecot.org/configuration_manual/plugins/listescape_plugin/
        listescape_char = "\\"
      }
    '';
  };
}