Root configuration

By default, the following files are created in the /etc/vsmtp directory once vSMTP is installed.

/etc/vsmtp
┣ vsmtp.vsl
┣ conf.d/
┃      β”— config.vsl
┣ domain-available/
┣ domain-enabled/
┣ objects/
┣ services/
β”— plugins/

Default file structure in `/etc/vsmtp`

vsmtp.vsl is the mandatory entrypoint for vSMTP. It’s content SHOULD NOT be modified, since it can change between versions.

conf.d/config.vsl, on the other hand, is a mandatory configuration file that contains the root configuration for vSMTP.

This file must at least contain the following statement:

fn on_config(config) {
  return config;
}

An empty root configuration file in `/etc/vsmtp/conf.d/config.vsl`

vSMTP calls the on_config function once starting up. Modify the config object to change the configuration. The config object MUST be returned at the end of the function.

The Configuration reference lists all fields that can be changed in the config object.

For example:

fn on_config(config) {
  // Change the name of the server.
  config.server.name = "example.com";

  // Specify addresses that the server will listen to.
  config.server.interfaces = #{
    addr: ["192.168.1.254:25"],
    addr_submission: ["192.168.1.254:587"],
    addr_submissions: ["192.168.1.254:465"],
  };

  // Specify a user and group that will run vsmtp.
  // If those fields are not set, vsmtp will try to use,
  // by default, the `vsmtp` user and `vsmtp` group.
  config.server.system = #{
    user: "debian-1",
    group: "mail",
  };

  // Change filter rules locations.
  config.app.vsl.filter_path = "/etc/vsmtp/filter.vsl";
  config.app.vsl.domain_dir = "/etc/vsmtp/domain-enabled";

  return config;
}

Configuring vSMTP by changing the `config` object

It is recommended that you use absolute paths in your configuration files. Relative paths will be relative to the execution path of vSMTP.

Splitting configuration in modules

Rhai exposes a module API, making it possible to split the configuration by theme.

For example, it is possible to split the above configuration this way:

/etc/vsmtp
 ┣ vsmtp.vsl
 ┣ conf.d/
 ┃    ┣ config.vsl
+┃    ┣ interfaces.vsl
+┃    β”— app.vsl
 ┣ domain-available/
 ┣ domain-enabled/
 ┣ objects/
 ┣ services/
 β”— plugins/

Adding modules to split the configuration

Let’s define the addresses that the server will listen to.

export const interfaces = #{
  addr: ["192.168.1.254:25"],
  addr_submission: ["192.168.1.254:587"],
  addr_submissions: ["192.168.1.254:465"],
};

`/etc/vsmtp/conf.d/interfaces.vsl`

Let’s also write our filtering scripts locations.

// Filter by domain.
export const domain_dir = "/etc/vsmtp/domain-enabled";
// Global filter.
export const filter_path = "/etc/vsmtp/filter.vsl";

`/etc/vsmtp/conf.d/app.vsl`

Those modules can then be imported in config.vsl, resulting in a more cleaner configuration file.

import "conf.d/interfaces" as i;
import "conf.d/app" as app;

fn on_config(config) {
  config.server.name = "example.com";
  config.server.interfaces = i::interfaces;

  config.server.system = #{
    user: "debian-1",
    group: "mail",
  };

  config.app.vsl.domain_dir = app::domain_dir;
  config.app.vsl.filter_path = app::filter_path;

  return config;
}

`/etc/vsmtp/conf.d/config.vsl`