The emailrelay program supports the following command-line usage:
emailrelay [<option> [<option> ...]]
where <option> is:
Under Windows there are a few minor differences. Use --help --verbose to see the complete list.
Mail messages are stored as text files in the configured spool directory. Each 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 RFC822 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:
If a message cannot be forwarded the envelope file is given a .bad suffix, and the failure reason is written into the file.
Spooled messages can be forwarded at various times, depending on the command-line options:
These modes of operation can be mixed, although more than one --poll option is not allowed.
When using --as-client the spooled messages begin to be forwarded as soon as the program starts up, and the program terminates once they have all been sent.
A pending --poll timer can be forced to expire immediately if a --filter script exits with a special value of 103, as described below.
All receipent addresses must be accepted by the remote server when E-MailRelay forwards a 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.
The --filter command-line option allows you to specify a mail pre-processor program which operates on mail messages as they pass through the E-MailRelay system. The mail pre-processor program is run as soon as the 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 10025 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=10025 --no-syslog \ --filter=$HOME/myfilter --spool-dir=$HOME/spool
The pre-processor 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 107 are reserved for special processing: 100 is used to cancel all further processing of the message, and 103 has the effect of immediately expiring any --poll timer.
If the pre-processor 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 << or [[ followed by >> or ]] respectively. The text in between is taken as a failure reason, and passed back to the SMTP client.
The pre-processor program can edit any part of the message's envelope file or content file: E-MailRelay remembers nothing about the message while the pre-processor is running except the filename. But if the message is deleted by the pre-processor then E-MailRelay may be upset, so to avoid the error message use an exit code of 100.
If the pre-processor program creates completely new 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 --poll option, or run emailrelay --as-client from within the pre-processor program.
As an example of a simple pre-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 cat "${content}" | /usr/sbin/sendmail -t 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 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 pre-processor programs written in JavaScript can be run using cscript, with an E-MailRelay --filter option something like this:
--filter="c:/program\ files/emailrelay/filter.js"
Note how the space character in program files is escaped with a backslash.
Example --filter scripts are included in the distribution, including emailrelay-process.sh which does rot-13 masking of messages. This script also does some simple MIME encoding, so that the masked message appears as an attachment within a plaintext bearer message.
E-MailRelay also has a --client-filter option that enables pre-processing of messages just before they are forwarded, rather then 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 applications using --filter is more useful. The special exit code of 100 can be used to ignore the current message, and 102 to stop looking for spooled messages after processing the current one.
Bear in mind the following points when writing --filter programs:
It is also possible to do message pre-processing in a separate process by using net:<address>:<port> 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. One advantage of using a network pre-processor compared to running a program is that the E-MailRelay server is not blocked while the messages are being pre-processed.
E-MailRelay supports the SMTP AUTH extension, as defined in RFC2554, on both the server-side and client-side.
The authentication mechanisms currently supported are:
Authentication is enabled with the --client-auth and --server-auth command-line options and the option's parameter is the name of a secrets file, containing usernames and passwords:
emailrelay --as-server --server-auth=/etc/emailrelay-clients.auth emailrelay --as-client=myisp.net:smtp --client-auth=/etc/emailrelay-myisp.auth
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:
The mechanism field must be LOGIN, APOP or CRAM-MD5 (case-insensitive); the client-or-server field must be client or server (also case-insensitive); the userid field is xtext-encoded user identifier; and the secret field is the xtext-encoded LOGIN password, or the CRAM-MD5 digest key.
The xtext encoding scheme is defined properly in RFC1891, but basically it says that non alphanumeric characters, space, + and = should be represented in hexadecimal ascii as +XX.
The client-side secrets file specified with --client-auth is used when E-MailRelay acts as a client to talk to a remove server. The file should contain at least one client LOGIN or client CRAM-MD5 entry.
A 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 LOGIN or server CRAM-MD5 entries, one for each client.
The same secrets file may be specified for both --client-auth and --server-auth options.
The CRAM-MD5 keys can be generated using the emailrelay-passwd utility.
As an example, the following secrets file defines jsmith as the username to be used when E-MailRelay authenticates with a remote SMTP server, and defines two usernames (user1 and user2) which can be used by clients when they authenticate with the E-MailRelay server:
# # emailrelay secrets file # client LOGIN jsmith my+20password server LOGIN user1 secret server LOGIN user2 e+3Dmc2
A CRAM-MD5 version would look like this:
# # emailrelay secrets file # client CRAM-MD5 jsmith 688498119.2977922305.1278051807.3015243256.2216875978.2833592318.2902375592.3156808220 server CRAM-MD5 user1 4059553961.2316091643.3282746241.1444639637.3735501773.3404060330.2760590371.1201092398 server CRAM-MD5 user2 2798539199.3144534242.3784876256.2879973305.2327113479.216533878.2436460291.2361831919
When using the LOGIN mechanism you have to store plaintext passwords in the secrets file, so you should make sure that the secrets file has tight permissions and the passwords in it are not also used for anything important.
On the server side authentication is advertised by E-MailRealy in the response to the SMTP EHLO command if the --server-auth command-line option is used. Authentication by the client is then mandatory unless the client's IP address is configured as a trusted address.
Trusted IP addresses are configured with lines in the secrets file having NONE in the first field, server 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 --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.*; wildcarded IPv6 addresses must have the full set of 32 lowercase hex digits followed by the CIDR netmask.
For example, this secrets file allows any client connecting from the 192.168.0.0/24 domain to connect without authentication desipte the --server-auth option:
# # emailrelay secrets file # server NONE 192.168.0.* localdomain server LOGIN user1 secret server LOGIN user2 e+3Dmc2
On the client side authentication is performed when E-MailRelay has connected to a server which implements the AUTH extension with one of the supported mechanisms. If client authentication is enabled (with the --client-auth option) but the remote server does not support the AUTH extension, or does not support the LOGIN or CRAM-MD5 mechanism, then E-MailRelay will log an error and not forward any messages.
If E-MailRelay successfully authenticates with the remote server then the client's authentication name (if any) is passed as a parameter to the MAIL command when the message is forwarded. Some SMTP servers are reported to reject the message if the name on the MAIL command does not match the name used to authenticate with them. However, the name passed as a parameter to the MAIL command is stored in the message's envelope file, so a --filter script can be used to change this to match whatever the remote server expects. An example script is provided in the distribution.
Note that some ISPs require separate POP/IMAP authentication before SMTP access from a particular IP address is allowed. This type of POP-before-SMTP authentication can be done outside the E-MailRelay system by POP/IMAP utilities such as fetchmail.
E-MailRelay can use negotiated TLS/SSL to encrypt SMTP and POP3 sessions: to enable TLS/SSL encryption when E-MailRelay is acting as an SMTP client use the --client-tls command-line option, and to enable TLS/SSL when E-MailRelay is acting as an SMTP or POP3 server use --server-tls. The connections start off as unencrypted and use the STARTTLS command to negotiate TSL/SSL encryption before any plaintext passwords are exchanged.
The --server-tls option requires the name of an X.509 certificate in the PEM format. This file must be in a directory that the OpenSSL library considers to be secure. On some systems this is /etc/ssl/certs.
Certificate files can be created with the openssl utility using the req -x509 sub-command. Refer to the OpenSSL documentation for the full details but something like this might work for testing purposes:
$ cd /etc/ssl/certs $ openssl req -x509 -nodes -days 365 -subj "/O=`uname -n`/CN=$USER" -newkey rsa:1024 -keyout emailrelay.pem -out emailrelay.pem $ ln -s emailrelay.pem `openssl x509 -noout -hash -in emailrelay.pem`.0
E-MailRelay can also make outgoing SMTP connections using TLS/SSL encryption where the whole SMTP dialog is encrypted from the start, without a negotiation step (--client-tls-connection). This is sometimes called SMTP-over-TLS or secure SMTP (ssmtp) and it is normally used with port number 465.
The behaviour of the TLS/SSL layer can be tweaked by using --tls-config option with a special number that is made up of the following:
E-MailRelay 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 by E-MailRelay to authenticate SMTP and POP3 sessions 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 enable PAM authentication at run-time. 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 somthing 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, but note that on some systems this will require special permissioning to allow the E-MailRelay server to read the shadow password database.
The passwords for system accounts are usually very sensitive so E-MailRelay requires the --server-tls command-line option when using PAM authentication, and clients are required to establish a TLS/SSL session before authenticating.
E-MailRelay can use a SOCKS 4a proxy for establishing outgoing SMTP connections if the SOCKS proxy address is appended 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 server listening on port 9050:
emailrelay --forward-to myisp.net:smtp@localhost:9050 ...
In this example the target SMTP server will receive a connection from the Tor exit node rather than from E-MailRelay directly.
E-MailRelay can be used as a POP3 server so that POP clients have access to spooled messages.
The following command-line options are used:
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 --verifier command-line option, so that you get to choose which recipient addresses are accepted as valid and which are rejected.
Your verifier script is passed a command-line containing: (1) the full e-mail address as supplied by the remote client, (2) the user-name part of the address in upper-case, (3) the host-name part in upper-case, (4) the local host's fully qualified domain name in upper-case, (5) the MAIL command's FROM: address as supplied by the client or the empty string in the case of the VRFY command,
used by the client (NONE if trusted), and (8) either the authentication name or the fourth field from authentication secrets file if a trusted IP address.
So, for example, a verifier script called myverifier might be run with the following command-line:
myverifier me@myhost.mydomain ME MYHOST.MYDOMAIN MYHOST.MYDOMAIN bob@other.net 192.168.0.1 LOGIN bob
The verifier script is expected to generate two lines of output on the standard output stream and then terminate with a specific exit code.
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 script 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 adminstrative messages such as delivery reports.
For invalid addresses the exit value should be non-zero and anything written to the standard output is taken as the reason for the failure.
#!/bin/sh # address verifier -- reject as invalid (550) echo invalid address: $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 address 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 address="$1" host="$3" local_domain="$4" auth_mechanism="$7" if test -z "${auth_mechanism}" ; then auth_mechanism="NONE" ; fi 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 var address = WScript.Arguments(0) ; var host = WScript.Arguments(2) ; var local_domain = WScript.Arguments(3) ; var auth_mechanism = WScript.Arguments(6) ; 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 ) ;
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 --verifier option of the form net:<address>:<port>. 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>. The inetd super-server daemon would be a convenient way to connect up the pieces in this case.
The following are some security issues that have been taken into consideration:
Security issues which relate to the SMTP protocol itself are beyond the scope of this document, but RFC2821 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 and Linux PAM sections above also relate to security.
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 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, as an alternative to running emailrelay --as-client as a separate process. In proxy mode it is a way of getting the proxy server to scan the spool-directory for new messages.
The list command lists the messages in the spool directory, info provides network status information and activity statistics, and notify enables asynchronous event notification.
Following a normal build from source, a make install puts files in the following locations:
For finer control of the directory structure the following can be specified on the configure command-line:
For example, running ./configure --prefix=/usr e_spooldir=/tmp/spool will install to a directory structure under /usr rather than /usr/local, and create the E-MailRelay spool directory as /tmp/spool rather than /usr/local/var/spool/emailrelay.
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_init_dir=/etc/init.d
As usual, 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 option.
Copyright (C) 2001-2013 Graeme Walker <graeme_walker@users.sourceforge.net>. All rights reserved.