204 lines
6.9 KiB
Nix
204 lines
6.9 KiB
Nix
{
|
|
config,
|
|
pkgs,
|
|
lib,
|
|
...
|
|
}: let
|
|
inherit (lib.modules) mkIf;
|
|
inherit (lib.strings) concatStringsSep;
|
|
inherit (lib.lists) flatten optional;
|
|
inherit (lib.attrsets) mapAttrsToList;
|
|
inherit (builtins) toFile;
|
|
|
|
mailConfig = config.services.mailserver;
|
|
|
|
tls_allowed = "TLSv1.3, TLSv1.2, TLSv1.1, !TLSv1, !SSLv2, !SSLv3";
|
|
tls_disallow = "MD5, DES, ADH, RC4, PSD, SRP, 3DES, eNULL, aNULL";
|
|
|
|
sendingReceivingAliases = concatStringsSep "\n" (flatten [
|
|
(mapAttrsToList (email: config:
|
|
map (
|
|
alias: "${alias} ${email} "
|
|
)
|
|
config.aliases)
|
|
mailConfig.accounts)
|
|
(mapAttrsToList (email: _config: [
|
|
# i dont know if this is actually needed
|
|
"${email} ${email}"
|
|
])
|
|
mailConfig.accounts)
|
|
]);
|
|
|
|
sendingReceivingAliasesMappedName = "sending_receiving_aliases";
|
|
sendingReceivingAliasesFile = toFile "${sendingReceivingAliasesMappedName}" sendingReceivingAliases;
|
|
|
|
extraAliasesCombinedFilePath = "/run/postfix_sending_receiving_aliases";
|
|
in {
|
|
config = mkIf mailConfig.enable {
|
|
systemd.tmpfiles.rules = mkIf (mailConfig.extraAliasesFile != null) [
|
|
"f ${extraAliasesCombinedFilePath} 660 root root"
|
|
];
|
|
|
|
systemd.services.postfix-extra-aliases-setup = mkIf (mailConfig.extraAliasesFile != null) {
|
|
wantedBy = ["multi-user.target"];
|
|
partOf = ["postfix.service"];
|
|
before = ["postfix-setup.service"];
|
|
script = ''
|
|
cat "${sendingReceivingAliasesFile}" > ${extraAliasesCombinedFilePath}
|
|
echo >> ${extraAliasesCombinedFilePath}
|
|
cat "${mailConfig.extraAliasesFile}" >> ${extraAliasesCombinedFilePath}
|
|
'';
|
|
};
|
|
|
|
services.postfix = let
|
|
mappedFile = name: "hash:/var/lib/postfix/conf/${name}";
|
|
|
|
sendingReceivingAliasesMappedFile = mappedFile sendingReceivingAliasesMappedName;
|
|
|
|
submissionOptions = {
|
|
smtpd_tls_security_level = "encrypt";
|
|
smtpd_sasl_auth_enable = "yes";
|
|
smtpd_sasl_type = "dovecot";
|
|
smtpd_sasl_path = "/run/dovecot2/auth";
|
|
smtpd_sasl_security_options = "noanonymous";
|
|
smtpd_sasl_local_domain = "$myhostname";
|
|
smtpd_client_restrictions = "permit_sasl_authenticated,reject";
|
|
smtpd_sender_login_maps = sendingReceivingAliasesMappedFile;
|
|
smtpd_sender_restrictions = "reject_sender_login_mismatch";
|
|
smtpd_recipient_restrictions = "reject_non_fqdn_recipient,reject_unknown_recipient_domain,permit_sasl_authenticated,reject";
|
|
cleanup_service_name = "submission-header-cleanup";
|
|
};
|
|
in {
|
|
enable = true;
|
|
hostname = "${mailConfig.fqdn}";
|
|
networksStyle = "host";
|
|
|
|
mapFiles = {
|
|
"sending_receiving_aliases" =
|
|
if (mailConfig.extraAliasesFile == null)
|
|
then sendingReceivingAliasesFile
|
|
else "${extraAliasesCombinedFilePath}";
|
|
};
|
|
|
|
enableSubmission = true;
|
|
enableSubmissions = true;
|
|
sslCert = mailConfig.sslConfig.cert;
|
|
sslKey = mailConfig.sslConfig.key;
|
|
|
|
config = {
|
|
# Extra Config
|
|
mydestination = "";
|
|
recipient_delimiter = "+";
|
|
smtpd_banner = "${mailConfig.fqdn} ESMTP NO UCE";
|
|
disable_vrfy_command = true;
|
|
message_size_limit = "20971520";
|
|
|
|
virtual_uid_maps = "static:${toString mailConfig.vmail.userID}";
|
|
virtual_gid_maps = "static:${toString mailConfig.vmail.groupID}";
|
|
virtual_mailbox_base = "${mailConfig.vmail.directory}";
|
|
virtual_mailbox_domains = toFile "vhosts" (concatStringsSep "\n" mailConfig.domains);
|
|
virtual_mailbox_maps = sendingReceivingAliasesMappedFile;
|
|
virtual_alias_maps = sendingReceivingAliasesMappedFile;
|
|
virtual_transport = "lmtp:unix:/run/dovecot2/dovecot-lmtp";
|
|
lmtp_destination_recipient_limit = "1";
|
|
|
|
smtpd_sasl_type = "dovecot";
|
|
smtpd_sasl_path = "/run/dovecot2/auth";
|
|
smtpd_sasl_auth_enable = true;
|
|
smtpd_relay_restrictions = [
|
|
"permit_mynetworks"
|
|
"permit_sasl_authenticated"
|
|
"reject_unauth_destination"
|
|
];
|
|
|
|
policy-spf_time_limit = mkIf mailConfig.spf.enable "3600s";
|
|
|
|
smtpd_recipient_restrictions = flatten [
|
|
(optional mailConfig.spf.enable "check_policy_service unix:private/policy-spf")
|
|
];
|
|
|
|
smtpd_tls_security_level = "may";
|
|
smtpd_tls_eecdh_grade = "ultra";
|
|
|
|
# Only Alow Modern TLS
|
|
smtp_tls_protocols = tls_allowed;
|
|
smtpd_tls_protocols = tls_allowed;
|
|
smtp_tls_mandatory_protocols = tls_allowed;
|
|
smtpd_tls_mandatory_protocols = tls_allowed;
|
|
|
|
# Disable Old Ciphers
|
|
smtp_tls_exclude_ciphers = tls_disallow;
|
|
smtpd_tls_exclude_ciphers = tls_disallow;
|
|
smtp_tls_mandatory_exclude_ciphers = tls_disallow;
|
|
smtpd_tls_mandatory_exclude_ciphers = tls_disallow;
|
|
|
|
smtp_tls_ciphers = "high";
|
|
smtpd_tls_ciphers = "high";
|
|
smtp_tls_mandatory_ciphers = "high";
|
|
smtpd_tls_mandatory_ciphers = "high";
|
|
|
|
tls_preempt_cipherlist = true;
|
|
|
|
smtpd_tls_auth_only = true;
|
|
smtpd_tls_loglevel = "1";
|
|
|
|
tls_random_source = "dev:/dev/urandom";
|
|
|
|
milter_default_action = "quarantine";
|
|
|
|
smtpd_milters = flatten [
|
|
(optional mailConfig.dkim.enable "unix:/run/opendkim/opendkim.sock")
|
|
];
|
|
|
|
non_smtpd_milters = flatten [
|
|
(optional mailConfig.dkim.enable "unix:/run/opendkim/opendkim.sock")
|
|
];
|
|
|
|
milter_protocol = "6";
|
|
milter_mail_macros = "i {mail_addr} {client_addr} {client_name} {auth_type} {auth_authen} {auth_author} {mail_addr} {mail_host} {mail_mailer}";
|
|
};
|
|
|
|
inherit submissionOptions;
|
|
submissionsOptions = submissionOptions;
|
|
|
|
masterConfig = {
|
|
"lmtp" = {
|
|
# Add headers when delivering, see http://www.postfix.org/smtp.8.html
|
|
# D => Delivered-To, O => X-Original-To, R => Return-Path
|
|
args = ["flags=O"];
|
|
};
|
|
"policy-spf" = mkIf mailConfig.spf.enable {
|
|
type = "unix";
|
|
privileged = true;
|
|
chroot = false;
|
|
command = "spawn";
|
|
args = let
|
|
policydConfig = toFile "policyd-spf.conf" mailConfig.spf.policydConfig;
|
|
in [
|
|
"user=nobody"
|
|
"argv=${pkgs.pypolicyd-spf}/bin/policyd-spf"
|
|
"${policydConfig}"
|
|
];
|
|
};
|
|
"submission-header-cleanup" = {
|
|
type = "unix";
|
|
private = false;
|
|
chroot = false;
|
|
maxproc = 0;
|
|
command = "cleanup";
|
|
args = let
|
|
submissionHeaderCleanupRules = toFile "submission_header_cleanup_rules" ''
|
|
/^Received:/ IGNORE
|
|
/^X-Originating-IP:/ IGNORE
|
|
/^X-Mailer:/ IGNORE
|
|
/^User-Agent:/ IGNORE
|
|
/^X-Enigmail:/ IGNORE
|
|
/^Message-ID:\s+<(.*?)@.*?>/ REPLACE Message-ID: <$1@${mailConfig.fqdn}>
|
|
'';
|
|
in ["-o" "header_checks=pcre:${submissionHeaderCleanupRules}"];
|
|
};
|
|
};
|
|
};
|
|
};
|
|
}
|