# E-MailRelay Reference

## Command line usage

The emailrelay program supports the following command-line usage:

    emailrelay [<option> [<option> ...]] [<config-file>]

where <option> is:

--address-verifier <program>
  Runs the specified external program to verify a message recipent's e-mail address. A network verifier can be specified as net:<transport-address>.
--admin <admin-port> (-a)
  Enables an administration interface on the specified listening port number. Use telnet or something similar to connect. The administration interface can be used to trigger forwarding of spooled mail messages if the --forward-to option is used.
--admin-terminate (-Q)
  Enables the terminate command in the administration interface.
--anonymous (-A)
  Disables the server's SMTP VRFY command, sends less verbose SMTP responses and SMTP greeting, and stops Received lines being added to mail message content files.
--as-client <host:port> (-q)
  This is equivalent to --log, --no-syslog, --no-daemon, --dont-serve, --forward and --forward-to. It is a convenient way of running a forwarding agent that forwards spooled mail messages and then terminates.
--as-proxy <host:port> (-y)
  This is equivalent to --log, --close-stderr, --forward-on-disconnect and --forward-to. It is a convenient way of running a store-and-forward daemon. Use --log, --forward-on-disconnect and --forward-to instead of --as-proxy to keep the standard error stream open.
--as-server (-d)
  This is equivalent to --log and --close-stderr. It is a convenient way of running a background storage daemon that accepts mail messages and spools them. Use --log instead of --as-server to keep standard error stream open.
--client-auth <file> (-C)
  Enables SMTP client authentication with the remote server, using the client account details taken from the specified secrets file. The secrets file should normally contain one line that starts with client and that line should have between four and five space-separated fields; the second field is the password encoding (plain or md5), the third is the user-id and the fourth is the password. The user-id is RFC-1891 xtext encoded, and the password is either xtext encoded or generated by emailrelay-passwd. If the remote server does not support SMTP authentication then the SMTP connection will fail.
--client-filter <program> (-Y)
  Runs the specified external filter program whenever a mail message is forwarded. The filter is passed the name of the message file in the spool directory so that it can edit it as required. A network filter can be specified as net:<transport-address> and prefixes of spam: and exit: are also allowed. The --filter option is normally more useful than --client-filter.
--client-interface <ip-address> (-6)
  Specifies the IP network address to be used to bind the local end of outgoing SMTP connections. By default the address will depend on the routing tables in the normal way. Use 0.0.0.0 to use only IPv4 addresses returned from DNS lookups of the --forward-to address, or :: for IPv6.
--client-tls (-j)
  Enables negotiated TLS for outgoing SMTP connections; the SMTP STARTTLS command will be issued if the remote server supports it.
--client-tls-certificate <pem-file>
  Defines the TLS certificate file when acting as a SMTP client. This file must contain the client's private key and certificate chain using the PEM file format. Keep the file permissions tight to avoid accidental exposure of the private key.
--client-tls-connection (-b)
  Enables the use of a TLS tunnel for outgoing SMTP connections. This is for SMTP over TLS (SMTPS), not TLS negotiated within SMTP using STARTTLS.
--client-tls-required
  Makes the use of TLS mandatory for outgoing SMTP connections. The SMTP STARTTLS command will be used before mail messages are sent out. If the remote server does not allow STARTTLS then the SMTP connection will fail.
--client-tls-server-name <hostname>
  Defines the target server hostname in the TLS handshake. With --client-tls-connection this can be used for SNI, allowing the remote server to adopt an appropriate identity.
--client-tls-verify <ca-list>
  Enables verification of the remote SMTP server's certificate against any of the trusted CA certificates in the specified file or directory. In many use cases this should be a file containing just your self-signed root certificate.
--client-tls-verify-name <cname>
  Enables verification of the CNAME within the remote SMTP server's certificate.
--close-stderr (-e)
  Causes the standard error stream to be closed soon after start-up. This is useful when operating as a backgroud daemon and it is therefore implied by --as-server and --as-proxy.
--connection-timeout <time> (-U)
  Specifies a timeout (in seconds) for establishing a TCP connection to remote SMTP servers. The default is 40 seconds.
--debug (-g)
  Enables debug level logging, if built in. Debug messages are usually only useful when cross-referenced with the source code and they may expose plaintext passwords and mail message content.
--domain <fqdn> (-D)
  Specifies the network name that is used in SMTP EHLO commands, Received lines, and for generating authentication challenges. The default network name it derived from a DNS lookup of the local hostname.
--dont-serve (-x)
  Disables all network serving, including SMTP, POP and administration interfaces. The program will terminate as soon as any initial forwarding is complete.
--filter <program> (-z)
  Runs the specified external filter program whenever a mail message is stored. The filter is passed the name of the message file in the spool directory so that it can edit it as required. The mail message is rejected if the filter program terminates with an exit code between 1 and 99. Use net:<transport-address> to communicate with a filter daemon over the network, or spam:<transport-address> to talk to a spamassassin spamd daemon, or exit:<number> to emulate a filter program that just exits.
--filter-timeout <time> (-W)
  Specifies a timeout (in seconds) for running a --filter program. The default is 300 seconds.
--forward (-f)
  Causes spooled mail messages to be forwarded when the program first starts.
--forward-on-disconnect (-1)
  Causes spooled mail messages to be forwarded whenever a SMTP client connection disconnects.
--forward-to <host:port> (-o)
  Specifies the transport address of the remote SMTP server that is use for mail message forwarding.
--help (-h)
  Displays help text and then exits. Use with --verbose for more complete output.
--hidden (-H)
  Windows only. Hides the application window and disables all message boxes. This is useful when running as a windows service.
--immediate (-m)
  Causes mail messages to be forwarded as soon as they are submitted, even before they are accepted. This can be used to do proxying without store-and-forward, but in practice clients tend to to time out while waiting for their mail message to be accepted.
--interface <ip-address-list> (-I)
  Specifies the IP network addresses used to bind listening ports. By default listening ports for incoming SMTP, POP and administration connections will bind the 'any' address for IPv4 and for IPv6, ie. 0.0.0.0 and ::. Use this option to limit listening to particular addresses (and by implication to particular network interfaces). Multiple addresses can be specified by using the option more than once or by using a comma-separated list. Use a prefix of smtp=, pop= or admin= on addresses that should apply only to those types of listening port.
--log (-l)
  Enables logging to the standard error stream and to the syslog. The --close-stderr and --no-syslog options can be used to disable output to standard error stream and the syslog separately. Note that --as-server, --as-client and --as-proxy imply --log, and --as-server and --as-proxy also imply --close-stderr.
--log-file <file> (-N)
  Redirects standard-error logging to the specified file. Logging to the log file is not affected by --close-stderr. The filename can include %d to get daily log files; the %d is replaced by the current date in the local timezone using a YYYYMMDD format.
--log-time (-L)
  Adds a timestamp to the logging output using the local timezone.
--no-daemon (-t)
  Disables the normal backgrounding at startup so that the program runs in the foreground, without forking or detaching from the terminal. On Windows this disables the system tray icon so the program uses a normal window; when the window is closed the program terminates.
--no-smtp (-X)
  Disables listening for incoming SMTP connections.
--no-syslog (-n)
  Disables logging to the syslog. Note that --as-client implies --no-syslog.
--pid-file <pid-file> (-i)
  Causes the process-id to be written into the specified file when the program starts up, typically after it has become a backgroud daemon.
--poll <period> (-O)
  Causes forwarding of spooled mail messages to happen at regular intervals (with the time given in seconds).
--pop (-B)
  Enables the POP server listening, by default on port 110, providing access to spooled mail messages. Negotiated TLS using the POP3 STLS command will be enabled if the --server-tls option is also given.
--pop-auth <file> (-F)
  Specifies a file containing valid POP account details. The file format is the same as for the SMTP server secrets file, ie. lines starting with server, with user-id and password in the third and fourth fields. A special value of /pam can be used for authentication using linux PAM.
--pop-by-name (-J)
  Modifies the spool directory used by the POP server to be a sub-directory with the same name as the POP authentication user-id. This allows multiple POP clients to read the spooled messages without interfering with each other. Content files can stay in the main spool directory with the envelope files copied into user-specific sub-directories. The emailrelay-filter-copy program is a convenient way of doing this when run via --filter.
--pop-no-delete (-G)
  Disables the POP DELE command so that the command appears to succeed but mail messages are not deleted from the spool directory.
--pop-port <port> (-E)
  Sets the POP server's listening port number.
--port <port> (-p)
  Sets the port number used for listening for incoming SMTP connections.
--prompt-timeout <time> (-w)
  Specifies a timeout (in seconds) for getting the initial prompt from a remote SMTP server. If no prompt is received after this time then the SMTP dialog goes ahead without it.
--remote-clients (-r)
  Allows incoming connections from addresses that are not local. The default behaviour is to ignore connections that are not local in order to prevent accidental exposure to the public internet, but a firewall should also be used. The definition of 'local' is different for IPv4 and IPv6.
--response-timeout <time> (-T)
  Specifies a timeout (in seconds) for getting responses from remote SMTP servers. The default is 1800 seconds.
--server-auth <file> (-S)
  Enables SMTP server authentication of remote SMTP clients. Account names and passwords are taken from the specified secrets file. The secrets file should contain lines that have four space-separated fields, starting with server in the first field; the second field is the password encoding (plain or md5), the third is the client user-id and the fourth is the password. The user-id is RFC-1891 xtext encoded, and the password is either xtext encoded or generated by emailrelay-passwd. A special value of /pam can be used for authentication using linux PAM.
--server-tls (-K)
  Enables TLS for incoming SMTP and POP connections. SMTP clients can then request TLS encryption by issuing the STARTTLS command. The --server-tls-certificate option must be used to define the server certificate.
--server-tls-certificate <pem-file>
  Defines the TLS certificate file when acting as a SMTP or POP server. This file must contain the server's private key and certificate chain using the PEM file format. Keep the file permissions tight to avoid accidental exposure of the private key.
--server-tls-required
  Makes the use of TLS mandatory for any incoming SMTP and POP connections. SMTP clients must use the STARTTLS command to establish a TLS session before they can issue SMTP AUTH or SMTP MAIL-TO commands.
--server-tls-verify <ca-list>
  Enables verification of remote SMTP and POP clients' certificates against any of the trusted CA certificates in the specified file or directory. In many use cases this should be a file containing just your self-signed root certificate.
--size <bytes> (-M)
  Limits the size of mail messages that can be submitted over SMTP.
--spool-dir <dir> (-s)
  Specifies the directory used for holding mail messages that have been received but not yet forwarded.
--syslog (-k)
  When used with --log this option enables logging to the syslog even if the --no-syslog option is also used. This is typically used as a convenient override when using --as-client.
--tls-config <options> (-9)
  Selects and configures the low-level TLS library, using a comma-separated list of keywords. If OpenSSL and mbedTLS are both built in then keywords of openssl and mbedtls will select one or the other. Keywords like tlsv1.0 can be used to set a minimum TLS protocol version, or -tlsv1.2 to set a maximum version.
--user <username> (-u)
  When started as root the program switches to an non-privileged effective user-id when idle. This option can be used to define which user-id is used. Ignored on Windows.
--verbose (-v)
  Enables more verbose logging when used with --log, and more verbose help when used with --help.
--version (-V)
  Displays version information and then exits.

A configuration file can be used to provide additional options; put each options on a separate line, use the long option names but without the double dash, and separate the option name from the option value with spaces.

All command-line options that specify a filename can use a special @app substitution variable that is interpreted as the directory that contains the emailrelay executable or MacOS application bundle.

## Message store

Mail messages are stored as text files in the configured spool directory. Each e-mail message is represented as an envelope file and a content file. The envelope file contains parameters relevant to the SMTP dialogue, and the content file contains the RFC-822 headers and body text.

The filenames used in the message store have a prefix of emailrelay, followed by a process-id, timestamp and sequence number, and then envelope or content. The envelope files then have an additional suffix to implement a simple locking scheme.

The envelope file suffixes are:

- .new -- while the envelope is first being written
- .busy -- while the message is being forwarded
- .bad -- if the message cannot be forwarded
- .local -- for copies of the envelope file for delivery to local recipients

If an e-mail message cannot be forwarded the envelope file is given a .bad suffix, and the failure reason is written into the file.

## Forwarding

Spooled e-mail messages can be forwarded at various times, depending on the command-line options:

- when E-MailRelay first starts up (--as-client or --forward)
- as each message is submitted, just before receipt is acknowledged (--immediate)
- as soon as the submitting client connection disconnects (--forward-on-disconnect)
- periodically (--poll=<seconds>)
- on demand using the administration interface's flush command (--admin=<port>)
- when a --filter script exits with an exit code of 103

These can be mixed.

When using --as-client, or --dont-serve and --forward, the spooled messages begin to be forwarded as soon as the program starts up, and the program terminates once they have all been sent.

All recipient e-mail addresses must be accepted by the remote server when E-MailRelay forwards an e-mail message. If any one recipient is rejected then the message will be left in the spool directory with a .bad suffix on the envelope file.

## Mail processing

The --filter command-line option allows you to specify a mail processing program which operates on e-mail messages as they pass through the E-MailRelay system. The filter program is run as soon as the e-mail message has been stored in the spool directory, with the full path of the content file added onto the end of the given command-line.

For example, the following command will start a proxy server on port 587 which processes mail using the specified filter program, and then forwards the mail on to the system's default MTA (on port 25):

    emailrelay --as-proxy=localhost:smtp --port=587 --no-syslog \
      --filter=$HOME/myfilter --spool-dir=$HOME/spool

The filter program should terminate with an exit code of zero to indicate success, or a value between 1 and 99 to indicate failure. Exit codes between 100 and 115 are reserved for special processing: 100 is used to abandon the current e-mail message (so the filter can delete the files), and 103 has the effect of requesting a rescan of the spool directory if forwarding is enabled (typically to pick up on new messages that the filter program has created).

If the filter program terminates with a non-zero exit code then the first few thousand characters of the standard output stream are searched for a line starting with <<error text>> or [[error text]]. The text inside is taken as a failure reason, and passed back to the SMTP client. A second error-text line can be used for additional diagnostics that will not be visible to the remote client.

The filter program can edit any part of the e-mail message's envelope file or content file: E-MailRelay remembers nothing about the e-mail message while the filter is running except the filename. However, if the message is deleted by the filter program then E-MailRelay will complain, so to avoid the error message use an exit code of 100.

If the filter program creates completely new e-mail messages in the spool directory then they may not be processed immediately, or they may be completely ignored. To get E-MailRelay to pick up any new messages you create in the spool directory use the special 103 exit code, or rely on the --poll mechanism, or perhaps run emailrelay --as-client from within the filter program.

As an example of a simple filter program processor this shell script examines the sending client's IP address and conditionally passes the message into sendmail (using the sendmail command-line interface rather than SMTP):

    #!/bin/sh
    # filter.sh
    content="${1}"
    envelope="`echo \"${content}\" | sed 's/content/envelope.new/'`"
    ip="`awk '/MailRelay-Client:/ {print $2;exit}' \"${envelope}\"`"
    if test "${ip}" = "192.168.0.2"
    then
        /usr/sbin/sendmail -t < "${content}"
        rm -f "${envelope}" "${content}"
        exit 100 # <= cancel further processing by emailrelay
    fi
    exit 0

The first thing this script does is convert the path of the content file which it is given, into the corresponding envelope file. It then extracts the client's IP address out of the envelope file using awk. If this matches the fixed address then it pipes the message content into sendmail, deletes the e-mail message and exits with a value of 100. The exit value of 100 tells E-MailRelay to forget the message, and not to complain about the files disappearing.

For Windows this example can be rewritten in JavaScript:

    // filter.js
    var content = WScript.Arguments(0) ;
    var envelope = content.substr(0,content.length-7) + "envelope.new" ;
    var fs = WScript.CreateObject( "Scripting.FileSystemObject" ) ;
    var ts = fs.OpenTextFile( envelope , 1 , false ) ;
    var e = ts.ReadAll() ;
    ts.Close() ;
    var re = new RegExp( "MailRelay-Client: \(.*\)" ) ;
    var ip = e.match(re)[1] ;
    if( ip === "192.168.0.2" )
    {
        var sh = WScript.CreateObject( "Wscript.Shell" ) ;
        sh.Run( "sendmail " + content ) ; // bogus
        fs.DeleteFile( content ) ;
        fs.DeleteFile( envelope ) ;
        WScript.Quit( 100 )
    }
    WScript.Quit( 0 ) ;

Windows filter programs written in JavaScript can be run with an E-MailRelay --filter option something like this:

    --filter="C:/Program Files/E-MailRelay/filter.js"

Note that double-quotes are needed because the file path contains a space. Either forward-slashes or back-slashes can be used.

E-MailRelay also has a --client-filter option that enables processing of e-mail messages just before they are forwarded, rather than after they are stored. The disadvantage is that by then it is too late to notify the submitting SMTP client of any processing failures, so in many store-and-forward applications using --filter is more useful. The special exit code of 100 can be used to ignore the current message, and 102 to stop scanning for more spooled messages after processing the current one (eg. for simple rate-limiting).

Bear in mind the following points when writing --filter programs:

- The standard input and output are not used; the content filename is passed on the command-line.
- Programs are run with a reduced set of environment variables.
- E-MailRelay files use CR-LF line terminators, as required by the RFCs.
- Envelope files will have a file extension of .new or .busy when the program runs.
- Windows scripts may need to be run via cscript or a batch file wrapper.

It is also possible to do message filtering in a separate process by using net:<transport-address> as the --filter or --client-filter option parameter. E-MailRelay connects to this address and then uses a simple line-based dialog as each e-mail message is processed where it sends the full path of the message content file in one line and expects the remote process to respond with an ok line if the message is to be accepted or an error message.

Alternatively, use spam:<transport-address> for connecting to a SpamAssassim spamd server, or use exit:<exit-code> for simulating a filter program that just does an exit with the specified exit code.

## Authentication

E-MailRelay can perform client-side authentication when connecting to remote SMTP servers, and server-side authentication when remote clients connect to the E-MailRelay server.

SMTP authentication is enabled with the --client-auth and --server-auth command-line options, followed by the name of a 'secrets' file containing usernames and passwords:

    emailrelay --as-server --server-auth=/etc/emailrelay-client.auth
    emailrelay --as-client=example.com:smtp --client-auth=/etc/emailrelay-server.auth

The client-side secrets file specified with --client-auth is used when E-MailRelay acts as a client to talk to a remote server. The file should contain at least one client entry.

The server-side secrets file specified with --server-auth is used when a remote client tries to authenticate with the E-MailRelay server. The file should normally contain several server entries, one for each remote client.

The same secrets file may be specified for both --client-auth and --server-auth options.

The secrets file has a line-based format: blank lines are ignored and the hash character (#) is used for comments.

Lines have four white-space delimited fields:

- client-or-server
- password-type
- userid
- password

The client-or-server field must be client or server; the password-type field must be plain or md5; the userid field is xtext-encoded user identifier; and the password field is the xtext-encoded plain password or a base64-encoded HMAC-MD5 state. For client lines the password-type can also be oauth.

The first two fields are case-insensitive. The xtext encoding scheme is defined properly in RFC-1891, but basically it says that non-alphanumeric characters (including space, +, # and =) should be represented in uppercase hexadecimal ascii as +XX. So a space should be written as +20; + as +2B; # as +23; and = as +3D.

Authentication proceeds according to an authentication 'mechanism' that is advertised by the server and selected by the client. Many authentication mechanisms have been defined and standardised, and the simplest ones just exchange a username and plaintext password. E-MailRelay supports the PLAIN, LOGIN and CRAM-MD5 mechanisms for both client-side and server-side authentication as a minimum, but other mechanisms might be built in or available via PAM (see below).

The PLAIN, LOGIN and CRAM-MD5 mechanisms can use plaintext passwords, stored in the secrets file using a password-type of plain. In addition, the CRAM-MD5 mechanism can also use hashed passwords generated by the emailrelay-passwd program and these are stored in the secrets file with a password-type of md5. (Hashed passwords are marginally more secure because the plaintext password which might be used on other accounts, is not easily recovered. However, hashed passwords can only be used for HMAC authentication mechanisms that are based on the same hash function.) The XOAUTH2 mechanism can be used for client-side authentication using tokens that have been recently obtained from a third-party authentication server and added to the secrets file with a password-type of oauth.

In the following example bob is the username that E-MailRelay uses when it authenticates with a remote SMTP server, and two usernames (alice and carol) can be used by remote clients when they authenticate with the E-MailRelay server:

    #
    # emailrelay secrets file
    #
    client plain bob password123
    server plain alice e+3Dmc2
    server plain carol my+20password

Using MD5 hashes the same users would look like this:

    #
    # emailrelay secrets file
    #
    client md5 bob 9N2IRYVXqu7SkOW1Xat+wpR9NbA2R6fb61XlmqW+46E=
    server md5 alice v1HOpuLIbbvgoJjhueeoqwfvtIp2C+gMA285ke+xxow=
    server md5 carol x6UJKQF9f7HfhS1M+PW4s8rXIoT+L+WoqLz+rBwSKbw=

When the --server-auth option is used clients must authenticate with the E-MailRelay server but it is possible to configure some client IP addresses as 'trusted' so that connections from these addresses do not have to authenticate.

Trusted IP addresses are configured with lines in the secrets file having server in the first field, none in the second field, a wildcarded IP address in the third field, and an arbitrary keyword in the fourth field. The keyword field is passed to any external address verifier program specified by the --address-verifier command-line option; it is not used for any other purpose. Wildcarded IPv4 addresses can use a format like 192.168.0.0/24 or 192.168.0.*.

For example, this secrets file allows any client connecting over IPv4 from the 192.168.0.0/24 address range, or over IPv6 from the fe80::/64 or fc00::/7 ranges, to connect without authentication:

    #
    # emailrelay secrets file
    #
    server none 192.168.0.* localipv4
    server none fe80::/64 localipv6
    server plain alice e+3Dmc2
    server plain carol my+20password

On the client side, authentication is performed when E-MailRelay connects to a server which implements the SMTP AUTH extension with one of the supported mechanisms. If the remote server does not support the AUTH extension, or does not support mechanisms for which E-MailRelay has secrets, then an error will be logged and no messages will be forward.

When E-MailRelay successfully authenticates with the remote server the session authentication name is passed as the AUTH parameter of the SMTP MAIL FROM command, ignoring any AUTH name from the original submission. This default policy can be modified by editing the MailFromAuthOut field in the message envelope file, perhaps by using a --filter or --client-filter program. The value in this envelope field should be empty for the default policy, <> for no AUTH name, or an xtext-encoded authentication name.

The TLS layer can also be used for authentication, independently of SMTP, as described below.

## TLS encryption

E-MailRelay can use negotiated TLS to encrypt SMTP and POP sessions: to enable client-side TLS encryption when E-MailRelay is acting as an SMTP client use the --client-tls command-line option, and to enable server-side TLS when E-MailRelay is acting as an SMTP or POP server use --server-tls. The connections start off as unencrypted and the SMTP command STARTTLS (or the POP STLS command) can be used to negotiate TLS encryption before any passwords are exchanged.

The --server-tls option requires that the --server-tls-certificate option is used to specify a PEM-format file containing a X.509 certificate and private key.

This OpenSSL command can be used to create a self-signed certificate file suitable for testing:

    $ openssl req -x509 -nodes -subj "/CN=$USER" -newkey rsa:2048 -keyout emailrelay.pem  -out emailrelay.pem

TLS performs encryption to prevent eavesdropping, but it does not necessarily do authentication to prevent man-in-the-middle attacks. For full TLS authentication you must use private keys and X.509 certificates symmetrically on both ends, with TLS verification enabled in both directions. Refer to the documentation of all the --server-tls... and --client-tls... command-line options for more details.

E-MailRelay can also make outgoing SMTP connections using TLS encryption where the whole SMTP dialog is encrypted from the start (--client-tls-connection). This is sometimes called SMTP-over-TLS or secure SMTP (smtps) and it is normally used with port number 465.

## PAM Authentication

E-MailRelay on Linux supports the use of PAM (Pluggable Authentication Modules) for authentication if it has been built with the --with-pam configure option.

PAM authentication can be used to authenticate SMTP and POP connections coming in from remote clients; it cannot be used by E-MailRelay to supply passwords when acting as an SMTP client.

Use --server-auth=/pam and/or --pop-auth=/pam on the command-line to use PAM authentication for SMTP and POP respectively. The E-MailRelay server will then advertise an SMTP authentication mechanism of PLAIN and do the actual authentication via PAM.

The PAM system itself must be configured with a service of emailrelay. This normally involves creating a file /etc/pam.d/emailrelay containing something like the following:

    auth requisite pam_unix.so nullok_secure
    session required pam_permit.so
    account required pam_permit.so
    password required pam_deny.so

With this configuration the E-MailRelay server will use normal unix system account names and passwords to authenticate remote clients. On some systems this will require special permissioning to allow the E-MailRelay server to read the shadow password database.

When using PAM authentication E-MailRelay requires that remote clients establish an encrypted session using TLS before authentication can proceed.

## IP addresses

By default the E-MailRelay server listens for connections on the wildcard IPv4 and IPv6 addresses, and when making outgoing connections it does not explicitly bind any address to the the local socket.

If a single network address is specified with the --interface command-line option then that address is used for listening.

Eg:

    --interface 127.0.0.1

If the --client-interface option is used then that address is used to bind the local end of outgoing SMTP client connections.

Eg:

    --client-interface 192.168.0.1

More than one address can be given in the --interface option separated by commas, or multiple --interface options can be used. All of those addresses will be used for listening.

Eg:

    --interface 192.168.0.1,127.0.0.1,fc00::1,::1
    --interface 192.168.0.1 --interface 127.0.0.1 --interface fc00::1 --interface ::1

A listening address can also be qualified by one of the prefixes smtp=, pop= or admin= so that it is only used in that context.

Eg:

    --interface smtp=192.168.0.1 --interface pop=127.0.0.1 --interface admin=127.0.0.1

The IPv4 and IPv6 wildcard addresses (0.0.0.0 and ::) can be used with --interface and --client-interface to enable the use of IPv4 only or IPv6 only.

To use IPv4 only for incoming connections use --interface 0.0.0.0; for IPv6 only on incoming connections use --interface ::.

    --interface 0.0.0.0 # IPv4 only
    --interface ::      # IPv6 only

To use IPv4 only on outgoing SMTP connection use --client-interface 0.0.0.0; for IPv6 only on outgoing SMTP connections use --client-interface ::.

    --client-interface 0.0.0.0 # IPv4 only
    --client-interface ::      # IPv6 only

Hostnames given in the --forward-to, --as-proxy and --as-client options are resolved to IPv4 addresses and/or IPv6 addresses using DNS. If both IPv4 and IPv6 records are returned from the DNS query then the --client-interface option can be used to select either the IPv4 or IPv6 results. Otherwise the first address is used, whether that is IPv4 or IPv6.

Eg:

    --as-client ipv4or6.example.com:25 --client-interface 0.0.0.0
    --as-client ipv4or6.example.com:25 --client-interface ::

## SOCKS

E-MailRelay can use a SOCKS 4a proxy for establishing outgoing SMTP connections; just append the SOCKS proxy address to the SMTP server's address, separated by @.

For example, this could be used to send e-mails via the Tor network, assuming there is a local Tor node running on port 9050:

    emailrelay --forward-to example.com:smtp@localhost:9050 ...

The Tor system will then be used to resolve the example.com domain name and establish the connection. The target SMTP server will see a connection coming from the Tor exit node rather than from the E-MailRelay server.

## Address verification

By default the E-MailRelay server will accept all recipient addresses for incoming e-mails as valid. This default behaviour can be modified by using an external verifier program, specified with the --address-verifier command-line option, so that you get to choose which recipient addresses are accepted as valid and which are rejected.

Your verifier program is passed a command-line containing: (1) the recipient e-mail address as supplied by the remote client, (2) the from e-mail address as supplied by the client, or the empty string in the case of the VRFY command, (3) the IP address and port of the far end of the client connection, (4) the local fully qualified domain name, (5) the authentication mechanism used by the client (if any, and none if trusted), and (6) either the authentication name or the fourth field from authentication secrets file if a trusted IP address.

So, for example, a verifier program called myverifier might be run with the following command-line:

    myverifier bob@local.net alice@example.com 192.168.0.1:123 local.net login alice

The verifier program is expected to generate two lines of output on the standard output stream and then terminate with a specific exit code.

For future-proofing a verifier must report a version number of 2.0 if called with a command-line starting with --emailrelay-version.

For valid addresses the first line of output is ignored, the second line should be copied from the first command-line argument, and the exit value should be one.

    #!/bin/sh
    # address verifier -- accept all (252)
    echo ""
    echo $1
    exit 1

If the address is valid but it should be delivered to a local mailbox rather than forwarded then the verifier program should write two lines to the standard output -- the full name associated with the mailbox, and the canonical mailbox name -- and then exit with a value of zero.

    #!/bin/sh
    # address verifier -- accept as local (250)
    echo Local Postmaster '<postmaster@localhost>'
    echo postmaster
    exit 0

For E-MailRelay local delivery just means that the message file in the spool directory is given a .local filename suffix. This can be used to create a separate channel for administrative messages such as delivery reports.

For invalid addresses the exit value should be non-zero and the first line of output is the error response.

    #!/bin/sh
    # address verifier -- reject as invalid (550)
    echo invalid mailbox: $1
    exit 2

To indicate a temporary failure this can be changed to an exit code of 3.

    #!/bin/sh
    # address verifier -- reject as temporarily invalid (450)
    echo mailbox unavailable: $1
    exit 3

If the verifier exit code is 100 then the connection is aborted immediately, which may be useful in limiting the impact of denial of service attacks:

    #!/bin/sh
    # address verifier -- abort
    exit 100

In this more complete example the verifier script accepts all addresses as valid as long as they contain an at character:

    #!/bin/sh
    # address verifier -- accept only if containing an at sign
    address="$1"
    expr "$address" : ".*@" > /dev/null || exit 2
    echo ""
    echo "$address"
    exit 1 # accept

As another example, this verifier script accepts all recipient addresses by default but rejects remote addresses if the client has bypassed authentication by connecting on a trusted IP address:

    #!/bin/sh
    # address verifier
    if test "$1" = "--emailrelay-version" ; then echo 2.0 ; exit 0 ; fi
    address="$1"
    local_domain="$4"
    auth_mechanism="$5"
    host="`echo \"$address\" | sed 's/.*@//'`"
    if test "$auth_mechanism" = "none" -a "$host" != "$local_domain"
    then
        echo "cannot relay without authentication"
        exit 2 # reject the recipient address
    fi
    echo ""
    echo "$address"
    exit 1 # accept the recipient address

or written in JavaScript for Windows:

    // verifier.js
    if( WScript.Arguments(0) === "--emailrelay-version" )
    {
        WScript.Stdout.WriteLine( "2.0" ) ;
        WScript.Quit( 0 ) ;
    }
    try
    {
        var address = WScript.Arguments(0) ;
        var local_domain = WScript.Arguments(3) ;
        var auth_mechanism = WScript.Arguments(4) ;
        var host = address.split(/@/)[1] || "" ;
        if( ( auth_mechanism === "none" || !auth_mechanism ) && host !== local_domain )
        {
            WScript.Stdout.WriteLine( "cannot relay without authentication" ) ;
            WScript.Quit( 2 ) ;
        }
        WScript.Stdout.WriteLine( "" ) ;
        WScript.Stdout.WriteLine( address ) ;
        WScript.Quit( 1 ) ;
    }
    catch( e )
    {
        WScript.Stdout.WriteLine( "mailbox unavailable" ) ;
        WScript.Stdout.WriteLine( e ) ;
        WScript.Quit( 3 ) ;
    }

If this verifier script is used with a suitable --server-auth file then it can be used to prevent open relay without restricting authenticated clients.

It is also possible to verify addresses in a separate daemon process by using a --address-verifier option of the form net:<transport-address>. In this case E-MailRelay will connect to the specified verifier daemon over the network and send address verification requests as lines with pipe-delimited fields. The expected response is another pipe-delimited line containing the same information as returned by verifier scripts but in reverse, such as 3|address unavailable or 0|postmaster|Local Postmaster <postmaster@localhost>.

## Security issues

The following are some security issues that have been taken into consideration:

Effective userid
  Suid privileges are revoked at start-up, switching the effective userid/groupid to be the real userid/groupid values. If started as root then the effective userid/groupid are switched at start-up to those of user daemon. Special privileges are only reclaimed when needed to bind sockets and do file i/o. Normally this means temporarily switching the userid and groupid back to what they were at start-up. However, when writing spool files after being started as root only the effective userid is changed, not the groupid, so that new files have group ownership corresponding to the daemon user.
Execution environment
  The external filter programs are run with an almost empty set of environment variables (PATH and IFS), and with no open file descriptors other than stdin and stderr open onto /dev/null, and stdout open onto a pipe.
Umask
  The program runs for most of the time with a umask of 177, switching to 117 when creating spool files.
Remote clients
  By default connections will be rejected if they come from remote machines.
Remote configuration
  No configuration parameters can be changed through the administrative interface.
Use of exec() and system()
  No exec(), system() or popen() calls are used other than execve() to spawn the mail filter and/or address verifier.
File permissions
  After a normal installation the spool directory is has ownership of root.daemon with permissions of -rwxrwxr-x and messages files are created with permissions of -rw-rw----. This allows normal users to list messages files but not read them.

  The emailrelay-submit program is given group ownership of daemon with its group set-user-id flag set. This allows it to create message files in the spool directory, and the files created end up owned by the submitter but with group ownership of daemon.
Logging
  Logging output is conditioned so that ANSI escape sequences cannot appear in the log.

  Passwords and message content are not logged (except if using the --debug option at run time with debug logging enabled at build time).
Information leakage
  The --anonymous option can be used to reduce the amount of information leaked to remote clients.
Mandatory encryption
  When using PAM for authentication all clients are required to use TLS/SSL encryption.

Security issues which relate to the SMTP protocol itself are beyond the scope of this document, but RFC-2821 makes the following observation: "SMTP mail is inherently insecure in that it is feasible for even [..] casual users to [..] create messages that will trick a [..] recipient into believing that they came from somewhere else. [..] Real [..] security lies [..] in end-to-end methods [..] such as those which use digital signatures."

The Authentication, PAM Authentication and TLS encryption sections above also relate to security.

## Administration interface

If enabled with the --admin command-line option, the E-MailRelay server will provide a network interface for performing administration tasks. This is a simple command-line interface which is compatible with netcat and telnet:

    $ emailrelay --as-server --port=125 --forward-to=localhost:25 --admin=10026
    $ telnet localhost 10026
    E-MailRelay> help
    E-MailRelay> quit

The flush command is used to get the E-MailRelay server to forward spooled mail to the next SMTP server.

The list command lists the messages in the spool directory, status provides network status information and activity statistics, and notify enables asynchronous event notification.

## Bcc handling

E-MailRelay transfers e-mail messages without changing their content in any way, other than by adding a Received header. In particular, if a message contains a Bcc: header when it is submitted to the E-MailRelay server it will have the same Bcc: header when forwarded.

It is normally the responsibility of the program that submits an e-mail message to submit it separately for each Bcc recipient, removing the Bcc: header from the message content or changing it to contain only the 'current' recipient. If this is not done, perhaps through mis-configuration of the e-mail user agent program, then Bcc recipients may be visible to the To and Cc message recipients.

An E-MailRelay --filter script can be used to reject messages with incorrect Bcc: headers, and an example script is included.

## Files and directories

On Unix-like systems E-MailRelay installs by default under /usr/local, but binary distributions will probably have been built to install elsewhere.

Installation directories can be defined at build-time by the following configure script command-line options:

- --mandir=<dir>
- --sbindir=<dir>
- e_bsdinitdir=<dir>
- e_docdir=<dir>
- e_examplesdir=<dir>
- e_icondir=<dir>
- e_initdir=<dir>
- e_libexecdir=<dir>
- e_pamdir=<dir>
- e_spooldir=<dir>
- e_sysconfdir=<dir>

These are all defaulted to paths that are ultimately based on --prefix, so ./configure --prefix=$HOME will work as expected.

For a directory structure conforming more closely to the FHS use this configure command:

    ./configure --prefix=/usr --localstatedir=/var --libexecdir=/usr/lib --sysconfdir=/etc e_initdir=/etc/init.d

It is possible to change the installation root directory after building by using make DESTDIR=<root> install or DESTDIR=<root> make -e install. However, this will not affect the default spool directory path built into the scripts and executables so the correct spool directory will have to be specified at run-time with the --spool-dir command-line option.

On Windows the installation GUI prompts for two installation directories, and these default to %ProgramFiles%/E-MailRelay for programs and %ProgramData%/E-MailRelay for data.