Copying all messages with Sendmail

Using the Synonym mail filter ("milter"), it is possible to make a copy of all messages sent and received by a Sendmail mail server. Synonym has other uses, but in this example, we will copy every message sent and received by our Sendmail server to a local user named mailcopy using procmail as the Mail Delivery Agent (MDA). procmail provides incredible flexibility in handling the copied messages as shown in the example ~mailcopy/.procmailrc below.

Install Synonym

The following steps show how to install the Synonym 0.4-1 milter with Sendmail 8.13.1 on a Solaris 2.6 system. These steps should also work with other Sendmail versions that support milter and other Solaris versions.

1. Install the libiconv, libxml2, make, and procmail packages from Sunfreeware.

2. Build and install libmilter.a and the libmilter include files.
cd $SENDMAIL_SOURCE_TREE/libmilter
./Build install

3. Extract the Synonym archive.
synonym-0.4-1.tar.gz | tar xvf -

4. Build Synonym. Make sure to use GNU make in /usr/local/bin instead of /usr/ccs/bin/make.
make

5. Install Synonym.
cp synonym /usr/local/sbin

6. Create a Synonym startup/shutdown script and /etc/rc.d links. In this example, I place Synonym's configuration file in /etc/mail and run Synonym as user daemon in the background.

vi /etc/init.d/synonym


#!/bin/sh

case $1 in
   'start' )
      # Increase file descriptor limit to 1024
      ulimit -Sn 1024
      LD_LIBRARY_PATH=/usr/local/lib /usr/local/sbin/synonym \
         -c /etc/mail/synonym.conf -d -u daemon
      ;;
   'stop' )
      kill `ps -ef | grep [s]ynonym | awk '{print $2}'` > /dev/null 2>&1
      [ -f /var/run/synonym/synonym.pid ] && rm /var/run/synonym/synonym.pid
      ;;
   *)
   echo "usage: $0 {start|stop}"
esac

If you do not increase the file descriptor limit for the Synonym milter, you may encounter errors when the milter reaches the file descriptor limit:

Dec 16 10:58:01 mail_server Synonym[16007]: Synonym: thread_create() failed: 11, try again
Dec 16 10:58:02 mail_server Synonym[16007]: Synonym: thread_create() failed: 11, try again
Dec 16 10:58:04 mail_server Synonym[16007]: Synonym: thread_create() failed: 11, try again
Dec 16 10:58:22 mail_server Synonym[16007]: Synonym: thread_create() failed: 11, try again
Dec 16 10:58:23 mail_server Synonym[16007]: Synonym: thread_create() failed: 11, try again
Dec 16 10:58:35 mail_server Synonym[16007]: Synonym: thread_create() failed: 11, try again
Dec 16 10:58:36 mail_server Synonym[16007]: Synonym: thread_create() failed: 11, try again

# /usr/proc/bin/pfiles 16007

3314:   /usr/local/bin/perl /usr/local/bin/sendmail-milter-spf-1.41.pl -T daem
  Current rlimit: 64 file descriptors

Create /etc/rc.d links.

ln -s /etc/init.d/synonym /etc/rc2.d/S99synonym
ln -s /etc/init.d/synonym /etc/rc1.d/K58synonym

7. Create a Synonym process ID and socket directory.
mkdir /var/run/synonym
chown daemon:daemon /var/run/synonym

8. Start Synonym.
/etc/init.d/synonym start

9. Configure Sendmail to use the Synonym milter and procmail MDA.
cd $SENDMAIL_SOURCE_TREE/cf/cf

Add the following to sendmail.mc:

FEATURE(local_procmail)dnl
define(`_FFR_MILTER', `true')

INPUT_MAIL_FILTER(`Synonym', `S=local:/var/run/synonym/synonym.sock, T=C:10m;S:1s;R:1s;E:5m')dnl

10. Build and install the sendmail.cf file.
./Build install-cf

Configure Synonym

Here is an example synonym.conf file that copies every message containing a "From" header (this should be every message sent and received by the server) to the local user mailcopy:

<Rules>
        <Rule>
                <Condition>
                        <Header>From</Header>
                        <Match>.*</Match>
                </Condition>
                <Action>
                        <ActionType>Copy</ActionType>
                        <Address>mailcopy</Address>
                </Action>
        </Rule>
</Rules>

Configure mailcopy user

In this example, we will create a local user named mailcopy. Since we are using the procmail MDA, here is an example ~mailcopy/.procmailrc:

MAILDIR=$HOME
FORMAIL=/usr/local/bin/formail

# Copy monitored addresses to abuse@example.com
:0 c
* ^(From|To).*brandonhutchinson@hotmail\.com
{
   # Prevent mail loops
   :0
   * ^X-Loop
   /dev/null

   # Copy each message to "monitored" directory
   :0 c
   monitored

   # Add an "X-Loop" header to prevent milter mail loops and mail a copy of the message to abuse@example.com
   :0
   | $FORMAIL -I "X-Loop: Synonym" | mailx -s "Monitored email" abuse@example.com
}

# Copy messages from example.com containing attachments
# to attachments sub-directory for attachment report processing
:0
* ^From.*example\.com
{
   :0 B
   * filename=
   attachments
}

# Discard all other messages
:0
*
/dev/null

Start Synonym

1. Start the Synonym daemon.
/etc/init.d/synonym start

2. Send Sendmail a SIGHUP to begin using Synonym with Sendmail.
kill -HUP `head -n1 /etc/mail/sendmail.pid`

Back to brandonhutchinson.com.
Last modified: 12/16/2004