Sendmail

Before you begin trying to build and install the latest sendmail on CentOS or RedHat, be aware that some genius has decided that the dependencies for postfix should now include cron. This being the case, you can't install the cron daemon without postfix being present. The reason is probably that this genius has decided that cron must be able to send email if a job fails. Ain't that swell? It may be a perfectly good sentiment but it should be the user's business if they don't want email when a job fails. Its not up to the smartest people in the world to tell them how stuff must work.

Anyway, the upshot of this is that, on the surface, you cannot get rid of postfix without also getting rid of cron. But, if you are planning on building and installing sendmail, you really don't want postfix anywhere near your system. Which is unfortunate because cron is probably the most useful package that you can install on your system.

If you are using the package manager or yum, there is no way to fix this idiotic situation. The smartest people in the world know what's best for you and their package management tool is going to enforce their will. Luckily for us, we can simply use rpm to rip postscript out and ignore the misguided dependancies. So, if you find yourself in this bind, here's how to do it:

     su
     rpm -q postfix
     rpm -e --nodeps postfix-2.6.6-2.2.el6_1.i686

Use the result of the first rpm command to obtain the package name. Then, use the second rpm command to rip postfix out but leave cron on the system.

Now, on to building /usr/sbin/sendmail. To build sendmail from scratch, obtain a fresh distribution from http://www.sendmail.org/releases/. Unzip the distribution:

     tar xzvf sendmail.8.14.2.tar.gz

Create a sendmail userid and group:

     su
     /usr/sbin/groupadd -g 51 -r smmsp
     /usr/sbin/useradd -c "Sendmail MTA" -g smmsp -M -N -r \
       -s /sbin/nologin -u 51 smmsp

Then, create a "site.config.m4" file in .../devtools/Site. You can copy the sample file in that directory (but be aware that you must then select or comment out the appropriate options) or just create an empty file.

If you are planning on using a milter to filter mail, add the following line to this file:

     APPENDDEF(`conf_sendmail_ENVDEF', `-DMILTER')dnl

Also, if you don't have the Berkeley DB installed, the sendmail build screws up when using DB1 for the database. You may need the following, in the above file:

     APPENDDEF(`confMAPDEF',`-DNEWDB')dnl
     APPENDDEF(`confINCDIRS', `-I/usr/include/db1')
     APPENDDEF(`confLIBDIRS', `-ldb1')

In the top directory, run the build command:

     sh Build

Prior to doing this you may want to look at the instructions in the various README and INSTALL files (the top level INSTALL file in the install directory is a good place to start). If you add the line above to the "site.config.m4" file after the fact, rebuild sendmail with "sh Build -c"

If you need to build the milter library, switch to the libmilter directory and build "libmilter.a" by typing:

     sh Build

Building the milter library is required before the components like the sendmail filter can be built.

To install sendmail, run "sh Build install" as root in the top directory. Note that you may need to create the /usr/man directory structure on some systems to hold the sendmail man pages. The directories required are "man1", "man8" and possibly "man5" . Their permissions should be set the same as the standard man directories (e.g. /usr/share/man/manx).

You may also want to get rid of any sendmail man pages that are in the /usr/share/man tree, since these will override the true sendmail man pages that are installed by "sh Build install". The pages to delete are:

     /usr/share/man/man1/sendmail.1
     /usr/share/man/man8/mailstats.8
     /usr/share/man/man8/makemap.8
     /usr/share/man/man8/praliases.8
     /usr/share/man/man8/smrsh.8*

/etc/sendmail.cf or /etc/mail/sendmail.cf:

The sendmail configuration file is famous for being impossible to hack. Instead of hacking it, a M4 macro file (e.g. sendmail.mc) in /etc/mail, /usr/share/sendmail-cf/cf, /usr/lib/sendmail-cf/cf or the sendmail build directory .../cf/cf is hacked and then passed through the macro processor to yield /etc/sendmail.cf or /etc/mail/sendmail.cf.

The macro file should allow you to make all of the changes that you want, to the sendmail configuration, without touching sendmail.cf so no more needs to be said about how to hack sendmail.cf.

However, if you are relaying mail (via smart host) to the Cleopatra 2525 version of SMTP (at a remote ISP), because some pinhead at your local ISP decided to dump all packet traffic outbound for port 25 into the bit bucket because some other asshole was spamming them, the easy way to fix this is to hack sendmail.cf slightly. On the other hand, if you ever anticipate having to change the sendmail configuration using sendmail.mc, see the changes to /usr/share/sendmail-cf/mailer/smtp.m4, /usr/lib/sendmail-cf/mailer/smtp.m4 or in the sendmail build directory .../cf/mailer/smtp.m4 below for a much superior, alternative approach.

Having been warned about the pitfals of hacking sendmail.cf directly and having been informed about the enlightened way to do it (below), if you still feel the urge to hack sendmail.cf (e.g. to relay to Cleopatra), first build your sendmail.cf using the M4 macros below or grab a copy of the existing sendmail.cf. Then, hack all mail gateways that will be listening on port 2525 to use "smtpcleo" instead of "smtp". An example for the smart host is as follows:

     DSsmtpcleo:mail.mailgw.com

In the mailers section, add the "smtpcleo" mailer simlar to that shown (you should just copy whatever is there for the "smtp" mailer and add port 2525):

     Msmtpcleo,      P=[IPC], F=mDFMuX, S=EnvFromSMTP/HdrFromSMTP, R=EnvToSMTP,
                     E=\r\n, L=990,
                     T=DNS/RFC822/SMTP,
                     A=TCP $h 2525

In this manner, you can continue to deliver mail to other SMTPs, if any can be reached from your network (e.g. an internal server elsewhere or one reachable via a different link), while also delivering mail to unreachable servers via Cleopatra SMTP.

Similarly, if you want to use the mail redirector to send mail through your ISP but make it look like it is coming from somewhere else (e.g. to send mail through xyz.net but make it appear to be comming from abc.com), you'll, once again, need to hack sendmail.cf slightly (or see the changes to /usr/share/sendmail-cf/mailer/smtp.m4, /usr/lib/sendmail-cf/mailer/smtp.m4 or in the sendmail build directory .../cf/mailer/smtp.m4 below for a much superior, alternative approach).

First build your sendmail.cf using the M4 macros below or grab a copy of the existing sendmail.cf. Then, hack all mail gateways that will be sent through the redirector to use "smtpredir" instead of "smtp". An example for the smart host is as follows:

     DSsmtpredir:mail.mailgw.com/username

In the mailers section, add the "smtpredir" mailer simlar to that shown (you should just copy whatever is there for the "smtp" mailer and replace the "A=..." with the line shown):

     Msmtpredir,     P=/usr/sbin/SMTPRedirect, F=DFMnSu,
                     S=EnvFromSMTP/HdrFromSMTP, R=EnvToSMTP,
                     T=DNS/RFC822/SMTP,
                     A=SMTPRedirect $h $f $u

Another instance where you might want to hack the sendmail.cf file directly is to quickly turn off canonicalization of names, if you experience a problem with DNS (see the discussion below about how canonicalization is related to DNS). To stop sendmail from doing DNS lookups, one of the rules of ruleset 96 should be commented out in the sendmail.cf file.

Edit the sendmail.cf file and look for the rule in ruleset 96 that looks like this and comment it out:

     # pass to name server to make hostname canonical
     R$ $| $ < @ $ > $ $: $2 < @ $[ $3 $] > $4

In all of these examples, save the changed file and restart sendmail.

/usr/share/sendmail-cf/cf/.mc:
/usr/lib/sendmail-cf/cf/
.mc:
.../cf/cf/*.mc (in the sendmail build directory):

This file is a macro file, typically named sendmail.mc, that is used to generate sendmail.cf. Hacking this file is far and above THE preferred method for configuring sendmail, since sendmail.cf is so impossible to change. Once this file is hacked, it is passed through the M4 macro processor to yield the sendmail.cf file. The simple way to invoke the macro processor is:

     cd .../cf/cf
     /usr/bin/m4 sendmail.mc >sendmail.cf

You can use this to test your sendmail.mc file before you build it. Or, you can copy the resulting file directly to /etc/mail, if you like doing everything by hand.

To hack sendmail.mc, start by copying the canned configuration supplied with the OS. For example:

     cd /usr/share/sendmail-cf/cf

or

     cd /usr/lib/sendmail-cf/cf

or

     cd .../cf/cf
     cp redhat.mc sendmail.mc

Alternately, if you unpacked and installed a distribution of sendmail, you can build the sendmail.cf file in that directory tree instead. You should change to the directory .../sendmail-8.12.x/cf/cf (or whatever your's is called). Then, you can use the command "sh Build sendmail.cf" and copy the resulting sendmail.cf to /etc/mail by hand. To do this, you will need to copy your choice for the starting sendmail.mc to it:

     cd .../cf/cf
     cp redhat.mc sendmail.mc

or

     ln -s mysys.mc sendmail.mc

Once you've created the sendmail.mc file, you can hack it with your favorite text editor. You may specifically want to add or make the following changes. If you would like the aliases file to be in /etc/mail (with all of the other sendmail files), you should add or change:

     define(`ALIAS_FILE',`/etc/mail/aliases')dnl

For delivery of all outbound mail to Cleopatra, you should have something like this:

     define(`confDELIVERY_MODE',`interactive')dnl
     define(`SMART_HOST',`smtpcleo:mail.myisp.com')dnl
     MASQUERADE_AS(`domain1.com')dnl

Or for redirection of all outbound mail to the redirector, try this:

     define(`confDELIVERY_MODE',`interactive')dnl
     define(`SMART_HOST',`smtpredir:mail.mailgw.net/username')dnl
     MASQUERADE_AS(`domain1.com')dnl

You can supply whatever parameters the redirector needs, such as a port number, like this:

     define(`SMART_HOST',`smtpredir:mail.mailgw.net:587|user|passwd')dnl

Note that, if you will be using alternate mailers in this manner, you must add them to the smtp.m4 file (see below) before you build the sendmail.cf file.

If you wish to run the sendmail filter (checks for inbound viruses, etc.) then add the following lines:

     define(`FFRMILTER', `1')dnl
     INPUT_MAIL_FILTER(`filter1',`S=inet:2526@localhost, F=R, \
                       T=S:10s;R:60s;E:5m')dnl
     define(`confINPUT_MAIL_FILTERS',`filter1')dnl

If you will be delivering any mail to programs (e.g. mail handling robots), you should change the queueing parameters for such messages, otherwise the mail to programs can sit in a queue for up to an hour before being delivered. The following definition will change this:

     define(`LOCAL_SHELL_FLAGS', `u9')dnl

If you wish to define more than one domain as the local domain, you can do so by placing a definition for each of the additional domains, as it would appear in the sendmail.cf file, at the end of the macro file. For example:

     CNdomain2.com

If your sendmail is simply relaying mail to a mail gateway, you probably should not be trying to canoify names through DNS. Whoever you are relaying to will take care of it. Meanwhile, DNS lookups on email messages with lots of "to names" can take forever, if canonicalization is enabled, especially if your system does not provide a local or have acces to a reliable DNS bind server. This can actually result in timeouts that are problematic, for example causing fetchmail to drop messages, when it is trying to pass on messages with many "to names".

To disable canonicalization, add this feature to the sendmail.mc file along with all the other features and particularly before you define the SMART_HOST:

     FEATURE(`nocanonify')dnl

Here is an example of the complete M4 file (for relaying to Cleopatra):

     divert(-1)
     dnl This is the macro config file used to generate the /etc/sendmail.cf
     dnl file for mysys. If you modify this file you will have to regenerate
     dnl /etc/sendmail.cf by running this macro config through the m4
     dnl preprocessor:
     dnl
     dnl      m4 /usr/lib/sendmail-cf/cf/sendmail.mc > /etc/sendmail.cf
     dnl
     dnl You will need to have the sendmail-cf package installed for this to
     dnl work.
     dnl
     dnl You can do everything in one fell swoop by running:
     dnl
     dnl      /usr/lib/sendmail-cf/cf/newsendmail
     include(`../m4/cf.m4')
     VERSIONID(`linux setup for Red Hat Linux')dnl
     define(`confDEF_USER_ID',``8:12'')dnl
     OSTYPE(`linux')
     undefine(`UUCP_RELAY')dnl
     undefine(`BITNET_RELAY')dnl
     define(`confAUTO_REBUILD')dnl
     define(`confTO_CONNECT', `1m')dnl
     define(`confTRY_NULL_MX_LIST',true)dnl
     define(`confDONT_PROBE_INTERFACES',true)dnl
     define(`confDELIVERY_MODE',`interactive')dnl
     define(`PROCMAIL_MAILER_PATH',`/usr/bin/procmail')dnl
     define(`ALIAS_FILE',`/etc/mail/aliases')dnl
     define(`STATUS_FILE', `/var/log/sendmail.st')dnl
     define(`UUCP_MAILER_MAX', `2000000')dnl
     define(`confUSERDB_SPEC', `/etc/mail/userdb.db')dnl
     dnl define(`confPRIVACY_FLAGS', `authwarnings,novrfy,noexpn')dnl
     dnl define(`confTO_QUEUEWARN', `4h')dnl
     dnl define(`confTO_QUEUERETURN', `5d')dnl
     dnl define(`confQUEUE_LA', `12')dnl
     dnl define(`confREFUSE_LA', `18')dnl
     define(`LOCAL_SHELL_FLAGS', `u9')dnl
     FEATURE(`smrsh',`/usr/sbin/smrsh')dnl
     FEATURE(`mailertable',`hash -o /etc/mail/mailertable')dnl
     FEATURE(`virtusertable',`hash -o /etc/mail/virtusertable')dnl
     FEATURE(redirect)dnl
     FEATURE(always_add_domain)dnl
     FEATURE(use_cw_file)dnl
     FEATURE(local_procmail)dnl
     FEATURE(`access_db')dnl
     FEATURE(`blacklist_recipients')dnl
     FEATURE(`nocanonify')dnl
     dnl We strongly recommend to comment this one out if you want to protect
     dnl yourself from spam. However, the laptop and users on computers that do
     dnl not hav 24x7 DNS do need this.
     dnl FEATURE(`accept_unresolvable_domains')
     dnl FEATURE(`relay_based_on_MX')
     define(`SMART_HOST',`smtp:mail.myisp.com')dnl
     MASQUERADE_AS(`domain1.com')dnl
     FEATURE(`masquerade_envelope')dnl
     define(RELAY_MAILER, TCP)dnl
     FEATURE(`accept_unqualified_senders')dnl
     define(`FFRMILTER', `1')dnl
     INPUT_MAIL_FILTER(`filter1',`S=inet:2526@localhost, F=R, T=S:10s;R:60s;E:5m')dnl
     define(`confINPUT_MAIL_FILTERS',`filter1')dnl
     MAILER(local)dnl
     MAILER(smtp)dnl
     MAILER(procmail)dnl
     CNdomain2.com

/usr/share/sendmail-cf/mailer/smtp.m4:
/usr/lib/sendmail-cf/mailer/smtp.m4:
.../cf/mailer/smtp.m4 (in the sendmail build directory):

If you used any alternate mailers in the sendmail.mc file (above), for example to set up relaying to Cleopatra or redirection through the redirector, you will have to hack this file to define them.

To set up relaying to Cleopatra SMTP in the sendmail.mc (above), add the following new mailer to the smtp.m4 file after the "smtp" mailer (basically, you just copy the smtp mailer and add the 2525 port number):

     Msmtpcleo,      P=[IPC], F=MODMF(CONCAT(DEFSMTP_MAILER_FLAGS,
                     SMTP_MAILER_FLAGS), `SMTP'), S=EnvFromSMTP/HdrFromSMTP,
                     R=ifdef(`ALLMASQUERADE_', `EnvToSMTP/HdrFromSMTP',
                     `EnvToSMTP'), E=\r\n, L=990,
                     OPTINS(`SMTPMAILER_MAX',
                       `M=', `, ')OPTINS(`SMTPMAILER_MAXMSGS',
                       `m=', `, ')OPTINS(`SMTPMAILER_MAXRCPTS',
                       `r=', `, ')OPTINS(`SMTPMAILER_CHARSET',
                       `C=', `, ')T=DNS/RFC822/SMTP,
                     A=SMTP_MAILER_ARGS 2525

Then, change sendmail.mc to read:

     define(`SMART_HOST',`smtpcleo:mail.myisp.com')dnl

To set up relaying to the redirector for SMTP in the sendmail.mc (above), add the following new mailer to the smtp.m4 file after the "smtp" mailer (basically, just copy whatever is there for the "smtp" mailer and replace the "A=..." with the line shown):

     Msmtpredir,     P=/usr/sbin/SMTPRedirect, F=DFMnSu,
                     S=EnvFromSMTP/HdrFromSMTP, R=ifdef(`ALLMASQUERADE_',
                       `EnvToSMTP/HdrFromSMTP', `EnvToSMTP'),
                     T=DNS/RFC822/SMTP,
                     A=SMTPRedirect $h $f $u

Then, change sendmail.mc to read something like this:

     define(`SMART_HOST',`smtpredir:mail.mailgw.com/username')dnl

/usr/lib/sendmail-cf/cf/submit.mc

Newer versions of sendmail use a second non-priviledged mail-submission program to submit mail for delivery, thereby plugging a security hole. They use a second config file called submit.cf. This file is built by the macro file submit.mc, which embeds sendmail.mc.

So, beware of two things. One is to make sure that sendmail.mc is either the correct file for building your sendmail.cf or that it is symlinked to the correct file. The other is to make sure that submit.cf is built (e.g. "sh Build submit.cf") and copied to /etc/mail.

Another is that some versions of submit.mc file put the PID file in the queue directory instead of /var/run. You might want to change the default location for the PID file to /var/run so that the standard startup script will be able find sm-client and start/stop it properly. Add the following line:

     define(`confPID_FILE', `/var/run/sm-client.pid')dnl

Also, some later versions of sendmail and/or combinations of certain versions of Unix have problems setting the permissions when submit runs so that non-root users can submit mail. This problem manifests itself by displaying the following message when non-root users try to use "mail" to send mail locally:

     WARNING: RunAsUser for MSP ignored, check group ids (egid=51, want=12)
       can not write to queue directory /var/spool/clientmqueue/
       (RunAsGid=0, required=51): Permission denied

Although the submit.cf file correctly has:

     # what user id do we assume for the majority of the processing?
     O RunAsUser=smmsp

And, all of the permissions on the client mail queue are correct but the problem still persists.

Apparently, submit is trying to look up the group permissions to use for the submit operation, based on the username. However, this fails and the group permissions (which are needed to access the client mail queue) are not set correctly. Consequently, the submit fails.

The solution is to change RunAsUser to:

     # what user id do we assume for the majority of the processing?
     O RunAsUser=smmsp:smmsp

This can be done by adding the following lines to the end of submit.mc:

     dnl
     dnl Fix a bug in later versions of submit that don't set the group properly
     dnl from the RunAs username.
     define(`confRUN_AS_USER', `smmsp:smmsp')dnl

/etc/mail/sendmail.cf or submit.cf:

As mentioned above, if you are building sendmail from scratch in a source directory tree, you can build and install the sendmail.cf and submit.cf files using the following commands:

     cd .../cf/cf
     sh Build sendmail.cf
     sh Build submit.cf
     su
     sh Build install-cf

Otherwise, you want sendmail.cf and submit.cf to end up in the /etc/mail directory so copy them there by hand:

     su
     cd .../cf/cf
     cp sendmail.cf /etc/mail
     cp submit.cf /etc/mail

/etc/mail/aliases or /etc/aliases (on older systems):

Aliases for mail delivery on this system. Probably all we care about is to get all mail being sent to root. Here's the clip from /etc/aliases:

.

       .
  # Person who should get root's mail
  root:              joeblow

Run /usr/bin/newaliases to rebuild the alias file, once it is changed. Or, if you use the /etc/init.d/sendmail startup script that we show below, the rebuild will be done automatically at startup.

/etc/mail/relay-domains:

A list of domains from which sendmail will relay (i.e. accept) messages.

Add your local machines to the list of domains. For example:

     stargate.homeworld
     gabriella.homeworld
     clara-bow.homeworld
     phoebe.homeworld

Or, alternately, you can allow hosts based on IP addresses:

     # Allow all local machines to relay
     192.168

/etc/mail/local-host-names:

With later versions of sendmail, this is a list of local host/domain names that will be considered as local to the machine running sendmail. Any mail to a user in these domains will be delivered to same user locally. For example:

     mydomain.com
     myotherdomain.com

/etc/mail/access:

Since sendmail already uses /etc/mail/relay-domains to control who can relay mail, why not have a second control method? Why not indeed. This is the purpose of /etc/mail/access.db. To be the belt and suspenders too. You'd like to use just one method but sendmail won't deliver local mail without the /etc/mail/access.db database. So, you must create the file /etc/mail/access and then build the database.

We populate /etc/mail/access like this:

     # Check the /usr/share/doc/sendmail/README.cf file for a description
     # of the format of this file. (search for access_db in that file)
     # The /usr/share/doc/sendmail/README.cf is part of the sendmail-doc
     # package.
     #
     # by default we allow relaying from localhost...
     localhost.localdomain           RELAY
     localhost                       RELAY
     127.0.0.1                       RELAY

The access.db map file is built from this file automagically by the startup script, /etc/rc.d/init.d/sendmail, that we show below. Set the permissions on the access file like so:

     su
     chown root:root /etc/mail/access
     chmod u=rw,g=r,o= /etc/mail/access

/etc/mail/domaintable:
/etc/mail/mailertable:
/etc/mail/virtusertable:

These three files are used to build the map files that sendmail uses to check domains and mailers, and implement virtual users. Normally, you won't need any of these so just use touch to create empty files:

     su
     touch /etc/mail/domaintable
     touch /etc/mail/mailertable
     touch /etc/mail/virtusertable
     chown root:root /etc/mail/table
     chmod u=rw,g=r,o= /etc/mail/table

/etc/sendmail.cw (earlier versions of sendmail use this instead):

The name of any domains, such that any mail directed to them is actually local. DNS lookup won't be done on the domain name and mail will be delivered directly to the user on this machine.

Add your domain name to this list. For example:

     # sendmail.cw - include all aliases for your machine here.
     domain1.com

/var/spool/mqueue:

For some reason, sendmail can create the files and directories that it needs (such as /var/spool/clientmqueue) but not /var/spool/mqueue. This leaves it to us to create the directory by hand, before sendmail is run. The sendmail install documentation suggests that this directory should be solely owned by root but we prefer root:smmsp. If you set the permissions like this, it seems to work:

     su
     mkdir -p /var/spool/mqueue
     chown root:smmsp /var/spool/mqueue
     chmod ug=rwx,o= /var/spool/mqueue

Alternately, if you prefer to go with sendmail's advice, set the permissions like this:

     su
     mkdir -p /var/spool/mqueue
     chown root:root /var/spool/mqueue
     chmod u=rwx,go= /var/spool/mqueue

/var/spool/clientmqueue:

While we're at it, the clientmqueue directory usually is created by the sendmail install but, even when it is, it appears sometimes to be created with the wrong permissions. We check that it is indeed created and that the permissions are properly set like this:

     su
     mkdir -p /var/spool/clientmqueue
     chown smmsp:smmsp /var/spool/clientmqueue
     chmod ug=rwx,o= /var/spool/clientmqueue

/usr/adm/sm.bin (RedHat):
/usr/lib/sendmail.d/bin (SuSE):

Create this directory and give it permissions of root/root/755. Put soft links to any programs which will be executed by a .forward file. Be careful. Read "man smrsh" for more information.

Note: the sendmail documentation claims that only programs in this directory can be executed in a .forward file and that it matters not what the actual path of the program is called. This is bullshit. Sendmail checks the path that is mentioned in the .forward file to see if the program exists and fails if it does not. Not only that but the symlinked name of the program in this directory must be the same as the name of the actual progam. For example:

     /usr/adm/sm.bin/myprog.pl -> /usr/local/myprograms/myprog.pl  (symlink)
     |"/usr/local/myprograms/myprog.pl"  (.forward)

Do not try anything clever like this:

     /usr/adm/sm.bin/myprog -> /usr/local/myprograms/myprog.pl  (symlink)

or this:

     |"myprog.pl"  (.forward)

~/.forward:

The .forward file is placed in the user's home directory. Any mail that is to be delivered to the user is instead forwarded according to the rules found in the .forward file. The permissions of the .forward file should be set to:

     -rw-------   1 joeuser joeuser    161 Aug 24  2010 .forward

Be sure that ownership is given to the user, as shown above. Sendmail will access this file as the user. If they don't have permissions to this file, you will see a message in /var/log/maillog that reads something like this:

     Sep 28 23:30:02 mtabox sendmail[1234]: s8T3U2Hx013969: forward 
       /home/joeuser/.forward: Permission denied

If you wish to deliver mail to a mail robot program, you will first need to add the program to the sendmail permissions directory (see above). Once you've done that, make sure you can execute the program using the symlink in the permissions directory. The executable and all of the directories, files, etc. that it uses must be available to the user whom the mail is being forwarded from. Sendmail runs everything setuid to the user. Make sure all of this works because you don't get any error messages, it just fails to send the message.

You may include anything in the .forward file that you would include in the aliases file (see "man aliases" for more information). However, care must be taken to avoid alias loops so one significant divergence from the format of the aliases file is that usernames may be prefixed with '\' to inhibit further aliasing. Its a good idea, unless you specifically want the forwarded mail to go to an alias, to always use the '\' on user names.

In general, you will probably want to forward mail to another user or a program. If you have an account that you rarely use and want to see its mail under another account, try this:

     \otheruser

If you want to send mail to a mail robot program, try this:

     "|/usr/local/myprograms/mailrobot --options"

Note the use of the double quotes around the entire command line for the robot. These are very important. You may specify options, etc. along with the program name, if you wish, but always use the quotes.

You can also send mail to a user and a program. For example, the vacation program does this:

     \thisuser, "|/usr/bin/vacation thisuser"

Getting .forward files to work is often a whole lot of grief but if you follow these simple rules you should be fine. Otherwise, if you experience the following errors, they usually mean what is shown:

     Error 127 - Sendmail couldn't find the program being forwarded to, the
                 program has the wrong permissions or the name in the .forward
                 file doesn't match the name in the permissions directory or the
                 path/filename given doesn't exist (even though the program is
                 supposed to be looked up in the permissions directory).

/etc/init.d/sendmail:

Here is a new and improved startup script for sendmail. It will rebuild the sendmail configuration files, if they exist and then it will start sendmail. Next, it will start the sendmail filter and the sendmail client queue runner. If you don't need the filter, you can turn it off in /etc/sysconfig/sendmail.

The clamav and spamassassin configurations are also used to decide whether the filter should use clamd and spamd for virus and spam scanning.

     #!/bin/bash
     #
     # sendmail - Shell script to take care of starting and stopping sendmail.
     #
     # chkconfig: 2345 80 30
     # description: Sendmail is a Mail Transport Agent, which is the program \
     #              that moves mail from one machine to another.
     #
     # processname: sendmail
     # pidfile: /var/run/sendmail.pid
     # config: /etc/mail/sendmail.cf
     #
     #
     # Define the install path for the sendmail binaries, etc.  Define the
     # programs to run.
     #
     INSTALL_PATH="/usr/sbin"
     CONFIG_PATH="/etc/mail"
     MTA_PROG="sendmail"
     FILTER_PROG="sendmailfilter"
     #
     # Load the functions.
     #
     if [ -f /etc/init.d/functions ] ; then
         . /etc/init.d/functions
     fi
     #
     # Source the networking configuration.
     #
     if [ -f /etc/sysconfig/network ] ; then
         . /etc/sysconfig/network
     else
         NETWORKING=no
     fi
     #
     # Source the sendmail configuration or take the defaults.
     #
     if [ -f /etc/sysconfig/sendmail ] ; then
         . /etc/sysconfig/sendmail
     else
         DAEMON=no
         QUEUE=1h
         FILTER=no
     fi
     [ -z "$SMQUEUE" ] && SMQUEUE="$QUEUE"
     [ -z "$SMQUEUE" ] && SMQUEUE=1h
     if [ "x$FILTER" == xyes ] ; then
         [ -z "$FILTER_OPTIONS" ] && FILTER_OPTIONS="-h -i -k -p24 -s1 -t -um"
         [ -z "$FILTER_PORT" ] && FILTER_PORT=2526
     fi
     #
     # Source the clamd configuration.  If it exists, it turns on filtering using
     # clamd.
     #
     if [ -f /etc/sysconfig/clamd ] ; then
         . /etc/sysconfig/clamd
         [ -z "$CLAMD_PORT" ] && CLAMD_PORT=2528
     fi
     #
     # Source the spamd configuration.  If it exists, it turns on filtering using
     # spamd.
     #
     if [ -f /etc/sysconfig/spamd ] ; then
         . /etc/sysconfig/spamd
         [ -z "$SPAMD_PORT" ] && SPAMD_PORT=783
     fi
     #
     # Check that networking is up.
     #
     [ "x$NETWORKING" != xyes ] && exit 0
     #
     # Make sure we have something to run.
     #
     [ -f $INSTALL_PATH/$MTA_PROG ] || exit 0
     RETVAL=0
     #
     # Upon startup, first start sendmail.
     #
     # Then, start the sendmail filter, if we were asked to do so.
     #
     start()
         {
         #
         # As a favor to the world, rebuild the various databases that sendmail
         # uses as configuration files.
         #
         echo -n $"Rebuilding the $MTA_PROG config tables: "
      /usr/bin/newaliases >/dev/null 2>&1
      if test -x /usr/bin/make -a -f $CONFIG_PATH/Makefile ; then
          make -C $CONFIG_PATH -s
      else
          for i in virtusertable access domaintable mailertable ; do
              if [ -f $CONFIG_PATH/$i ] ; then
                  makemap hash $CONFIG_PATH/$i < $CONFIG_PATH/$i
              fi
          done
      fi
      echo [ DONE ]
      #
      # Start sendmail.
      #
      echo -n $"Starting $MTA_PROG: "
      daemon $INSTALL_PATH/$MTA_PROG $([ "x$DAEMON" == xyes ] && echo -bd) \
          $([ -n "$QUEUE" ] && echo -q$QUEUE)
      RETVAL=$?
      echo
      [ $RETVAL -eq 0 ] && touch /var/lock/subsys/sendmail
      #
      # Start the mail filter
      #
      if [ "x$FILTER" == xyes ] ; then
          if [ -x $INSTALL_PATH/$FILTER_PROG ] ; then
              echo -n $"Starting $FILTER_PROG: "
                  $([ "x$FILTER_STRACE" != x ] && echo -e \
                      "/usr/bin/strace $FILTER_STRACE" ) \
                  $INSTALL_PATH/$FILTER_PROG -A $CONFIG_PATH/aliases \
                      $([ "x$FILTER_DOMAINS" != x ] && echo -e \
                          "-D \"$FILTER_DOMAINS\"" ) \
                      $FILTER_OPTIONS \
                      $([ "x$FILTER_PORT" != x ] && echo -e \
                          "-p inet:${FILTER_PORT}@localhost" ) \
                      $([ "x$CLAMD_PORT" != x ] && echo -e \
                          "-v clamd:${CLAMD_PORT}@localhost" ) \
                      $([ "x$SPAMD_PORT" != x ] && echo -e \
                          "-s spamd:${SPAMD_PORT}@localhost" ) \
                      $FILTER_DEBUG >/dev/null 2>&1 &
              FILTVAL=$?
              [ $FILTVAL -eq 0 ] && success "sendmailfilter startup" \
                  || failure "sendmailfilter startup"
              echo
          else
              echo -n $"Starting $FILTER_PROG, bypassed: "
              failure "sendmailfilter startup"
              echo
          fi
      fi
      #
      # Start the sendmail client, if not already running.
      #
      if ! test -f /var/run/sm-client.pid ; then
          echo -n $"Starting $MTA_PROG client: "
          touch /var/run/sm-client.pid
          chown smmsp:smmsp /var/run/sm-client.pid
          daemon --check sm-client $INSTALL_PATH/$MTA_PROG -L sm-msp-queue \
              -Ac -q$SMQUEUE
          RETVAL=$?
          echo
          [ $RETVAL -eq 0 ] && touch /var/lock/subsys/sm-client
      fi
      return $RETVAL
      }

#
# Upon shutdown, do everything in reverse (except the client is shut down # last).
#
stop()

      {
      #
      # Shut down the sendmail client.
      #
      # Note that, most of the time, the sendmail client doesn't exist so the
      # call to killproc fails.  We don't really want to see any whining so we
      # send the results to the bit bucket.
      #
      if test -f /var/run/sm-client.pid ; then
          echo -n $"Shutting down $MTA_PROG client: "
          killproc sm-client >/dev/null 2>&1
          RETVAL=$?
          echo "[  OK  ]"
          [ $RETVAL -eq 0 ] && rm -f /var/run/sm-client.pid
          [ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/sm-client
      fi
      #
      # Stop the daemons.  Sendmail requires a big hammer.
      #
      if [ "x$FILTER" == xyes ] ; then
          echo -n $"Shutting down $FILTER_PROG: "
          killproc $FILTER_PROG
          echo
      fi
      echo -n $"Shutting down $MTA_PROG: "
      killproc $MTA_PROG
      RETVAL=$?
      echo
      killproc $MTA_PROG >/dev/null 2>&1
      [ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/sendmail
      return $RETVAL
      }

#
# See how we were called.
#
case "$1" in

      #
      # Start.
      #
      start)
          start
          RETVAL=$?
          ;;
      #
      # Stop.
      #
      stop)
          stop
          RETVAL=$?
          ;;
      #
      # Restart or reload (whatever).
      #
      restart|reload)
          stop
          start
          RETVAL=$?
          ;;
      #
      # Conditional restart.
      #
      condrestart)
          if [ -f /var/lock/subsys/sendmail ] ; then
              stop
              start
              RETVAL=$?
          fi
          ;;
      #
      # Give the status of all of the sendmail components that are running.
      #
      status)
          status $MTA_PROG
          RETVAL=$?
          if [ "x$FILTER" == xyes ] ; then
              status $FILTER_PROG
          fi
          ;;
      #
      # Help text.
      #
      *)
          echo $"Usage: $0 {start|stop|restart|condrestart|status}"
          exit 1

esac

     exit $RETVAL

/etc/sysconfig/sendmail:

If you use the above startup script, you will need to either create or update /etc/sysconfig/sendmail. This file contains the options that tell sendmail how to run. By default, the startup script runs sendmail once and then has it exit. This probably not what you intended. Rather you probably want it to run as a daemon. So, set /etc/sysconfig/sendmail to at least the following options:

     DAEMON=yes
     QUEUE=1h

You may also want to set some of the filtering options such as

     FILTER=yes
     FILTER_DOMAINS=
     FILTER_OPTIONS=
     FILTER_PORT=2526

The permissions on this file should be:

     -rw-r--r--    1 root     root

Here is a sample of the complete file:

     #
     # Configuration for sendmail and its various filters and classifiers.
     #
     # Sendmail parameters.
     #
     # Daemonize and set the queue interval to one hour.
     #
     DAEMON=yes
     QUEUE=1h
     #
     # Filter parameters.
     #
     # Yes, we want filtering.
     #
     FILTER=yes
     #
     # Local domains.
     #
     FILTER_DOMAINS="192.168.1.0/24,stargate.homeworld"
     #
     # Filtering options.
     #
     FILTER_OPTIONS="-h -i -k -p24 -s1 -t -um"
     #
     # Sendmail port (as set in the sendmail config file)
     #
     FILTER_PORT=2526
     #
     # Debugging options.
     #
     FILTER_DEBUG="-d /var/log/sendmailfilter -d3"
     #
     # Strace options.  Set this parameter to cause the filter to be run with
     # strace so that system call problems, etc. can be debugged.  If non-blank,
     # the options specified will be passed to strace and tracing will be enabled.
     #
     # FILTER_STRACE="-f -ff -o /var/log/smfstrace"