*********************
E-MailRelay Reference
*********************

Command line usage
==================
The *emailrelay* program supports the following command-line usage:

::

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

*   --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.

*   --spool-dir \<dir\> (-s)

    Specifies the directory used for holding mail messages that have been
    received but not yet forwarded.

*   --help (-h)

    Displays help text and then exits. Use with *--verbose* for more complete
    output.

*   --version (-V)

    Displays version information and then exits.


*   --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 spooled mail
    messages are forwarded to.

*   --poll \<period\> (-O)

    Causes forwarding of spooled mail messages to happen at regular intervals
    (with the time given in seconds).

*   --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:<tcp-address>* and prefixes of *spam:*, *spam-edit:* and
    *exit:* are also allowed. The *spam:* and *spam-edit:* prefixes require a
    SpamAssassin daemon to be running. For store-and-forward applications 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.

*   --connection-timeout \<time\> (-U)

    Specifies a timeout (in seconds) for establishing a TCP connection to remote
    SMTP servers. The default is 40 seconds.

*   --idle-timeout \<time\>

    Specifies a timeout (in seconds) for receiving network traffic from remote
    SMTP and POP_ clients. The default is 60 seconds.

*   --response-timeout \<time\> (-T)

    Specifies a timeout (in seconds) for getting responses from remote SMTP
    servers. The default is 60 seconds.

*   --forward-to-some

    Allow forwarding to continue even if some recipient addresses on an e-mail
    envelope are rejected by the remote server.

*   --immediate (-m)

    Causes mail messages to be forwarded as they are received, even before they
    have been 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.


*   --port \<port\> (-p)

    Sets the port number used for listening for incoming SMTP connections.

*   --remote-clients (-r)

    Allows incoming connections from addresses that are not local. The default
    behaviour is to reject connections that are not local in order to prevent
    accidental exposure to the public internet, although a firewall should also
    be used. Local address ranges are defined in RFC-1918_, RFC-6890 etc.

*   --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:<tcp-address>*.

*   --anonymous[=\<scope\>] (-A)

    Disables the server's SMTP VRFY command, sends less verbose SMTP greeting and
    responses, stops *Received* lines being added to mail message content
    files, and stops the SMTP client protocol adding *AUTH=* to the *MAIL*
    command. For finer control use a comma-separated list of things to
    anonymise: *vrfy*, *server*, *content* and/or *client*, eg.
    \ *--anonymous*\ =server,content.

*   --dnsbl \<config\>

    Specifies a list of DNSBL_ servers that are used to reject SMTP connections
    from blocked addresses. The configuration string is made up of
    comma-separated fields: the DNS server's transport address, a timeout in
    milliseconds, a rejection threshold, and then the list of DNSBL servers.

*   --domain \<fqdn\> (-D)

    Specifies the network name that is used in SMTP EHLO commands, *Received*
    lines, and for generating authentication challenges. The default is derived
    from a DNS lookup of the local hostname.

*   --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:<tcp-address>* to communicate with a filter daemon over the network,
    or *spam:<tcp-address>* for a spamassassin spamd daemon to accept or reject
    mail messages, or *spam-edit:<tcp-address>* to have spamassassin edit the
    message content without rejecting it, 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 60 seconds.

*   --interface \<ip-address-list\> (-I)

    Specifies the IP network addresses or interface names 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 *::*. 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. Any link-local IPv6 addresses must include a zone name or
    scope id.  Interface names can be used instead of addresses, in which case
    all the addresses associated with that interface at startup will used for
    listening. When an interface name is decorated with a *-ipv4* or *-ipv6*
    suffix only their IPv4 or IPv6 addresses will be used (eg. *ppp0-ipv4*).
    To inherit listening file descriptors from the parent process on unix use a
    syntax like this: *--interface*=smtp=fd#3,smtp=fd#4,pop=fd#5.

*   --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.

*   --size \<bytes\> (-M)

    Limits the size of mail messages that can be submitted over SMTP.


*   --pop (-B)

    Enables the POP server, listening by default on port 110, providing access to
    spooled mail messages. Negotiated TLS_ using the POP *STLS* command will be
    enabled if the *--server-tls* option is also given.

*   --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 mail messages without interfering with each
    other, particularly when also using *--pop-no-delete*. Content files can
    stay in the main spool directory with only 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.


*   --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.


*   --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-auth-config \<config\>

    Configures the SMTP client authentication module using a semicolon-separated
    list of configuration items. Each item is a single-character key, followed
    by a colon and then a comma-separated list. A 'm' character introduces an
    ordered list of preferred authentication mechanisms and an 'x' introduces a
    list of mechanisms to avoid. An 'a' list and a 'd' list can be used
    similarly to prefer and avoid certain mechanisms once the session is
    encrypted with TLS.

*   --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-auth-config \<config\>

    Configures the SMTP server authentication module using a semicolon-separated
    list of configuration items. Each item is a single-character key, followed
    by a colon and then a comma-separated list. A 'm' character introduces an
    ordered list of allowed authentication mechanisms and an 'x' introduces a
    list of mechanisms to deny. An 'a' list and a 'd' list can be used
    similarly to allow and deny mechanisms once the session is encrypted with
    TLS. In typical usage you might have an empty allow list for an unencrypted
    session and a single preferred mechanism once encrypted, *m:;a:plain*.

*   --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.


*   --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. Alternatively, use this option twice with the first one specifying
    the key file and the second the certificate file. 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. Specify *<default>* for the TLS library's default set of
    trusted CAs.

*   --client-tls-verify-name \<cname\>

    Enables verification of the CNAME within the remote SMTP server's
    certificate.

*   --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. Alternatively, use this option twice with the first one
    specifying the key file and the second the certificate file. Keep the file
    permissions tight to avoid accidental exposure of the private key.

*   --server-tls-connection

    Enables SMTP over TLS when acting as an SMTP server. This is for SMTP over
    TLS (SMTPS), not TLS negotiated within SMTP using STARTTLS.

*   --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. Specify *<default>* for the TLS library's default set of
    trusted CAs.

*   --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.


*   --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.

*   --hidden (-H)

    Windows only. Hides the application window and disables all message boxes,
    overriding any *--show* option. This is useful when running as a windows
    service.

*   --localedir \<dir\>

    Enables localisation and specifies the locale base directory where message
    catalogues can be found. An empty directory can be used for the built-in
    default.

*   --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.

*   --pid-file \<path\> (-i)

    Causes the process-id to be written into the specified file when the program
    starts up, typically after it has become a background daemon. The immediate
    parent directory is created if necessary.

*   --user \<username\> (-u)

    When started as root the program switches to a non-privileged effective
    user-id when idle. This option can be used to define the idle user-id and
    also the group ownership of new files and sockets. Specify *root* to
    disable all user-id switching. Ignored on Windows.


*   --verbose (-v)

    Enables more verbose logging when used with *--log*, and more verbose help
    when used with *--help*.

*   --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*.

*   --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.

*   --log-address

    Adds the network address of remote clients to the logging output.

*   --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-syslog (-n)

    Disables logging to the syslog. Note that *--as-client* implies
    \ *--no-syslog*\ .

*   --syslog[=\<facility\>] (-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*.

*   --close-stderr (-e)

    Causes the standard error stream to be closed soon after start-up. This is
    useful when operating as a background daemon and it is therefore implied by
    *--as-server* and *--as-proxy*.

A configuration file can be used to provide additional options; put each
option 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 *forward* 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.

By default 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. This behaviour can be changed by using *--forward-to-some*
command-line option so that forwarding will succeed for the valid recipients
and the failed message will contain the invalid ones.

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 and envelope
file put on the 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="${2}"
    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 = WScript.Arguments(1) ;
    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 message 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:<tcp-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: 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. If the error message
contains a tab character then anything after the tab character is logged but
otherwise ignored.

Alternatively, use *spam:<tcp-address>* or *spam-edit:<tcp-address>* to connect
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.

.. image:: authentication.png
   :alt: authentication.png


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 should 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 *xtext* encoding scheme is defined properly in RFC-3461_, 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*.

Base64 encoding can be used instead of xtext encoding for the user identifier
and plain password by replacing *plain* by *plain:b*.

Note that modern email services will expect userids and passwords containing
non-ASCII characters to use UTF-8 encoding with RFC-4013_ normalisation applied.

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 make use of 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 that implements the SMTP AUTH extension with one of the supported
mechanisms. If client-side authentication is required but 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
forwarded.

When E-MailRelay successfully authenticates with the remote server the
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: use the
*--client-tls* command-line option to enable client-side TLS encryption when
E-MailRelay is acting as an SMTP client, and use *--server-tls* to enable
server-side TLS when E-MailRelay is acting as an SMTP or POP server. 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 -noenc -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) or implicit TLS
and it is normally used with port number 465.

Similarly, when using *--server-tls-connection* the E-MailRelay server will
expect all connections to be using TLS from the start, so the whole SMTP
dialogue is encrypted, without the need for *STARTTLS*.

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

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, so run the server as *root* and also add the
*--user=root* command-line option to make sure that the process's effective
user-id stays as *root* while it accesses the PAM system.

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

On some systems interface names can be used, in which case all the addresses
associated with that interface are used for listening.

Eg:

::

    --interface eth0

The interface name can have a *-ipv4* or *-ipv6* suffix to limit the listening
addresses to one address family.

Eg:

::

    --interface eth0-ipv4

The *--interface* option can also have 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
    --interface smtp=eth0-ipv4,pop=eth1-ipv6

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 ::

Unix domain sockets
===================
E-MailRelay on Unix will listen on unix-domain sockets instead of IPv4 or IPv6
if the *--interface* option is given as an absolute file-system path:

Eg:

::

    --interface=/run/smtp.s --port=0

When listening on more than one unix-domain socket use the extended form of the
*--interface* option with a prefix of *smtp=*, *pop=*, or *admin=*:

Eg:

::

    --interface=smtp=/run/smtp.s --port=0 --interface=pop=/run/pop.s --pop --pop-port=0

The forwarding address can also be a unix-domain address:

Eg:

::

    --forward-to=/run/smtp.s

And it is also possible to communicate with message filters over a unix-domain
socket:

Eg:

::

    --filter=net:/run/filter.s
    --filter=spam:/run/spamd.s
    --filter=spam-edit:/run/spamd.s

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 as if 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 should 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 files in the spool
directory are copied to files with a *.local* filename suffix. If all the
envelope recipients are local-mailboxes then no normal message files are
created. This mechanism 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. A second output line can be used for
diagnostic information that gets put into the E-MailRelay log file.

::

    #!/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

Any other exit code, from 4 to 99 or 101 and above, behaves in the same way
as an exit code of 2.

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:<tcp-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
*0|postmaster|Local Postmaster <postmaster@eg.com>* or *2|mailbox unavailable*.

Connection blocking
===================
All incoming connections from remote network addresses are blocked by default,
but can be allowed by using the *--remote-clients*/*-r* option. This is to
guard against accidental exposure to the internet.

Incoming SMTP connections can also be checked against DNSBL blocklists in order
to block connections from known spammers. Use the *--dnsbl* option to define a
list of DNSBL servers, together with a rejection threshold. If the threshold
number of servers 'deny' the incoming connection's network address then
E-MailRelay will drop the connection immediately.

The *--dnsbl* configuration starts with the DNS server transport address and a
millisecond timeout, followed by the threshold and list of servers:

::

    emailrelay -r --dnsbl 1.1.1.1:53,500,1,spam.example.com,block.example.com ...

A threshold of zero means that the DNSBL servers are consulted but connections
are always allowed. This can be combined with verbose logging (\ *--log -v*\ )
for initial testing.

If the timeout period expires before a collective decision is reached then the
connection is allowed by default. This default behaviour can be changed by
using a negative timeout, but for finer control use a DNSBL proxy.

Connections from loopback and private (RFC-1918_) network addresses are never
checked.

Security issues
===============
The following are some security issues that have been taken into consideration:
    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.

    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.

    The program runs for most of the time with a *umask* of 077, switching to 007
    when creating spool files.

    By default connections will be rejected if they come from remote machines.

    No configuration parameters can be changed through the administrative
    interface.

    No exec(), system() or popen() calls are used other than execve() to spawn the
    mail filter and/or address verifier.

    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 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).

    The *--anonymous* option can be used to reduce the amount of information
    leaked to remote clients.

    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 *forward* command is used to trigger the E-MailRelay server into forwarding
spooled mail to the next SMTP server.

The *flush* command is similar but it uses its own connection to the SMTP
server and waits for the messages to be sent.

The *unfail-all* command can be used to remove the *.bad* filename extension
from files in the spool directory.

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.

Routing
=======
E-MailRelay does not normally do any routing of e-mail messages; they are
all forwarded to a fixed *smarthost* address given by the *--forward-to* or
*--as-client* command-line options.

However, each message envelope file contains a *ForwardToAddress* field that
can be populated by filter scripts in order to route the message to some other
server.

If the *ForwardTo* field has any non-empty value then E-MailRelay runs its
client filter early to allow the client filter script to set or update the
*ForwardToAddress* before the outgoing connection is made. (The client filter is
run a second time as normal once the connection is made and the SMTP session has
been established.)

Typically a *--filter* script would be used to examine the message content and
populate the *ForwardTo* field, then a *--client-filter* script would use
the *ForwardTo* value to populate the *ForwardToAddress* field with an up-to-date
forwarding address.

Note that a successful connection to the smarthost is required even if a message
is routed elsewhere.

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\>
* --localedir=\<dir\>
* e_bsdinitdir=\<dir\>
* e_docdir=\<dir\>
* e_examplesdir=\<dir\>
* e_icondir=\<dir\>
* e_trdir=\<dir\>
* e_initdir=\<dir\>
* e_libexecdir=\<dir\>
* e_pamdir=\<dir\>
* e_spooldir=\<dir\>
* e_sysconfdir=\<dir\>
* e_rundir=\<dir\>
* e_systemddir=\<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 File Hierarchy
Standard (FHS_) use this configure command:

::

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

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 change the default spool directory path built into the
scripts and executables so the correct spool directory will then 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.





.. _DNSBL: https://en.wikipedia.org/wiki/DNSBL
.. _FHS: https://wiki.linuxfoundation.org/lsb/fhs
.. _MTA: https://en.wikipedia.org/wiki/Message_transfer_agent
.. _PAM: https://en.wikipedia.org/wiki/Linux_PAM
.. _POP: https://en.wikipedia.org/wiki/Post_Office_Protocol
.. _RFC-1891: https://tools.ietf.org/html/rfc1891
.. _RFC-1918: https://tools.ietf.org/html/rfc1918
.. _RFC-2821: https://tools.ietf.org/html/rfc2821
.. _RFC-3461: https://tools.ietf.org/html/rfc3461
.. _RFC-4013: https://tools.ietf.org/html/rfc4013
.. _RFC-822: https://tools.ietf.org/html/rfc822
.. _SMTP: https://en.wikipedia.org/wiki/Simple_Mail_Transfer_Protocol
.. _SOCKS: https://en.wikipedia.org/wiki/SOCKS
.. _TLS: https://en.wikipedia.org/wiki/Transport_Layer_Security

.. footer:: Copyright (C) 2001-2022 Graeme Walker
