Sendmail is complicated software, no doubt about it. But sendmail is also the Swiss Army Knife of mail servers, and I don't mean one of those little key-chain trinkets. Instead, it's the monster three-inch wide kind with all the tools, most of which you have never seen before and have no idea what they do. However, with a little time and patience, you too can become proficient enough with sendmail to make it accomplish everything you need.
This article will help you understand the most useful of the tools that sendmail gives you and will serve as a companion to the article titled Setting Up a Site Server with Jaguar by filling in the sendmail configuration issues that we touched on there.
Here's what I'll cover in this article:
Be warned, this is not a beginner's article. If you're uncomfortable performing shell commands as root on your system with sudo and editing files with vi, emacs, or pico, then there is a high likelihood that you'll get a bit lost here. However, if you do have a bit of shell experience, and I haven't scared you off by mentioning the word emacs, then this should be just the quick reference guide you need.
The number one "trick" to setting up sendmail on Mac OS X is dealing with the way that Apple has configured the permissions on the various directories on the filesystem. You see, in its quest to make Unix more "Mac like," Apple decided that it would be best to allow users, at least administrative users, to be able to move files in and out of the root directory with impunity. Apparently Apple doesn't want users to see a "You can't drag that file here!" dialog box.
This clashes heavily with sendmail's built-in paranoia. You see sendmail really wants any directory that it is involved with to be only modifiable by the root user. This includes the '/' and '/Users' directories. It will complain bitterly and refuse to startup with a statement that looks something like the following:
/etc/mail/sendmail.cf: line 93: fileclass: cannot open '/etc/mail/local-host-names': Group writable directory
There are two primary solutions to this problem:
'/' and '/Users' directories to something that sendmail prefers (ie, `chmod g-w / /Users').In Setting Up a Site Server with Jaguar, I gave the recommendation to use the first of these solutions. I instructed readers to change the ownership, edit the sendmail startup script to make sure that these permissions are correct on system startup, and even add a cron job that fires every hour to make sure that things stay right even if a system update changes things back.
I'll go on the record right now and confess that this is an extreme solution. It is, as Chuq Von Rospach (who has many moons of experience working with sendmail) wrote to me in an email "Using a machine gun on a mosquito." I wholeheartedly agree with him, but it the absolute safest way to set your server up. It is the correct solution for the paranoid system-administrator who wants to make sure that nobody, not even any of his users, can compromise the system. It does have the side affect that nobody, not even the administrator, will be able to use the Finder to copy files into the '/' and '/Users' directories.
On the other hand, as long as you trust every person you
give a user account to (or at least every user that you allow to administer
your machine), there is a better way to go about this. This is to use the DontBlameSendmail
configuration parameter with sendmail. Think of it as the administration of a
small amount of medication to sendmail to reassure it that not everything in
the world is a risk.
After debating the point with Chuq (as well as thinking about it a while), I've decided that using DontBlameSendmail is good enough for my server and me. As to which you should do: consider your situation. If you're only going to give people you trust accounts on the machine and you have a reasonable acceptance of risk, then DontBlameSendmail is the way to go. However, if you can't trust your users, or if you are maximally paranoid, then change the permissions on your directories.
If you are going to not blame sendmail, then there are two ways in which we can administer this medication. The first is to edit the /System/Library/StartupItems/Sendmail/Sendmail startup script in order to use the following commands to start up sendmail:
/usr/sbin/sendmail -OdontBlameSendmail=GroupWritableDirPathSafe -bd -q1h
/usr/sbin/sendmail -OdontBlameSendmail=GroupWritableDirPathSafe -C /etc/mail/submit.cf -q1h
This does a pretty good job. However, some of the other commands that you will find yourself working with will still complain about group writable directories if you do this. A better way is to modify the configuration files in the /etc/mail directory that sendmail uses. Before we do that though, we have to take a look at how to work with sendmail's configuration files.
|
As soon as you decide to work with sendmail's configuration files, you'll find out that there is a lot of confusing stuff in there.
Take a look at the /etc/mail/sendmail.cf file. The first thing you see is a header that says:
##### DO NOT EDIT THIS FILE! Only edit the source .mc file.
Scroll down a bit further and you'll see some stuff that could only be friendly looking to an old-time Perl hacker:
# hostnames ending in class P are always canonical
R$* < @ $* $=P > $* $: $1 < @ $2 $3 . > $4
R$* < @ $* $~P > $* $: $&{daemon_flags} $| $1 < @ $2 $3 > $4
R$* CC $* $| $* < @ $+.$+ < $* $: $3 < @ $4.$5 . > $6
R$* CC $* $| $* $: $3
# pass to name server to make hostname canonical
R$* $| $* < @ $* > $* $: $2 < @ $[ $3 $] > $4
R$* $| $* $: $2
So, if you're not supposed to edit this file, and really
wouldn't want to even if you should, what are you supposed to do? The answer is
to ignore it. Treat it like a binary file. You don't muck about in the /bin/sh executable to use it do you? Take the same approach to /etc/mail/sendmail.cf.
Instead, we're going to see how to edit the source code for
this file. Take a look at the /usr/share/sendmail/conf/cf/generic-darwin.mc file. The body of it looks like this:
VERSIONID(`$Id: generic-darwin.mc,v 1.3 2002/04/12 18:41:47 bbraun Exp $')
OSTYPE(darwin)dnl
DOMAIN(generic)dnl
undefine(`ALIAS_FILE')
define(`PROCMAIL_MAILER_PATH',`/usr/bin/procmail')
FEATURE(`smrsh',`/usr/libexec/smrsh')
FEATURE(local_procmail)
FEATURE(`virtusertable',`hash -o /etc/mail/virtusertable')dnl
FEATURE(`genericstable', `hash -o /etc/mail/genericstable')dnl
FEATURE(`mailertable',`hash -o /etc/mail/mailertable')dnl
FEATURE(`access_db')dnl
MAILER(smtp)
MAILER(procmail)
This is much more approachable than sendmail.cf ever could be. This is actually a script written in the m4 macro language. m4 has been around for a while and Mac OS X ships with GNU m4 version 1.4. Luckily, it is simple enough to use without having to learn much about it. If you are interested in learning more, see the GNU m4 project page.
So, this is the source code we'll use to configure sendmail. Let's make a copy of it and put it into a place where we will remember where it is:
% sudo cp /usr/share/sendmail/conf/cf/generic-darwin.mc /etc/mail/config.mc
We now have a copy of the source code for the sendmail.cf file in a place where we can edit it and keep track of where it is. However, even if you have a copy of the source code, you still have to know how to compile the file. In our case, the set of commands to compile the config.mc file to sendmail.cf looks something like:
m4 /usr/share/sendmail/conf/m4/cf.m4 /etc/mail/config.mc > /tmp/sendmail.cf
mv /etc/mail/sendmail.cf /etc/mail/sendmail.cf.old
mv /tmp/sendmail.cf /etc/mail/sendmail.cf
Yikes! That's too much to remember. It goes against my philosophy of keeping things as simple as possible (without being too simple that is!). Luckily, I've written a little script that should help this part of working with sendmail's configuration files, as well as some of the others.
The following script will compile config.mc into sendmail.cf and restart sendmail so that it will notice the configuration changes. You can put it anywhere you want, I happen to have placed my copy in the /etc/mail folder so that I can find it easily. Fire up your editor of choice and cut-and-paste this in. Then, if you want to mirror what I've done, save it to /etc/mail/update. Otherwise, you might want to save it as /usr/local/bin/sendmail-update or some other fairly easy to remember location.
#! /bin/sh
if [ /etc/mail/config.mc -nt /etc/mail/sendmail.cf ]
then
echo Regenerating sendmail.cf
m4 /usr/share/sendmail/conf/m4/cf.m4 /etc/mail/config.mc > \
/tmp/sendmail.cf
mv /etc/mail/sendmail.cf /etc/mail/sendmail.cf.old
mv /tmp/sendmail.cf /etc/mail/sendmail.cf
/System/Library/StartupItems/Sendmail/Sendmail restart
fi
We're going to add a bit more to this script later. But for now, we're ready to feed sendmail a little anti-paranoia medicine.
|
In order to use the DontBlameSendmail configuration parameter with sendmail, all we need to do is add one line to the config.mc file.
Edit it to match the following. The line you need to add is bold-faced.
% sudo emacs /etc/mail/config.mc
VERSIONID(`$Id: generic-darwin.mc,v 1.3 2002/04/12 18:41:47 bbraun Exp $')
OSTYPE(darwin)dnl
DOMAIN(generic)dnl
undefine(`ALIAS_FILE')
define(`PROCMAIL_MAILER_PATH',`/usr/bin/procmail')
define(`confDONT_BLAME_SENDMAIL', `GroupWritableDirPathSafe')
FEATURE(`smrsh',`/usr/libexec/smrsh')
FEATURE(local_procmail)
FEATURE(`virtusertable',`hash -o /etc/mail/virtusertable')dnl
FEATURE(`genericstable', `hash -o /etc/mail/genericstable')dnl
FEATURE(`mailertable',`hash -o /etc/mail/mailertable')dnl
FEATURE(`access_db')dnl
MAILER(smtp)
MAILER(procmail)
Be careful to note that the quoting around the values use both the ` and ' characters around the arguments to the define statement.. Save the file. Next we need to compile it. Execute your update script. You may need to remember to give it execute permissions (`chmod g+x /etc/mail/update') first!
% sudo ./update
Regenerating sendmail.cf
Restarting mail services
That's all you need to do. If you followed my previous advice in Setting Up a Site Server with Jaguar and sendmail is already running, then you can remove the `chmod g-w / /Users' line in the /System/Library/StartupItems/Sendmail/Sendmail script. Be sure to edit the root crontab entry as well.
If you didn't and don't have sendmail running, just execute the system startup script with the start argument:
% sudo /System/Library/StartupItems/Sendmail/Sendmail start
Also, If you haven't already done so, be sure to edit /etc/hostconfigto have sendmail startup when the system starts. If you can't remember how to do this, refer back to the Setting Up a Site Server).
Some of the Apple documentation on sendmail (notably, the /etc/mail/README file) implies that it's a good idea to set a few properties in NetInfo to ensure that the sendmail binary reads its configuration from /etc/mail/sendmail.cf. So far, I've not had a problem with this, but in the interest of making sure that we don't get bit by a modified sendmail binary from Apple in the future, we should go ahead and execute the commands that will modify the netinfo database:
% sudo niutil -create . /locations/sendmail
% sudo niutil -createprop . /locations/sendmail sendmail.cf /etc/mail/sendmail.cf
Now, we are going to take a look at several other features that you can tweak and the various results they have.
|
The next setting we are going to look at is the LUSER_RELAY. No, this doesn't mean a way to deal with those 14 year old kids who hold their hands up to their foreheads saying "loooooos-errrr", but instead is a way of handling email that comes to your server that is not addressed to any user. The LUSER_RELAY setting will direct any piece of mail to your server without a user to a particular user's account.
This is particularly handy when you want to be able to hand out lots of different addresses, such as im-a-geek@myhost.com and spam-target@myhost.com, without having to set up anything on your server. I personally use this feature all the time when giving my email address out to stores that I'm interested in getting email from, but fear that they will sell the address off or pummel me with too much information later.
So, to set this up, simply edit the config.mc file as follows (the bold line is the line where you will add-replace duncan with the name
of the local user you want to get the mail!):
% sudo emacs /etc/mail/config.mc
VERSIONID(`$Id: generic-darwin.mc,v 1.3 2002/04/12 18:41:47 bbraun Exp $')
OSTYPE(darwin)dnl
DOMAIN(generic)dnl
undefine(`ALIAS_FILE')
define(`PROCMAIL_MAILER_PATH',`/usr/bin/procmail')
define(`confDONT_BLAME_SENDMAIL', `GroupWritableDirPathSafe')
define(`LUSER_RELAY', `local:duncan')
FEATURE(`smrsh',`/usr/libexec/smrsh')
FEATURE(local_procmail)
FEATURE(`virtusertable',`hash -o /etc/mail/virtusertable')dnl
FEATURE(`genericstable', `hash -o /etc/mail/genericstable')dnl
FEATURE(`mailertable',`hash -o /etc/mail/mailertable')dnl
FEATURE(`access_db')dnl
MAILER(smtp)
MAILER(procmail)
Now, just run the update script:
% sudo ./update
Regenerating sendmail.cf
Restarting mail services
Try things out. Use your mail client to send mail to all sorts of addresses on your machine that don't exist. When you get tired of getting mail from one of your addresses, use procmail to filter it out. You can read more about how to use procmail in Dru Lavigne's article (Filtering Spam with Procmail). Procmail is already installed and ready to go on your system - all you need to do is define a ~/.procmailrc file. Or if you don't want to do that, you can use the filtering capabilities of your mail client to filter out unwanted email.
Our next stop on the tour is to look at aliases. An alias lets you define that mail to an address actually gets sent to somebody else. That other person might be a user on the local machine or might be an email address on a completely different system.
If you were observant while editing the config.mc file, you'll have noticed the undefine(`ALIAS_FILE') statement. To enable aliases, we'll need to edit this line to match the following:
% sudo emacs /etc/mail/config.mc
VERSIONID(`$Id: generic-darwin.mc,v 1.3 2002/04/12 18:41:47 bbraun Exp $')
OSTYPE(darwin)dnl
DOMAIN(generic)dnl
define(`ALIAS_FILE', `/etc/mail/aliases')
define(`PROCMAIL_MAILER_PATH',`/usr/bin/procmail')
define(`confDONT_BLAME_SENDMAIL', `GroupWritableDirPathSafe')
define(`LUSER_RELAY', `local:duncan')
FEATURE(`smrsh',`/usr/libexec/smrsh')
FEATURE(local_procmail)
FEATURE(`virtusertable',`hash -o /etc/mail/virtusertable')dnl
FEATURE(`genericstable', `hash -o /etc/mail/genericstable')dnl
FEATURE(`mailertable',`hash -o /etc/mail/mailertable')dnl
FEATURE(`access_db')dnl
MAILER(smtp)
MAILER(procmail)
Remember to run the update script:
% sudo ./update
Regenerating sendmail.cf
Restarting mail services
Now, we'll set up some aliases. The format of the aliases file is simple. Each line in the file is composed of a local address name followed by one or more local or remote addresses to send the message to. For example, my aliases file might look something like the following:
% sudo emacs /etc/mail/aliases
root: duncan
friend: someone@somewhere.com
party: duncan, john@doe.com
The first line routes mail to root@host to user duncan. The second routes mail from afriend@host to someone@somewhere.com. The third routes mail from party@host to user duncan and to john@doe.com.
In order to get sendmail to use these,aliases we need to execute the newaliases command.
% sudo newaliases
/etc/mail/aliases: 3 aliases, longest 26 bytes, 68 bytes total
This command compiles the aliases into a database file, /etc/mail/aliases.db. Sendmail does this for performance reasons -- on a low volume site, the additional overhead of parsing a text file would be negligible, but sendmail runs some of the largest mail systems on the Internet. Under heavy load, this little tweak matters a great deal.
You can add as many lines to this file as you want. Use aliases to create group mailing lists, lists for work teams, or just lists to arrange parties.
Oh, and one thing to keep in mind: Sendmail is compiled so that it will look in NetInfo (under the /aliases folder) for aliases, then the /etc/mail/aliases file. If there is an alias defined in NetInfo, it will mask an alias by the same name in /etc/mail/aliases.
|
Sendmail doesn't like to relay mail that isn't sent from trusted sources. The designers of sendmail do this purposefully to try to alleviate the problem of spam. You see, spammers take advantage of mail servers that will relay mail from anyone in order to send mail to all of us while taking advantage of somebody else's bandwidth costs. It's truly heinous.
By default, sendmail's paranoia means that when we set up a server, we can only relay mail through it that originates on the local machine. In order to use it as a proper mail server, we need to let it know what hosts to trust to relay mail. For example, my mail sever is configured to accept email that comes from my private home network that is running behind a NAT with a fixed IP address. In addition, I always want to be able to send mail, using my laptop, from my friends houses which have known DSL hostnames. To do this, you simply need to define these rules in the /etc/mail/access file, as shown:
% sudo emacs /etc/mail/access
192.168.123.2 RELAY
dsl-1-1-1-1.networkprovider.net RELAY
You can also allow blocks of IP addresses or partial domain addresses to relay through your server. For example, to allow anybody on a subnet, as well as let everybody at the oreilly.com domain use my mail server, I could edit this file to look like:
% sudo emacs /etc/mail/access
192.168.123.2 RELAY
dsl-1-1-1-1.networkprovider.net RELAY
192.168.145 RELAY
oreilly.com RELAY
This will let anyone with an IP address that starts with 192.168.145, or whose IP address resolves to the oreilly.com domain use our server. Just like with aliases, we need to compile this file into a form that sendmail can use. To do this, use the following command:
% sudo makemap hash /etc/mail/access < /etc/mail/access
Yes, this is yet another command to remember and I personally always have to look it up to use it. Don't fear, we can fix this problem.
Since I hate having to use the documentation to execute what should be simple commands, I have actually added all these commands (and more) to my update script. I gave you the short form earlier. Here's the long form (with the section we haven't seen before in bold type):
#! /bin/sh
if [ /etc/mail/config.mc -nt /etc/mail/sendmail.cf ]
then
echo Regenerating sendmail.cf
m4 /usr/share/sendmail/conf/m4/cf.m4 /etc/mail/config.mc > \
/tmp/sendmail.cf
mv /etc/mail/sendmail.cf /etc/mail/sendmail.cf.old
mv /tmp/sendmail.cf /etc/mail/sendmail.cf
/System/Library/StartupItems/Sendmail/Sendmail restart
fi
if [ /etc/mail/aliases -nt /etc/mail/aliases.db ]
then
echo Updating aliases
newaliases
fi
if [ /etc/mail/access -nt /etc/mail/access.db ]
then
echo Updating access
makemap hash /etc/mail/access < /etc/mail/access
fi
In short, this file checks to see if it should:
sendmail.cf file.When the source to any of these files is out of date, it will be updated. Easy huh? Now, all we have to do is remember to run update whenever we edit one of the configuration files and the right thing will happen.
Running sendmail behind a firewall, especially if it's a NAT, can confuse it. You see, sendmail does its best to try to figure out what its host name is. As long as your machine is a first class citizen on the Internet (ie, has an IP address visible from the Internet at large), it can usually do a good job at this. However, when you are running behind a NAT, or if your IP address doesn't resolve to any hostname, you'll need to give sendmail a little help. For example, if you are hosting mail for domain.com, you need to tell sendmail that its domain name is $w.domain.com. The $w part is an important part of sendmail trickery that means "insert the local host name here."
To configure sendmail to use a specific domain name, edit your /etc/mail/config.mc file as follows:
% sudo emacs /etc/mail/config.mc
VERSIONID(`$Id: generic-darwin.mc,v 1.3 2002/04/12 18:41:47 bbraun Exp $')
OSTYPE(darwin)dnl
DOMAIN(generic)dnl
undefine(`ALIAS_FILE')
define(`PROCMAIL_MAILER_PATH',`/usr/bin/procmail')
define(`confDONT_BLAME_SENDMAIL', `GroupWritableDirPathSafe')
define(`LUSER_RELAY', `local:duncan')
define(`confDOMAIN_NAME', `$w.domain.com')
FEATURE(`smrsh',`/usr/libexec/smrsh')
FEATURE(local_procmail)
FEATURE(`virtusertable',`hash -o /etc/mail/virtusertable')dnl
FEATURE(`genericstable', `hash -o /etc/mail/genericstable')dnl
FEATURE(`mailertable',`hash -o /etc/mail/mailertable')dnl
FEATURE(`access_db')dnl
MAILER(smtp)
MAILER(procmail)
As always, remember to run the update script:
% sudo ./update
Regenerating sendmail.cf
Restarting mail services
Next we'll take a look at one other common problem that people have that is introduced by their ISP.
What do I mean by "Lame ISPs?" Well, I mean those ISPs that block all outgoing traffic on port 25. Instead of letting you have access to the Internet on port 25, they want you to use their own mail server. They do this to try to stop spammers from utilizing open relays on their networks. However, this means that your mail server can't send mail to other hosts on the Internet.
Luckily, since sendmail is the swiss army knife of mail servers, there is a configuration directive to fix this. To have all mail from your server go through your ISP's mail server, edit your /etc/mail/config.mc file to match the following:
% sudo emacs /etc/mail/config.mc
VERSIONID(`$Id: generic-darwin.mc,v 1.3 2002/04/12 18:41:47 bbraun Exp $')
OSTYPE(darwin)dnl
DOMAIN(generic)dnl
undefine(`ALIAS_FILE')
define(`PROCMAIL_MAILER_PATH',`/usr/bin/procmail')
define(`confDONT_BLAME_SENDMAIL', `GroupWritableDirPathSafe')
define(`LUSER_RELAY', `local:duncan')
define(`confDOMAIN_NAME', `$w.domain.com')
define(`SMART_HOST' `mail.mindspring.com')
FEATURE(`smrsh',`/usr/libexec/smrsh')
FEATURE(local_procmail)
FEATURE(`virtusertable',`hash -o /etc/mail/virtusertable')dnl
FEATURE(`genericstable', `hash -o /etc/mail/genericstable')dnl
FEATURE(`mailertable',`hash -o /etc/mail/mailertable')dnl
FEATURE(`access_db')dnl
MAILER(smtp)
MAILER(procmail)
Once again, run the update script:
% sudo ./update
Regenerating sendmail.cf
Restarting mail services
Problem solved.
I've taken you on a whirlwind tour of the major configuration areas of sendmail. To be sure, there is more, quite a bit more, than I could cover in this article. However, after reading this piece, you should have a start on being self-sufficient with sendmail. And when you need to do more, be sure to get sendmail, 2nd Edition by Bryan Costales and Eric Allman. There's a reason it's over a thousand pages long! Also, there's a 3rd edition in the works. Look for it in a few months.
James Duncan Davidson is a freelance author, software developer, and consultant focusing on Mac OS X, Java, XML, and open source technologies. He currently resides in San Francisco, California.
Return to the Mac DevCenter.
Copyright © 2009 O'Reilly Media, Inc.