Skip to content

Commit

Permalink
postfix: Add submissions option for postfix and test
Browse files Browse the repository at this point in the history
RFC 8314 suggests, for end user submission of
mails, SMTP over TLS on port 465 should be used.

Closes NixOS#91690
  • Loading branch information
typetetris committed Jun 28, 2020
1 parent c6e52f2 commit a288521
Show file tree
Hide file tree
Showing 4 changed files with 173 additions and 0 deletions.
51 changes: 51 additions & 0 deletions nixos/modules/services/mail/postfix.nix
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,17 @@ in
description = "Whether to enable smtp submission.";
};

enableSubmissions = mkOption {
type = types.bool;
default = false;
description = ''
Whether to enable smtp submission via smtps.
According to RFC 8314 this should be preferred
over STARTTLS for submission of messages by end user clients.
'';
};

submissionOptions = mkOption {
type = types.attrs;
default = {
Expand All @@ -298,6 +309,29 @@ in
description = "Options for the submission config in master.cf";
};

submissionsOptions = mkOption {
type = types.attrs;
default = {
smtpd_sasl_auth_enable = "yes";
smtpd_client_restrictions = "permit_sasl_authenticated,reject";
milter_macro_daemon_name = "ORIGINATING";
};
example = {
smtpd_sasl_auth_enable = "yes";
smtpd_sasl_type = "dovecot";
smtpd_client_restrictions = "permit_sasl_authenticated,reject";
milter_macro_daemon_name = "ORIGINATING";
};
description = ''
Options for the submission config via smtps in master.cf.
smtpd_tls_security_level will be set to encrypt, if it is missing
or has one of the values "may" or "none".
smtpd_tls_wrappermode with value "yes" will be added automatically.
'';
};

setSendmail = mkOption {
type = types.bool;
default = true;
Expand Down Expand Up @@ -878,6 +912,23 @@ in
command = "smtp";
args = [ "-o" "smtp_fallback_relay=" ];
};
} // optionalAttrs cfg.enableSubmissions {
submissions = {
type = "inet";
private = false;
command = "smtpd";
args = let
mkKeyVal = opt: val: [ "-o" (opt + "=" + val) ];
adjustSmtpTlsSecurityLevel = !(cfg.submissionsOptions ? smtpd_tls_security_level) ||
cfg.submissionsOptions.smtpd_tls_security_level == "none" ||
cfg.submissionsOptions.smtpd_tls_security_level == "may";
submissionsOptions = cfg.submissionsOptions // {
smtpd_tls_wrappermode = "yes";
} // optionalAttrs adjustSmtpTlsSecurityLevel {
smtpd_tls_security_level = "encrypt";
};
in concatLists (mapAttrsToList mkKeyVal submissionsOptions);
};
};
}

Expand Down
2 changes: 2 additions & 0 deletions nixos/tests/all-tests.nix
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,8 @@ in
plasma5 = handleTest ./plasma5.nix {};
plotinus = handleTest ./plotinus.nix {};
podman = handleTest ./podman.nix {};
postfix = handleTest ./postfix.nix {};
postfix-raise-smtpd-tls-security-level = handleTest ./postfix-raise-smtpd-tls-security-level.nix {};
postgis = handleTest ./postgis.nix {};
postgresql = handleTest ./postgresql.nix {};
postgresql-wal-receiver = handleTest ./postgresql-wal-receiver.nix {};
Expand Down
44 changes: 44 additions & 0 deletions nixos/tests/postfix-raise-smtpd-tls-security-level.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
let
certs = import ./common/acme/server/snakeoil-certs.nix;
in
import ./make-test-python.nix {
name = "postfix";

machine = { pkgs, ... }: {
imports = [ common/user-account.nix ];
services.postfix = {
enable = true;
enableSubmissions = true;
submissionsOptions = {
smtpd_tls_security_level = "none";
};
};

environment.systemPackages = let
checkConfig = pkgs.writeScriptBin "check-config" ''
#!${pkgs.python3.interpreter}
import sys
state = 1
success = False
with open("/etc/postfix/master.cf") as masterCf:
for line in masterCf:
if state == 1 and line.startswith("submissions"):
state = 2
elif state == 2 and line.startswith(" ") and "smtpd_tls_security_level=encrypt" in line:
success = True
elif state == 2 and not line.startswith(" "):
state == 3
if not success:
sys.exit(1)
'';

in [ checkConfig ];
};

testScript = ''
machine.wait_for_unit("postfix.service")
machine.succeed("check-config")
'';
}
76 changes: 76 additions & 0 deletions nixos/tests/postfix.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
let
certs = import ./common/acme/server/snakeoil-certs.nix;
in
import ./make-test-python.nix {
name = "postfix";

machine = { pkgs, ... }: {
imports = [ common/user-account.nix ];
services.postfix = {
enable = true;
enableSubmission = true;
enableSubmissions = true;
sslCACert = certs.ca.cert;
sslCert = certs."acme.test".cert;
sslKey = certs."acme.test".key;
submissionsOptions = {
smtpd_sasl_auth_enable = "yes";
smtpd_client_restrictions = "permit";
milter_macro_daemon_name = "ORIGINATING";
};
};

security.pki.certificateFiles = [
certs.ca.cert
];

networking.extraHosts = ''
127.0.0.1 acme.test
'';

environment.systemPackages = let
sendTestMail = pkgs.writeScriptBin "send-testmail" ''
#!${pkgs.python3.interpreter}
import smtplib
with smtplib.SMTP('acme.test') as smtp:
smtp.sendmail('root@localhost', 'alice@localhost', 'Subject: Test\n\nTest data.')
smtp.quit()
'';

sendTestMailStarttls = pkgs.writeScriptBin "send-testmail-starttls" ''
#!${pkgs.python3.interpreter}
import smtplib
import ssl
ctx = ssl.create_default_context()
with smtplib.SMTP('acme.test') as smtp:
smtp.ehlo()
smtp.starttls(context=ctx)
smtp.ehlo()
smtp.sendmail('root@localhost', 'alice@localhost', 'Subject: Test STARTTLS\n\nTest data.')
smtp.quit()
'';

sendTestMailSmtps = pkgs.writeScriptBin "send-testmail-smtps" ''
#!${pkgs.python3.interpreter}
import smtplib
import ssl
ctx = ssl.create_default_context()
with smtplib.SMTP_SSL(host='acme.test', context=ctx) as smtp:
smtp.sendmail('root@localhost', 'alice@localhost', 'Subject: Test SMTPS\n\nTest data.')
smtp.quit()
'';
in [ sendTestMail sendTestMailStarttls sendTestMailSmtps ];
};

testScript = ''
machine.wait_for_unit("postfix.service")
machine.succeed("send-testmail")
machine.succeed("send-testmail-starttls")
machine.succeed("send-testmail-smtps")
'';
}

0 comments on commit a288521

Please sign in to comment.