From b0a99da8843d982ab43e4a4f7bb21fa2a101ac1b Mon Sep 17 00:00:00 2001 From: Colin Date: Thu, 20 Apr 2023 14:25:59 +0000 Subject: [PATCH] dovecot: if mail fails DKIM, deliver it to Junk --- .../by-name/servo/services/email/dovecot.nix | 100 ++++++++++++++---- .../by-name/servo/services/email/postfix.nix | 36 +++++-- 2 files changed, 104 insertions(+), 32 deletions(-) diff --git a/hosts/by-name/servo/services/email/dovecot.nix b/hosts/by-name/servo/services/email/dovecot.nix index 7c59f75f..9c8f1c5b 100644 --- a/hosts/by-name/servo/services/email/dovecot.nix +++ b/hosts/by-name/servo/services/email/dovecot.nix @@ -1,5 +1,10 @@ # dovecot config options: -{ config, ... }: +# +# sieve docs: +# - sieve language examples: +# - sieve protocol/language: + +{ config, lib, pkgs, ... }: { networking.firewall.allowedTCPPorts = [ # exposed over non-vpn imap.uninsane.org @@ -24,31 +29,16 @@ # inspired by https://gitlab.com/simple-nixos-mailserver/nixos-mailserver/ services.dovecot2.enable = true; - services.dovecot2.mailboxes = { - # special-purpose mailboxes: "All" "Archive" "Drafts" "Flagged" "Junk" "Sent" "Trash" - # RFC6154 describes these special mailboxes: https://www.ietf.org/rfc/rfc6154.html - # how these boxes are treated is 100% up to the client and server to decide. - # client behavior: - # iOS - # - Drafts: ? - # - Sent: works - # - Trash: works - # - Junk: ? - # aerc - # - Drafts: works - # - Sent: works - # - Trash: no; deleted messages are actually deleted - # use `:move trash` instead - # - Junk: ? - # Sent mailbox: all sent messages are copied to it. unclear if this happens server-side or client-side. - Drafts = { specialUse = "Drafts"; auto = "create"; }; - Sent = { specialUse = "Sent"; auto = "create"; }; - Trash = { specialUse = "Trash"; auto = "create"; }; - Junk = { specialUse = "Junk"; auto = "create"; }; - }; + # services.dovecot2.enableLmtp = true; services.dovecot2.sslServerCert = "/var/lib/acme/imap.uninsane.org/fullchain.pem"; services.dovecot2.sslServerKey = "/var/lib/acme/imap.uninsane.org/key.pem"; services.dovecot2.enablePAM = false; + + # sieve scripts require me to set a user for... idk why? + services.dovecot2.mailUser = "colin"; + services.dovecot2.mailGroup = "users"; + users.users.colin.isSystemUser = lib.mkForce false; + services.dovecot2.extraConfig = let passwdFile = config.sops.secrets.dovecot_passwd.path; @@ -73,9 +63,73 @@ } auth_mechanisms = plain login + # accept incoming messaging from postfix + # service lmtp { + # unix_listener dovecot-lmtp { + # mode = 0600 + # user = postfix + # group = postfix + # } + # } + + # plugin { + # sieve_plugins = sieve_imapsieve + # } mail_debug = yes auth_debug = yes # verbose_ssl = yes ''; + + services.dovecot2.mailboxes = { + # special-purpose mailboxes: "All" "Archive" "Drafts" "Flagged" "Junk" "Sent" "Trash" + # RFC6154 describes these special mailboxes: https://www.ietf.org/rfc/rfc6154.html + # how these boxes are treated is 100% up to the client and server to decide. + # client behavior: + # iOS + # - Drafts: ? + # - Sent: works + # - Trash: works + # - Junk: works ("mark" -> "move to Junk") + # aerc + # - Drafts: works + # - Sent: works + # - Trash: no; deleted messages are actually deleted + # use `:move trash` instead + # - Junk: ? + # Sent mailbox: all sent messages are copied to it. unclear if this happens server-side or client-side. + Drafts = { specialUse = "Drafts"; auto = "create"; }; + Sent = { specialUse = "Sent"; auto = "create"; }; + Trash = { specialUse = "Trash"; auto = "create"; }; + Junk = { specialUse = "Junk"; auto = "create"; }; + }; + + services.dovecot2.mailPlugins = { + perProtocol = { + # imap.enable = [ + # "imap_sieve" + # ]; + lda.enable = [ + "sieve" + ]; + # lmtp.enable = [ + # "sieve" + # ]; + }; + }; + services.dovecot2.modules = [ + pkgs.dovecot_pigeonhole # enables sieve execution (?) + ]; + services.dovecot2.sieveScripts = { + # if any messages fail to pass (or lack) DKIM, move them to Junk + # XXX the key name ("after") is only used to order sieve execution/ordering + after = builtins.toFile "ensuredkim.sieve" '' + require "fileinto"; + + if not header :contains "Authentication-Results" "dkim=pass" { + fileinto "Junk"; + stop; + } + ''; + }; } diff --git a/hosts/by-name/servo/services/email/postfix.nix b/hosts/by-name/servo/services/email/postfix.nix index 946a6f30..b6539547 100644 --- a/hosts/by-name/servo/services/email/postfix.nix +++ b/hosts/by-name/servo/services/email/postfix.nix @@ -1,6 +1,6 @@ # postfix config options: -{ lib, ... }: +{ lib, pkgs, ... }: let submissionOptions = { @@ -88,24 +88,40 @@ in @uninsane.org colin ''; - services.postfix.extraConfig = '' + services.postfix.config = { # smtpd_milters = local:/run/opendkim/opendkim.sock # milter docs: http://www.postfix.org/MILTER_README.html - # mail filters for receiving email and authorized SMTP clients + # mail filters for receiving email and from authorized SMTP clients (i.e. via submission) # smtpd_milters = inet:185.157.162.190:8891 - smtpd_milters = unix:/run/opendkim/opendkim.sock + # opendkim.sock will add a Authentication-Results header, with `dkim=pass|fail|...` value to received messages + smtpd_milters = "unix:/run/opendkim/opendkim.sock"; # mail filters for sendmail - non_smtpd_milters = $smtpd_milters - milter_default_action = accept - inet_protocols = ipv4 - smtp_tls_security_level = may + non_smtpd_milters = "$smtpd_milters"; + + # what to do when a milter exits unexpectedly: + milter_default_action = "accept"; + + inet_protocols = "ipv4"; + smtp_tls_security_level = "may"; + + # hand received mail over to dovecot so that it can run sieves & such + mailbox_command = ''${pkgs.dovecot}/libexec/dovecot/dovecot-lda -f "$SENDER" -a "$RECIPIENT"''; + + # hand received mail over to dovecot + # virtual_alias_maps = [ + # "hash:/etc/postfix/virtual" + # ]; + # mydestination = ""; + # virtual_mailbox_domains = [ "localhost" "uninsane.org" ]; + # # virtual_mailbox_maps = "hash:/etc/postfix/virtual"; + # virtual_transport = "lmtp:unix:/run/dovecot2/dovecot-lmtp"; # anti-spam options: # reject_unknown_sender_domain: causes postfix to `dig MX` and make sure that exists. # but may cause problems receiving mail from google & others who load-balance? # - # smtpd_sender_restrictions = reject_unknown_sender_domain - ''; + }; services.postfix.enableSubmission = true; services.postfix.submissionOptions = submissionOptions; @@ -120,6 +136,8 @@ in }; + #### OPENDKIM + services.opendkim.enable = true; # services.opendkim.domains = "csl:uninsane.org"; services.opendkim.domains = "uninsane.org";