aboutsummaryrefslogtreecommitdiff
path: root/nixpkgs/nixos/modules/services/mail/clamsmtp.nix
diff options
context:
space:
mode:
Diffstat (limited to 'nixpkgs/nixos/modules/services/mail/clamsmtp.nix')
-rw-r--r--nixpkgs/nixos/modules/services/mail/clamsmtp.nix181
1 files changed, 181 insertions, 0 deletions
diff --git a/nixpkgs/nixos/modules/services/mail/clamsmtp.nix b/nixpkgs/nixos/modules/services/mail/clamsmtp.nix
new file mode 100644
index 00000000000..fc1267c5d28
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/mail/clamsmtp.nix
@@ -0,0 +1,181 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+let
+ cfg = config.services.clamsmtp;
+ clamdSocket = "/run/clamav/clamd.ctl"; # See services/security/clamav.nix
+in
+{
+ ##### interface
+ options = {
+ services.clamsmtp = {
+ enable = mkOption {
+ type = types.bool;
+ default = false;
+ description = "Whether to enable clamsmtp.";
+ };
+
+ instances = mkOption {
+ description = "Instances of clamsmtp to run.";
+ type = types.listOf (types.submodule { options = {
+ action = mkOption {
+ type = types.enum [ "bounce" "drop" "pass" ];
+ default = "drop";
+ description =
+ ''
+ Action to take when a virus is detected.
+
+ Note that viruses often spoof sender addresses, so bouncing is
+ in most cases not a good idea.
+ '';
+ };
+
+ header = mkOption {
+ type = types.str;
+ default = "";
+ example = "X-Virus-Scanned: ClamAV using ClamSMTP";
+ description =
+ ''
+ A header to add to scanned messages. See clamsmtpd.conf(5) for
+ more details. Empty means no header.
+ '';
+ };
+
+ keepAlives = mkOption {
+ type = types.int;
+ default = 0;
+ description =
+ ''
+ Number of seconds to wait between each NOOP sent to the sending
+ server. 0 to disable.
+
+ This is meant for slow servers where the sending MTA times out
+ waiting for clamd to scan the file.
+ '';
+ };
+
+ listen = mkOption {
+ type = types.str;
+ example = "127.0.0.1:10025";
+ description =
+ ''
+ Address to wait for incoming SMTP connections on. See
+ clamsmtpd.conf(5) for more details.
+ '';
+ };
+
+ quarantine = mkOption {
+ type = types.bool;
+ default = false;
+ description =
+ ''
+ Whether to quarantine files that contain viruses by leaving them
+ in the temporary directory.
+ '';
+ };
+
+ maxConnections = mkOption {
+ type = types.int;
+ default = 64;
+ description = "Maximum number of connections to accept at once.";
+ };
+
+ outAddress = mkOption {
+ type = types.str;
+ description =
+ ''
+ Address of the SMTP server to send email to once it has been
+ scanned.
+ '';
+ };
+
+ tempDirectory = mkOption {
+ type = types.str;
+ default = "/tmp";
+ description =
+ ''
+ Temporary directory that needs to be accessible to both clamd
+ and clamsmtpd.
+ '';
+ };
+
+ timeout = mkOption {
+ type = types.int;
+ default = 180;
+ description = "Time-out for network connections.";
+ };
+
+ transparentProxy = mkOption {
+ type = types.bool;
+ default = false;
+ description = "Enable clamsmtp's transparent proxy support.";
+ };
+
+ virusAction = mkOption {
+ type = with types; nullOr path;
+ default = null;
+ description =
+ ''
+ Command to run when a virus is found. Please see VIRUS ACTION in
+ clamsmtpd(8) for a discussion of this option and its safe use.
+ '';
+ };
+
+ xClient = mkOption {
+ type = types.bool;
+ default = false;
+ description =
+ ''
+ Send the XCLIENT command to the receiving server, for forwarding
+ client addresses and connection information if the receiving
+ server supports this feature.
+ '';
+ };
+ };});
+ };
+ };
+ };
+
+ ##### implementation
+ config = let
+ configfile = conf: pkgs.writeText "clamsmtpd.conf"
+ ''
+ Action: ${conf.action}
+ ClamAddress: ${clamdSocket}
+ Header: ${conf.header}
+ KeepAlives: ${toString conf.keepAlives}
+ Listen: ${conf.listen}
+ Quarantine: ${if conf.quarantine then "on" else "off"}
+ MaxConnections: ${toString conf.maxConnections}
+ OutAddress: ${conf.outAddress}
+ TempDirectory: ${conf.tempDirectory}
+ TimeOut: ${toString conf.timeout}
+ TransparentProxy: ${if conf.transparentProxy then "on" else "off"}
+ User: clamav
+ ${optionalString (conf.virusAction != null) "VirusAction: ${conf.virusAction}"}
+ XClient: ${if conf.xClient then "on" else "off"}
+ '';
+ in
+ mkIf cfg.enable {
+ assertions = [
+ { assertion = config.services.clamav.daemon.enable;
+ message = "clamsmtp requires clamav to be enabled";
+ }
+ ];
+
+ systemd.services = listToAttrs (imap1 (i: conf:
+ nameValuePair "clamsmtp-${toString i}" {
+ description = "ClamSMTP instance ${toString i}";
+ wantedBy = [ "multi-user.target" ];
+ script = "exec ${pkgs.clamsmtp}/bin/clamsmtpd -f ${configfile conf}";
+ after = [ "clamav-daemon.service" ];
+ requires = [ "clamav-daemon.service" ];
+ serviceConfig.Type = "forking";
+ serviceConfig.PrivateTmp = "yes";
+ unitConfig.JoinsNamespaceOf = "clamav-daemon.service";
+ }
+ ) cfg.instances);
+ };
+
+ meta.maintainers = with lib.maintainers; [ ekleog ];
+}